A new set of wireless changes:
* validate key indices for key deletion * more preamble support in mac80211 * various 6 GHz scan fixes/improvements * a common SAR power limitations API * various small fixes & code improvements -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAl/TfYAACgkQB8qZga/f l8ShjQ/9Hd6KjvA7keATtdjR7rDHo7H2nBKV/LukpuHsiTRrXTVOAfkcUTOb2hfR 7SJMzsUXdJGivbwm4lkx5TrIgiJm1hfW3zG0PFOs/bIuXs/KICrb+kLgQWiRIUfa RIinf8BGPH3GgcCHDcWFUrnfnBVchrPUx2wIHoCQbCzLHIhB6q6x8jEJA67+smpv 57tDfUhm6pf6OYOqVN8HYlo0uRAIn1ImneplDelCmCI1dzlneEkMhqZuBXqWpD/I C5vU+MjoOsJiW1XkmYOMe6VKQ/Bve06GUWs830S7aROOEfByv+ptlR9IjqvHvPIm UI9NivfXQiZr6S7yD1m2xV7a14UMCIzYarwaM/I/NHAWF/Y4vzHFVzQjLfVKqMCV dxxsWN+Yg7Gx3T5Fj3NNiQgnPF9ASVqgMrlC59ga+4If0y60V7dOSFuo9HF7AWgP NIWKVI3He7Mb5TciM+BX5YQWkJiCSZXs427WLO6p0bp3kAgS6N6BThUraGCogXVF 1BT/y5G3QzZwg02vL3lxgWglXoH/e63UYCPt0r+i5c83Z+n4YnFSUZyRSViy9Elj DkCgdxmP0OtM+FaHxLdYm+FL4GXaGWQVNORIDP0ViSrstPgSxhWIgVj/pKNcKC7g bJI/IXm7eQkW5SXOafmhVV0TmvDOt/mM46E0CeWcPTqIhetk3lM= =+qd6 -----END PGP SIGNATURE----- Merge tag 'mac80211-next-for-net-next-2020-12-11' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next Johannes Berg says: ==================== A new set of wireless changes: * validate key indices for key deletion * more preamble support in mac80211 * various 6 GHz scan fixes/improvements * a common SAR power limitations API * various small fixes & code improvements * tag 'mac80211-next-for-net-next-2020-12-11' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next: (35 commits) mac80211: add ieee80211_set_sar_specs nl80211: add common API to configure SAR power limitations mac80211: fix a mistake check for rx_stats update mac80211: mlme: save ssid info to ieee80211_bss_conf while assoc mac80211: Update rate control on channel change mac80211: don't filter out beacons once we start CSA mac80211: Fix calculation of minimal channel width mac80211: ignore country element TX power on 6 GHz mac80211: use bitfield helpers for BA session action frames mac80211: support Rx timestamp calculation for all preamble types mac80211: don't set set TDLS STA bandwidth wider than possible mac80211: support driver-based disconnect with reconnect hint cfg80211: support immediate reconnect request hint mac80211: use struct assignment for he_obss_pd cfg80211: remove struct ieee80211_he_bss_color nl80211: validate key indexes for cfg80211_registered_device cfg80211: include block-tx flag in channel switch started event mac80211: disallow band-switch during CSA ieee80211: update reduced neighbor report TBTT info length cfg80211: Save the regulatory domain when setting custom regulatory ... ==================== Link: https://lore.kernel.org/r/20201211142552.209018-1-johannes@sipsolutions.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
00f7763a26
@ -1261,6 +1261,7 @@ struct ieee80211_mgmt {
|
||||
#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
|
||||
#define BSS_MEMBERSHIP_SELECTOR_VHT_PHY 126
|
||||
#define BSS_MEMBERSHIP_SELECTOR_HE_PHY 122
|
||||
#define BSS_MEMBERSHIP_SELECTOR_SAE_H2E 123
|
||||
|
||||
/* mgmt header + 1 byte category code */
|
||||
#define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u)
|
||||
@ -3835,15 +3836,15 @@ static inline bool for_each_element_completed(const struct element *element,
|
||||
#define WLAN_RSNX_CAPA_SAE_H2E BIT(5)
|
||||
|
||||
/*
|
||||
* reduced neighbor report, based on Draft P802.11ax_D5.0,
|
||||
* section 9.4.2.170
|
||||
* reduced neighbor report, based on Draft P802.11ax_D6.1,
|
||||
* section 9.4.2.170 and accepted contributions.
|
||||
*/
|
||||
#define IEEE80211_AP_INFO_TBTT_HDR_TYPE 0x03
|
||||
#define IEEE80211_AP_INFO_TBTT_HDR_FILTERED 0x04
|
||||
#define IEEE80211_AP_INFO_TBTT_HDR_COLOC 0x08
|
||||
#define IEEE80211_AP_INFO_TBTT_HDR_COUNT 0xF0
|
||||
#define IEEE80211_TBTT_INFO_OFFSET_BSSID_BSS_PARAM 8
|
||||
#define IEEE80211_TBTT_INFO_OFFSET_BSSID_SSSID_BSS_PARAM 12
|
||||
#define IEEE80211_TBTT_INFO_OFFSET_BSSID_BSS_PARAM 9
|
||||
#define IEEE80211_TBTT_INFO_OFFSET_BSSID_SSSID_BSS_PARAM 13
|
||||
|
||||
#define IEEE80211_RNR_TBTT_PARAMS_OCT_RECOMMENDED 0x01
|
||||
#define IEEE80211_RNR_TBTT_PARAMS_SAME_SSID 0x02
|
||||
|
@ -137,6 +137,17 @@ void rfkill_unregister(struct rfkill *rfkill);
|
||||
*/
|
||||
void rfkill_destroy(struct rfkill *rfkill);
|
||||
|
||||
/**
|
||||
* rfkill_set_hw_state_reason - Set the internal rfkill hardware block state
|
||||
* with a reason
|
||||
* @rfkill: pointer to the rfkill class to modify.
|
||||
* @blocked: the current hardware block state to set
|
||||
* @reason: one of &enum rfkill_hard_block_reasons
|
||||
*
|
||||
* Prefer to use rfkill_set_hw_state if you don't need any special reason.
|
||||
*/
|
||||
bool rfkill_set_hw_state_reason(struct rfkill *rfkill,
|
||||
bool blocked, unsigned long reason);
|
||||
/**
|
||||
* rfkill_set_hw_state - Set the internal rfkill hardware block state
|
||||
* @rfkill: pointer to the rfkill class to modify.
|
||||
@ -156,7 +167,11 @@ void rfkill_destroy(struct rfkill *rfkill);
|
||||
* should be blocked) so that drivers need not keep track of the soft
|
||||
* block state -- which they might not be able to.
|
||||
*/
|
||||
bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked);
|
||||
static inline bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked)
|
||||
{
|
||||
return rfkill_set_hw_state_reason(rfkill, blocked,
|
||||
RFKILL_HARD_BLOCK_SIGNAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* rfkill_set_sw_state - Set the internal rfkill software block state
|
||||
@ -256,6 +271,13 @@ static inline void rfkill_destroy(struct rfkill *rfkill)
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool rfkill_set_hw_state_reason(struct rfkill *rfkill,
|
||||
bool blocked,
|
||||
unsigned long reason)
|
||||
{
|
||||
return blocked;
|
||||
}
|
||||
|
||||
static inline bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked)
|
||||
{
|
||||
return blocked;
|
||||
|
@ -302,19 +302,6 @@ struct cfg80211_he_bss_color {
|
||||
bool partial;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ieee80211_he_bss_color - AP settings for BSS coloring
|
||||
*
|
||||
* @color: the current color.
|
||||
* @disabled: is the feature disabled.
|
||||
* @partial: define the AID equation.
|
||||
*/
|
||||
struct ieee80211_he_bss_color {
|
||||
u8 color;
|
||||
bool disabled;
|
||||
bool partial;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ieee80211_sta_ht_cap - STA's HT capabilities
|
||||
*
|
||||
@ -1187,6 +1174,7 @@ enum cfg80211_ap_settings_flags {
|
||||
* @vht_required: stations must support VHT
|
||||
* @twt_responder: Enable Target Wait Time
|
||||
* @he_required: stations must support HE
|
||||
* @sae_h2e_required: stations must support direct H2E technique in SAE
|
||||
* @flags: flags, as defined in enum cfg80211_ap_settings_flags
|
||||
* @he_obss_pd: OBSS Packet Detection settings
|
||||
* @he_bss_color: BSS Color settings
|
||||
@ -1218,7 +1206,7 @@ struct cfg80211_ap_settings {
|
||||
const struct ieee80211_vht_cap *vht_cap;
|
||||
const struct ieee80211_he_cap_elem *he_cap;
|
||||
const struct ieee80211_he_operation *he_oper;
|
||||
bool ht_required, vht_required, he_required;
|
||||
bool ht_required, vht_required, he_required, sae_h2e_required;
|
||||
bool twt_responder;
|
||||
u32 flags;
|
||||
struct ieee80211_he_obss_pd he_obss_pd;
|
||||
@ -1744,6 +1732,54 @@ struct station_info {
|
||||
u8 connected_to_as;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cfg80211_sar_sub_specs - sub specs limit
|
||||
* @power: power limitation in 0.25dbm
|
||||
* @freq_range_index: index the power limitation applies to
|
||||
*/
|
||||
struct cfg80211_sar_sub_specs {
|
||||
s32 power;
|
||||
u32 freq_range_index;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cfg80211_sar_specs - sar limit specs
|
||||
* @type: it's set with power in 0.25dbm or other types
|
||||
* @num_sub_specs: number of sar sub specs
|
||||
* @sub_specs: memory to hold the sar sub specs
|
||||
*/
|
||||
struct cfg80211_sar_specs {
|
||||
enum nl80211_sar_type type;
|
||||
u32 num_sub_specs;
|
||||
struct cfg80211_sar_sub_specs sub_specs[];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @struct cfg80211_sar_chan_ranges - sar frequency ranges
|
||||
* @start_freq: start range edge frequency
|
||||
* @end_freq: end range edge frequency
|
||||
*/
|
||||
struct cfg80211_sar_freq_ranges {
|
||||
u32 start_freq;
|
||||
u32 end_freq;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cfg80211_sar_capa - sar limit capability
|
||||
* @type: it's set via power in 0.25dbm or other types
|
||||
* @num_freq_ranges: number of frequency ranges
|
||||
* @freq_ranges: memory to hold the freq ranges.
|
||||
*
|
||||
* Note: WLAN driver may append new ranges or split an existing
|
||||
* range to small ones and then append them.
|
||||
*/
|
||||
struct cfg80211_sar_capa {
|
||||
enum nl80211_sar_type type;
|
||||
u32 num_freq_ranges;
|
||||
const struct cfg80211_sar_freq_ranges *freq_ranges;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_CFG80211)
|
||||
/**
|
||||
* cfg80211_get_station - retrieve information about a given station
|
||||
@ -4261,6 +4297,8 @@ struct cfg80211_ops {
|
||||
struct cfg80211_tid_config *tid_conf);
|
||||
int (*reset_tid_config)(struct wiphy *wiphy, struct net_device *dev,
|
||||
const u8 *peer, u8 tids);
|
||||
int (*set_sar_specs)(struct wiphy *wiphy,
|
||||
struct cfg80211_sar_specs *sar);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -5029,6 +5067,8 @@ struct wiphy {
|
||||
|
||||
u8 max_data_retry_count;
|
||||
|
||||
const struct cfg80211_sar_capa *sar_capa;
|
||||
|
||||
char priv[] __aligned(NETDEV_ALIGN);
|
||||
};
|
||||
|
||||
@ -6418,13 +6458,15 @@ void cfg80211_abandon_assoc(struct net_device *dev, struct cfg80211_bss *bss);
|
||||
* @dev: network device
|
||||
* @buf: 802.11 frame (header + body)
|
||||
* @len: length of the frame data
|
||||
* @reconnect: immediate reconnect is desired (include the nl80211 attribute)
|
||||
*
|
||||
* This function is called whenever deauthentication has been processed in
|
||||
* station mode. This includes both received deauthentication frames and
|
||||
* locally generated ones. This function may sleep. The caller must hold the
|
||||
* corresponding wdev's mutex.
|
||||
*/
|
||||
void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len);
|
||||
void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len,
|
||||
bool reconnect);
|
||||
|
||||
/**
|
||||
* cfg80211_rx_unprot_mlme_mgmt - notification of unprotected mlme mgmt frame
|
||||
@ -7531,6 +7573,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
|
||||
* @dev: the device on which the channel switch started
|
||||
* @chandef: the future channel definition
|
||||
* @count: the number of TBTTs until the channel switch happens
|
||||
* @quiet: whether or not immediate quiet was requested by the AP
|
||||
*
|
||||
* Inform the userspace about the channel switch that has just
|
||||
* started, so that it can take appropriate actions (eg. starting
|
||||
@ -7538,7 +7581,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
|
||||
*/
|
||||
void cfg80211_ch_switch_started_notify(struct net_device *dev,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
u8 count);
|
||||
u8 count, bool quiet);
|
||||
|
||||
/**
|
||||
* ieee80211_operating_class_to_band - convert operating class to band
|
||||
|
@ -635,9 +635,7 @@ struct ieee80211_fils_discovery {
|
||||
struct ieee80211_bss_conf {
|
||||
const u8 *bssid;
|
||||
u8 htc_trig_based_pkt_ext;
|
||||
bool multi_sta_back_32bit;
|
||||
bool uora_exists;
|
||||
bool ack_enabled;
|
||||
u8 uora_ocw_range;
|
||||
u16 frame_time_rts_th;
|
||||
bool he_support;
|
||||
@ -4197,6 +4195,8 @@ struct ieee80211_ops {
|
||||
struct ieee80211_vif *vif);
|
||||
void (*sta_set_4addr)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, bool enabled);
|
||||
int (*set_sar_specs)(struct ieee80211_hw *hw,
|
||||
const struct cfg80211_sar_specs *sar);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -5323,6 +5323,26 @@ ieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
|
||||
void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid,
|
||||
const u8 *replay_ctr, gfp_t gfp);
|
||||
|
||||
/**
|
||||
* ieee80211_key_mic_failure - increment MIC failure counter for the key
|
||||
*
|
||||
* Note: this is really only safe if no other RX function is called
|
||||
* at the same time.
|
||||
*
|
||||
* @keyconf: the key in question
|
||||
*/
|
||||
void ieee80211_key_mic_failure(struct ieee80211_key_conf *keyconf);
|
||||
|
||||
/**
|
||||
* ieee80211_key_replay - increment replay counter for the key
|
||||
*
|
||||
* Note: this is really only safe if no other RX function is called
|
||||
* at the same time.
|
||||
*
|
||||
* @keyconf: the key in question
|
||||
*/
|
||||
void ieee80211_key_replay(struct ieee80211_key_conf *keyconf);
|
||||
|
||||
/**
|
||||
* ieee80211_wake_queue - wake specific queue
|
||||
* @hw: pointer as obtained from ieee80211_alloc_hw().
|
||||
@ -5881,6 +5901,17 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif);
|
||||
*/
|
||||
void ieee80211_connection_loss(struct ieee80211_vif *vif);
|
||||
|
||||
/**
|
||||
* ieee80211_disconnect - request disconnection
|
||||
*
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
* @reconnect: immediate reconnect is desired
|
||||
*
|
||||
* Request disconnection from the current network and, if enabled, send a
|
||||
* hint to the higher layers that immediate reconnect is desired.
|
||||
*/
|
||||
void ieee80211_disconnect(struct ieee80211_vif *vif, bool reconnect);
|
||||
|
||||
/**
|
||||
* ieee80211_resume_disconnect - disconnect from AP after resume
|
||||
*
|
||||
|
@ -1178,6 +1178,10 @@
|
||||
* includes the contents of the frame. %NL80211_ATTR_ACK flag is included
|
||||
* if the recipient acknowledged the frame.
|
||||
*
|
||||
* @NL80211_CMD_SET_SAR_SPECS: SAR power limitation configuration is
|
||||
* passed using %NL80211_ATTR_SAR_SPEC. %NL80211_ATTR_WIPHY is used to
|
||||
* specify the wiphy index to be applied to.
|
||||
*
|
||||
* @NL80211_CMD_MAX: highest used command number
|
||||
* @__NL80211_CMD_AFTER_LAST: internal use
|
||||
*/
|
||||
@ -1408,6 +1412,8 @@ enum nl80211_commands {
|
||||
|
||||
NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS,
|
||||
|
||||
NL80211_CMD_SET_SAR_SPECS,
|
||||
|
||||
/* add new commands above here */
|
||||
|
||||
/* used to define NL80211_CMD_MAX below */
|
||||
@ -2079,7 +2085,8 @@ enum nl80211_commands {
|
||||
* until the channel switch event.
|
||||
* @NL80211_ATTR_CH_SWITCH_BLOCK_TX: flag attribute specifying that transmission
|
||||
* must be blocked on the current channel (before the channel switch
|
||||
* operation).
|
||||
* operation). Also included in the channel switch started event if quiet
|
||||
* was requested by the AP.
|
||||
* @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information
|
||||
* for the time while performing a channel switch.
|
||||
* @NL80211_ATTR_CNTDWN_OFFS_BEACON: An array of offsets (u16) to the channel
|
||||
@ -2534,6 +2541,15 @@ enum nl80211_commands {
|
||||
* This is a u8 attribute that encapsulates one of the values from
|
||||
* &enum nl80211_sae_pwe_mechanism.
|
||||
*
|
||||
* @NL80211_ATTR_SAR_SPEC: SAR power limitation specification when
|
||||
* used with %NL80211_CMD_SET_SAR_SPECS. The message contains fields
|
||||
* of %nl80211_sar_attrs which specifies the sar type and related
|
||||
* sar specs. Sar specs contains array of %nl80211_sar_specs_attrs.
|
||||
*
|
||||
* @NL80211_ATTR_RECONNECT_REQUESTED: flag attribute, used with deauth and
|
||||
* disassoc events to indicate that an immediate reconnect to the AP
|
||||
* is desired.
|
||||
*
|
||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
@ -3025,6 +3041,10 @@ enum nl80211_attrs {
|
||||
|
||||
NL80211_ATTR_SAE_PWE,
|
||||
|
||||
NL80211_ATTR_RECONNECT_REQUESTED,
|
||||
|
||||
NL80211_ATTR_SAR_SPEC,
|
||||
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
@ -7156,4 +7176,96 @@ enum nl80211_sae_pwe_mechanism {
|
||||
NL80211_SAE_PWE_HASH_TO_ELEMENT,
|
||||
NL80211_SAE_PWE_BOTH,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nl80211_sar_type - type of SAR specs
|
||||
*
|
||||
* @NL80211_SAR_TYPE_POWER: power limitation specified in 0.25dBm unit
|
||||
*
|
||||
*/
|
||||
enum nl80211_sar_type {
|
||||
NL80211_SAR_TYPE_POWER,
|
||||
|
||||
/* add new type here */
|
||||
|
||||
/* Keep last */
|
||||
NUM_NL80211_SAR_TYPE,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nl80211_sar_attrs - Attributes for SAR spec
|
||||
*
|
||||
* @NL80211_SAR_ATTR_TYPE: the SAR type as defined in &enum nl80211_sar_type.
|
||||
*
|
||||
* @NL80211_SAR_ATTR_SPECS: Nested array of SAR power
|
||||
* limit specifications. Each specification contains a set
|
||||
* of %nl80211_sar_specs_attrs.
|
||||
*
|
||||
* For SET operation, it contains array of %NL80211_SAR_ATTR_SPECS_POWER
|
||||
* and %NL80211_SAR_ATTR_SPECS_RANGE_INDEX.
|
||||
*
|
||||
* For sar_capa dump, it contains array of
|
||||
* %NL80211_SAR_ATTR_SPECS_START_FREQ
|
||||
* and %NL80211_SAR_ATTR_SPECS_END_FREQ.
|
||||
*
|
||||
* @__NL80211_SAR_ATTR_LAST: Internal
|
||||
* @NL80211_SAR_ATTR_MAX: highest sar attribute
|
||||
*
|
||||
* These attributes are used with %NL80211_CMD_SET_SAR_SPEC
|
||||
*/
|
||||
enum nl80211_sar_attrs {
|
||||
__NL80211_SAR_ATTR_INVALID,
|
||||
|
||||
NL80211_SAR_ATTR_TYPE,
|
||||
NL80211_SAR_ATTR_SPECS,
|
||||
|
||||
__NL80211_SAR_ATTR_LAST,
|
||||
NL80211_SAR_ATTR_MAX = __NL80211_SAR_ATTR_LAST - 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nl80211_sar_specs_attrs - Attributes for SAR power limit specs
|
||||
*
|
||||
* @NL80211_SAR_ATTR_SPECS_POWER: Required (s32)value to specify the actual
|
||||
* power limit value in units of 0.25 dBm if type is
|
||||
* NL80211_SAR_TYPE_POWER. (i.e., a value of 44 represents 11 dBm).
|
||||
* 0 means userspace doesn't have SAR limitation on this associated range.
|
||||
*
|
||||
* @NL80211_SAR_ATTR_SPECS_RANGE_INDEX: Required (u32) value to specify the
|
||||
* index of exported freq range table and the associated power limitation
|
||||
* is applied to this range.
|
||||
*
|
||||
* Userspace isn't required to set all the ranges advertised by WLAN driver,
|
||||
* and userspace can skip some certain ranges. These skipped ranges don't
|
||||
* have SAR limitations, and they are same as setting the
|
||||
* %NL80211_SAR_ATTR_SPECS_POWER to any unreasonable high value because any
|
||||
* value higher than regulatory allowed value just means SAR power
|
||||
* limitation is removed, but it's required to set at least one range.
|
||||
* It's not allowed to set duplicated range in one SET operation.
|
||||
*
|
||||
* Every SET operation overwrites previous SET operation.
|
||||
*
|
||||
* @NL80211_SAR_ATTR_SPECS_START_FREQ: Required (u32) value to specify the start
|
||||
* frequency of this range edge when registering SAR capability to wiphy.
|
||||
* It's not a channel center frequency. The unit is kHz.
|
||||
*
|
||||
* @NL80211_SAR_ATTR_SPECS_END_FREQ: Required (u32) value to specify the end
|
||||
* frequency of this range edge when registering SAR capability to wiphy.
|
||||
* It's not a channel center frequency. The unit is kHz.
|
||||
*
|
||||
* @__NL80211_SAR_ATTR_SPECS_LAST: Internal
|
||||
* @NL80211_SAR_ATTR_SPECS_MAX: highest sar specs attribute
|
||||
*/
|
||||
enum nl80211_sar_specs_attrs {
|
||||
__NL80211_SAR_ATTR_SPECS_INVALID,
|
||||
|
||||
NL80211_SAR_ATTR_SPECS_POWER,
|
||||
NL80211_SAR_ATTR_SPECS_RANGE_INDEX,
|
||||
NL80211_SAR_ATTR_SPECS_START_FREQ,
|
||||
NL80211_SAR_ATTR_SPECS_END_FREQ,
|
||||
|
||||
__NL80211_SAR_ATTR_SPECS_LAST,
|
||||
NL80211_SAR_ATTR_SPECS_MAX = __NL80211_SAR_ATTR_SPECS_LAST - 1,
|
||||
};
|
||||
|
||||
#endif /* __LINUX_NL80211_H */
|
||||
|
@ -69,6 +69,16 @@ enum rfkill_operation {
|
||||
RFKILL_OP_CHANGE_ALL,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum rfkill_hard_block_reasons - hard block reasons
|
||||
* @RFKILL_HARD_BLOCK_SIGNAL: the hardware rfkill signal is active
|
||||
* @RFKILL_HARD_BLOCK_NOT_OWNER: the NIC is not owned by the host
|
||||
*/
|
||||
enum rfkill_hard_block_reasons {
|
||||
RFKILL_HARD_BLOCK_SIGNAL = 1 << 0,
|
||||
RFKILL_HARD_BLOCK_NOT_OWNER = 1 << 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rfkill_event - events for userspace on /dev/rfkill
|
||||
* @idx: index of dev rfkill
|
||||
@ -76,6 +86,8 @@ enum rfkill_operation {
|
||||
* @op: operation code
|
||||
* @hard: hard state (0/1)
|
||||
* @soft: soft state (0/1)
|
||||
* @hard_block_reasons: valid if hard is set. One or several reasons from
|
||||
* &enum rfkill_hard_block_reasons.
|
||||
*
|
||||
* Structure used for userspace communication on /dev/rfkill,
|
||||
* used for events from the kernel and control to the kernel.
|
||||
@ -84,7 +96,9 @@ struct rfkill_event {
|
||||
__u32 idx;
|
||||
__u8 type;
|
||||
__u8 op;
|
||||
__u8 soft, hard;
|
||||
__u8 soft;
|
||||
__u8 hard;
|
||||
__u8 hard_block_reasons;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
|
@ -250,10 +250,10 @@ static void ieee80211_send_addba_resp(struct sta_info *sta, u8 *da, u16 tid,
|
||||
mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP;
|
||||
mgmt->u.action.u.addba_resp.dialog_token = dialog_token;
|
||||
|
||||
capab = (u16)(amsdu << 0); /* bit 0 A-MSDU support */
|
||||
capab |= (u16)(policy << 1); /* bit 1 aggregation policy */
|
||||
capab |= (u16)(tid << 2); /* bit 5:2 TID number */
|
||||
capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */
|
||||
capab = u16_encode_bits(amsdu, IEEE80211_ADDBA_PARAM_AMSDU_MASK);
|
||||
capab |= u16_encode_bits(policy, IEEE80211_ADDBA_PARAM_POLICY_MASK);
|
||||
capab |= u16_encode_bits(tid, IEEE80211_ADDBA_PARAM_TID_MASK);
|
||||
capab |= u16_encode_bits(buf_size, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
|
||||
|
||||
mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab);
|
||||
mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout);
|
||||
|
@ -95,10 +95,10 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
|
||||
mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ;
|
||||
|
||||
mgmt->u.action.u.addba_req.dialog_token = dialog_token;
|
||||
capab = (u16)(1 << 0); /* bit 0 A-MSDU support */
|
||||
capab |= (u16)(1 << 1); /* bit 1 aggregation policy */
|
||||
capab |= (u16)(tid << 2); /* bit 5:2 TID number */
|
||||
capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */
|
||||
capab = IEEE80211_ADDBA_PARAM_AMSDU_MASK;
|
||||
capab |= IEEE80211_ADDBA_PARAM_POLICY_MASK;
|
||||
capab |= u16_encode_bits(tid, IEEE80211_ADDBA_PARAM_TID_MASK);
|
||||
capab |= u16_encode_bits(agg_size, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
|
||||
|
||||
mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab);
|
||||
|
||||
@ -950,8 +950,8 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
|
||||
|
||||
capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
|
||||
amsdu = capab & IEEE80211_ADDBA_PARAM_AMSDU_MASK;
|
||||
tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
|
||||
buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
|
||||
tid = u16_get_bits(capab, IEEE80211_ADDBA_PARAM_TID_MASK);
|
||||
buf_size = u16_get_bits(capab, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
|
||||
buf_size = min(buf_size, local->hw.max_tx_aggregation_subframes);
|
||||
|
||||
txq = sta->sta.txq[tid];
|
||||
|
@ -405,6 +405,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
if (WARN_ON_ONCE(fips_enabled))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
case WLAN_CIPHER_SUITE_CCMP_256:
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
@ -1121,10 +1122,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||
sdata->vif.bss_conf.enable_beacon = true;
|
||||
sdata->vif.bss_conf.allow_p2p_go_ps = sdata->vif.p2p;
|
||||
sdata->vif.bss_conf.twt_responder = params->twt_responder;
|
||||
memcpy(&sdata->vif.bss_conf.he_obss_pd, ¶ms->he_obss_pd,
|
||||
sizeof(struct ieee80211_he_obss_pd));
|
||||
memcpy(&sdata->vif.bss_conf.he_bss_color, ¶ms->he_bss_color,
|
||||
sizeof(struct ieee80211_he_bss_color));
|
||||
sdata->vif.bss_conf.he_obss_pd = params->he_obss_pd;
|
||||
sdata->vif.bss_conf.he_bss_color = params->he_bss_color;
|
||||
sdata->vif.bss_conf.s1g = params->chandef.chan->band ==
|
||||
NL80211_BAND_S1GHZ;
|
||||
|
||||
@ -3297,6 +3296,7 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
if (cfg80211_get_chandef_type(¶ms->chandef) !=
|
||||
cfg80211_get_chandef_type(&sdata->u.ibss.chandef))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_5:
|
||||
case NL80211_CHAN_WIDTH_10:
|
||||
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||
@ -3448,7 +3448,7 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
|
||||
cfg80211_ch_switch_started_notify(sdata->dev, &sdata->csa_chandef,
|
||||
params->count);
|
||||
params->count, params->block_tx);
|
||||
|
||||
if (changed) {
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
@ -4073,6 +4073,17 @@ static int ieee80211_reset_tid_config(struct wiphy *wiphy,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ieee80211_set_sar_specs(struct wiphy *wiphy,
|
||||
struct cfg80211_sar_specs *sar)
|
||||
{
|
||||
struct ieee80211_local *local = wiphy_priv(wiphy);
|
||||
|
||||
if (!local->ops->set_sar_specs)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return local->ops->set_sar_specs(&local->hw, sar);
|
||||
}
|
||||
|
||||
const struct cfg80211_ops mac80211_config_ops = {
|
||||
.add_virtual_intf = ieee80211_add_iface,
|
||||
.del_virtual_intf = ieee80211_del_iface,
|
||||
@ -4175,4 +4186,5 @@ const struct cfg80211_ops mac80211_config_ops = {
|
||||
.probe_mesh_link = ieee80211_probe_mesh_link,
|
||||
.set_tid_config = ieee80211_set_tid_config,
|
||||
.reset_tid_config = ieee80211_reset_tid_config,
|
||||
.set_sar_specs = ieee80211_set_sar_specs,
|
||||
};
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <net/cfg80211.h>
|
||||
#include "ieee80211_i.h"
|
||||
#include "driver-ops.h"
|
||||
#include "rate.h"
|
||||
|
||||
static int ieee80211_chanctx_num_assigned(struct ieee80211_local *local,
|
||||
struct ieee80211_chanctx *ctx)
|
||||
@ -191,11 +192,13 @@ ieee80211_find_reservation_chanctx(struct ieee80211_local *local,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enum nl80211_chan_width ieee80211_get_sta_bw(struct ieee80211_sta *sta)
|
||||
static enum nl80211_chan_width ieee80211_get_sta_bw(struct sta_info *sta)
|
||||
{
|
||||
switch (sta->bandwidth) {
|
||||
enum ieee80211_sta_rx_bandwidth width = ieee80211_sta_cap_rx_bw(sta);
|
||||
|
||||
switch (width) {
|
||||
case IEEE80211_STA_RX_BW_20:
|
||||
if (sta->ht_cap.ht_supported)
|
||||
if (sta->sta.ht_cap.ht_supported)
|
||||
return NL80211_CHAN_WIDTH_20;
|
||||
else
|
||||
return NL80211_CHAN_WIDTH_20_NOHT;
|
||||
@ -232,7 +235,7 @@ ieee80211_get_max_required_bw(struct ieee80211_sub_if_data *sdata)
|
||||
!(sta->sdata->bss && sta->sdata->bss == sdata->bss))
|
||||
continue;
|
||||
|
||||
max_bw = max(max_bw, ieee80211_get_sta_bw(&sta->sta));
|
||||
max_bw = max(max_bw, ieee80211_get_sta_bw(sta));
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
@ -343,10 +346,42 @@ void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
|
||||
drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_MIN_WIDTH);
|
||||
}
|
||||
|
||||
static void ieee80211_chan_bw_change(struct ieee80211_local *local,
|
||||
struct ieee80211_chanctx *ctx)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
struct ieee80211_supported_band *sband =
|
||||
local->hw.wiphy->bands[ctx->conf.def.chan->band];
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(sta, &local->sta_list,
|
||||
list) {
|
||||
enum ieee80211_sta_rx_bandwidth new_sta_bw;
|
||||
|
||||
if (!ieee80211_sdata_running(sta->sdata))
|
||||
continue;
|
||||
|
||||
if (rcu_access_pointer(sta->sdata->vif.chanctx_conf) !=
|
||||
&ctx->conf)
|
||||
continue;
|
||||
|
||||
new_sta_bw = ieee80211_sta_cur_vht_bw(sta);
|
||||
if (new_sta_bw == sta->sta.bandwidth)
|
||||
continue;
|
||||
|
||||
sta->sta.bandwidth = new_sta_bw;
|
||||
rate_control_rate_update(local, sband, sta,
|
||||
IEEE80211_RC_BW_CHANGED);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void ieee80211_change_chanctx(struct ieee80211_local *local,
|
||||
struct ieee80211_chanctx *ctx,
|
||||
const struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
enum nl80211_chan_width width;
|
||||
|
||||
if (cfg80211_chandef_identical(&ctx->conf.def, chandef)) {
|
||||
ieee80211_recalc_chanctx_min_def(local, ctx);
|
||||
return;
|
||||
@ -354,7 +389,25 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local,
|
||||
|
||||
WARN_ON(!cfg80211_chandef_compatible(&ctx->conf.def, chandef));
|
||||
|
||||
width = ctx->conf.def.width;
|
||||
ctx->conf.def = *chandef;
|
||||
|
||||
/* expected to handle only 20/40/80/160 channel widths */
|
||||
switch (chandef->width) {
|
||||
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||
case NL80211_CHAN_WIDTH_20:
|
||||
case NL80211_CHAN_WIDTH_40:
|
||||
case NL80211_CHAN_WIDTH_80:
|
||||
case NL80211_CHAN_WIDTH_80P80:
|
||||
case NL80211_CHAN_WIDTH_160:
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
if (chandef->width < width)
|
||||
ieee80211_chan_bw_change(local, ctx);
|
||||
|
||||
drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH);
|
||||
ieee80211_recalc_chanctx_min_def(local, ctx);
|
||||
|
||||
@ -362,6 +415,9 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local,
|
||||
local->_oper_chandef = *chandef;
|
||||
ieee80211_hw_config(local, 0);
|
||||
}
|
||||
|
||||
if (chandef->width > width)
|
||||
ieee80211_chan_bw_change(local, ctx);
|
||||
}
|
||||
|
||||
static struct ieee80211_chanctx *
|
||||
@ -1051,8 +1107,14 @@ ieee80211_vif_use_reserved_reassign(struct ieee80211_sub_if_data *sdata)
|
||||
if (WARN_ON(!chandef))
|
||||
return -EINVAL;
|
||||
|
||||
if (old_ctx->conf.def.width > new_ctx->conf.def.width)
|
||||
ieee80211_chan_bw_change(local, new_ctx);
|
||||
|
||||
ieee80211_change_chanctx(local, new_ctx, chandef);
|
||||
|
||||
if (old_ctx->conf.def.width < new_ctx->conf.def.width)
|
||||
ieee80211_chan_bw_change(local, new_ctx);
|
||||
|
||||
vif_chsw[0].vif = &sdata->vif;
|
||||
vif_chsw[0].old_ctx = &old_ctx->conf;
|
||||
vif_chsw[0].new_ctx = &new_ctx->conf;
|
||||
@ -1443,6 +1505,7 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
|
||||
ieee80211_recalc_smps_chanctx(local, ctx);
|
||||
ieee80211_recalc_radar_chanctx(local, ctx);
|
||||
ieee80211_recalc_chanctx_min_def(local, ctx);
|
||||
ieee80211_chan_bw_change(local, ctx);
|
||||
|
||||
list_for_each_entry_safe(sdata, sdata_tmp, &ctx->reserved_vifs,
|
||||
reserved_chanctx_list) {
|
||||
|
@ -53,7 +53,7 @@ static const struct file_operations name## _ops = { \
|
||||
DEBUGFS_READONLY_FILE_OPS(name)
|
||||
|
||||
#define DEBUGFS_ADD(name) \
|
||||
debugfs_create_file(#name, 0400, phyd, local, &name## _ops);
|
||||
debugfs_create_file(#name, 0400, phyd, local, &name## _ops)
|
||||
|
||||
#define DEBUGFS_ADD_MODE(name, mode) \
|
||||
debugfs_create_file(#name, mode, phyd, local, &name## _ops);
|
||||
|
@ -319,7 +319,7 @@ KEY_OPS(key);
|
||||
|
||||
#define DEBUGFS_ADD(name) \
|
||||
debugfs_create_file(#name, 0400, key->debugfs.dir, \
|
||||
key, &key_##name##_ops);
|
||||
key, &key_##name##_ops)
|
||||
#define DEBUGFS_ADD_W(name) \
|
||||
debugfs_create_file(#name, 0600, key->debugfs.dir, \
|
||||
key, &key_##name##_ops);
|
||||
|
@ -642,7 +642,7 @@ IEEE80211_IF_FILE(dot11MeshConnectedToAuthServer,
|
||||
|
||||
#define DEBUGFS_ADD_MODE(name, mode) \
|
||||
debugfs_create_file(#name, mode, sdata->vif.debugfs_dir, \
|
||||
sdata, &name##_ops);
|
||||
sdata, &name##_ops)
|
||||
|
||||
#define DEBUGFS_ADD(name) DEBUGFS_ADD_MODE(name, 0400)
|
||||
|
||||
@ -711,7 +711,7 @@ static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
|
||||
struct dentry *dir = debugfs_create_dir("mesh_stats",
|
||||
sdata->vif.debugfs_dir);
|
||||
#define MESHSTATS_ADD(name)\
|
||||
debugfs_create_file(#name, 0400, dir, sdata, &name##_ops);
|
||||
debugfs_create_file(#name, 0400, dir, sdata, &name##_ops)
|
||||
|
||||
MESHSTATS_ADD(fwded_mcast);
|
||||
MESHSTATS_ADD(fwded_unicast);
|
||||
@ -728,7 +728,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
|
||||
sdata->vif.debugfs_dir);
|
||||
|
||||
#define MESHPARAMS_ADD(name) \
|
||||
debugfs_create_file(#name, 0600, dir, sdata, &name##_ops);
|
||||
debugfs_create_file(#name, 0600, dir, sdata, &name##_ops)
|
||||
|
||||
MESHPARAMS_ADD(dot11MeshMaxRetries);
|
||||
MESHPARAMS_ADD(dot11MeshRetryTimeout);
|
||||
|
@ -985,7 +985,7 @@ STA_OPS(he_capa);
|
||||
|
||||
#define DEBUGFS_ADD(name) \
|
||||
debugfs_create_file(#name, 0400, \
|
||||
sta->debugfs_dir, sta, &sta_ ##name## _ops);
|
||||
sta->debugfs_dir, sta, &sta_ ##name## _ops)
|
||||
|
||||
#define DEBUGFS_ADD_COUNTER(name, field) \
|
||||
debugfs_create_ulong(#name, 0400, sta->debugfs_dir, &sta->field);
|
||||
|
@ -452,7 +452,9 @@ struct ieee80211_if_managed {
|
||||
unsigned long probe_timeout;
|
||||
int probe_send_count;
|
||||
bool nullfunc_failed;
|
||||
bool connection_loss;
|
||||
u8 connection_loss:1,
|
||||
driver_disconnect:1,
|
||||
reconnect:1;
|
||||
|
||||
struct cfg80211_bss *associated;
|
||||
struct ieee80211_mgd_auth_data *auth_data;
|
||||
@ -1587,13 +1589,8 @@ ieee80211_have_rx_timestamp(struct ieee80211_rx_status *status)
|
||||
{
|
||||
WARN_ON_ONCE(status->flag & RX_FLAG_MACTIME_START &&
|
||||
status->flag & RX_FLAG_MACTIME_END);
|
||||
if (status->flag & (RX_FLAG_MACTIME_START | RX_FLAG_MACTIME_END))
|
||||
return true;
|
||||
/* can't handle non-legacy preamble yet */
|
||||
if (status->flag & RX_FLAG_MACTIME_PLCP_START &&
|
||||
status->encoding == RX_ENC_LEGACY)
|
||||
return true;
|
||||
return false;
|
||||
return !!(status->flag & (RX_FLAG_MACTIME_START | RX_FLAG_MACTIME_END |
|
||||
RX_FLAG_MACTIME_PLCP_START));
|
||||
}
|
||||
|
||||
void ieee80211_vif_inc_num_mcast(struct ieee80211_sub_if_data *sdata);
|
||||
@ -2280,7 +2277,6 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
|
||||
enum ieee80211_chanctx_mode chanmode,
|
||||
u8 radar_detect);
|
||||
int ieee80211_max_num_channels(struct ieee80211_local *local);
|
||||
enum nl80211_chan_width ieee80211_get_sta_bw(struct ieee80211_sta *sta);
|
||||
void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
|
||||
struct ieee80211_chanctx *ctx);
|
||||
|
||||
|
@ -1300,3 +1300,52 @@ ieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
|
||||
return &key->conf;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_add);
|
||||
|
||||
void ieee80211_key_mic_failure(struct ieee80211_key_conf *keyconf)
|
||||
{
|
||||
struct ieee80211_key *key;
|
||||
|
||||
key = container_of(keyconf, struct ieee80211_key, conf);
|
||||
|
||||
switch (key->conf.cipher) {
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
|
||||
key->u.aes_cmac.icverrors++;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
|
||||
key->u.aes_gmac.icverrors++;
|
||||
break;
|
||||
default:
|
||||
/* ignore the others for now, we don't keep counters now */
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ieee80211_key_mic_failure);
|
||||
|
||||
void ieee80211_key_replay(struct ieee80211_key_conf *keyconf)
|
||||
{
|
||||
struct ieee80211_key *key;
|
||||
|
||||
key = container_of(keyconf, struct ieee80211_key, conf);
|
||||
|
||||
switch (key->conf.cipher) {
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
case WLAN_CIPHER_SUITE_CCMP_256:
|
||||
key->u.ccmp.replays++;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
|
||||
key->u.aes_cmac.replays++;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
|
||||
key->u.aes_gmac.replays++;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_GCMP:
|
||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||
key->u.gcmp.replays++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ieee80211_key_replay);
|
||||
|
@ -1417,6 +1417,17 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
||||
return;
|
||||
}
|
||||
|
||||
if (sdata->vif.bss_conf.chandef.chan->band !=
|
||||
csa_ie.chandef.chan->band) {
|
||||
sdata_info(sdata,
|
||||
"AP %pM switches to different band (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n",
|
||||
ifmgd->associated->bssid,
|
||||
csa_ie.chandef.chan->center_freq,
|
||||
csa_ie.chandef.width, csa_ie.chandef.center_freq1,
|
||||
csa_ie.chandef.center_freq2);
|
||||
goto lock_and_drop_connection;
|
||||
}
|
||||
|
||||
if (!cfg80211_chandef_usable(local->hw.wiphy, &csa_ie.chandef,
|
||||
IEEE80211_CHAN_DISABLED)) {
|
||||
sdata_info(sdata,
|
||||
@ -1429,9 +1440,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
||||
csa_ie.chandef.width, csa_ie.chandef.center_freq1,
|
||||
csa_ie.chandef.freq1_offset,
|
||||
csa_ie.chandef.center_freq2);
|
||||
ieee80211_queue_work(&local->hw,
|
||||
&ifmgd->csa_connection_drop_work);
|
||||
return;
|
||||
goto lock_and_drop_connection;
|
||||
}
|
||||
|
||||
if (cfg80211_chandef_identical(&csa_ie.chandef,
|
||||
@ -1493,6 +1502,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
||||
sdata->csa_chandef = csa_ie.chandef;
|
||||
sdata->csa_block_tx = csa_ie.mode;
|
||||
ifmgd->csa_ignored_same_chan = false;
|
||||
ifmgd->beacon_crc_valid = false;
|
||||
|
||||
if (sdata->csa_block_tx)
|
||||
ieee80211_stop_vif_queues(local, sdata,
|
||||
@ -1500,7 +1510,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef,
|
||||
csa_ie.count);
|
||||
csa_ie.count, csa_ie.mode);
|
||||
|
||||
if (local->ops->channel_switch) {
|
||||
/* use driver's channel switch callback */
|
||||
@ -1516,6 +1526,9 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
||||
TU_TO_EXP_TIME((csa_ie.count - 1) *
|
||||
cbss->beacon_interval));
|
||||
return;
|
||||
lock_and_drop_connection:
|
||||
mutex_lock(&local->mtx);
|
||||
mutex_lock(&local->chanctx_mtx);
|
||||
drop_connection:
|
||||
/*
|
||||
* This is just so that the disconnect flow will know that
|
||||
@ -1560,9 +1573,17 @@ ieee80211_find_80211h_pwr_constr(struct ieee80211_sub_if_data *sdata,
|
||||
chan_increment = 1;
|
||||
break;
|
||||
case NL80211_BAND_5GHZ:
|
||||
case NL80211_BAND_6GHZ:
|
||||
chan_increment = 4;
|
||||
break;
|
||||
case NL80211_BAND_6GHZ:
|
||||
/*
|
||||
* In the 6 GHz band, the "maximum transmit power level"
|
||||
* field in the triplets is reserved, and thus will be
|
||||
* zero and we shouldn't use it to control TX power.
|
||||
* The actual TX power will be given in the transmit
|
||||
* power envelope element instead.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
/* find channel */
|
||||
@ -2382,6 +2403,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
|
||||
/* clear bssid only after building the needed mgmt frames */
|
||||
eth_zero_addr(ifmgd->bssid);
|
||||
|
||||
sdata->vif.bss_conf.ssid_len = 0;
|
||||
|
||||
/* remove AP and TDLS peers */
|
||||
sta_info_flush(sdata);
|
||||
|
||||
@ -2720,7 +2743,7 @@ EXPORT_SYMBOL(ieee80211_ap_probereq_get);
|
||||
|
||||
static void ieee80211_report_disconnect(struct ieee80211_sub_if_data *sdata,
|
||||
const u8 *buf, size_t len, bool tx,
|
||||
u16 reason)
|
||||
u16 reason, bool reconnect)
|
||||
{
|
||||
struct ieee80211_event event = {
|
||||
.type = MLME_EVENT,
|
||||
@ -2729,7 +2752,7 @@ static void ieee80211_report_disconnect(struct ieee80211_sub_if_data *sdata,
|
||||
};
|
||||
|
||||
if (tx)
|
||||
cfg80211_tx_mlme_mgmt(sdata->dev, buf, len);
|
||||
cfg80211_tx_mlme_mgmt(sdata->dev, buf, len, reconnect);
|
||||
else
|
||||
cfg80211_rx_mlme_mgmt(sdata->dev, buf, len);
|
||||
|
||||
@ -2751,13 +2774,18 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
|
||||
|
||||
tx = !sdata->csa_block_tx;
|
||||
|
||||
/* AP is probably out of range (or not reachable for another reason) so
|
||||
* remove the bss struct for that AP.
|
||||
*/
|
||||
cfg80211_unlink_bss(local->hw.wiphy, ifmgd->associated);
|
||||
if (!ifmgd->driver_disconnect) {
|
||||
/*
|
||||
* AP is probably out of range (or not reachable for another
|
||||
* reason) so remove the bss struct for that AP.
|
||||
*/
|
||||
cfg80211_unlink_bss(local->hw.wiphy, ifmgd->associated);
|
||||
}
|
||||
|
||||
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
|
||||
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
|
||||
ifmgd->driver_disconnect ?
|
||||
WLAN_REASON_DEAUTH_LEAVING :
|
||||
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
|
||||
tx, frame_buf);
|
||||
mutex_lock(&local->mtx);
|
||||
sdata->vif.csa_active = false;
|
||||
@ -2770,7 +2798,9 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), tx,
|
||||
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
|
||||
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
|
||||
ifmgd->reconnect);
|
||||
ifmgd->reconnect = false;
|
||||
|
||||
sdata_unlock(sdata);
|
||||
}
|
||||
@ -2789,6 +2819,13 @@ static void ieee80211_beacon_connection_loss_work(struct work_struct *work)
|
||||
sdata_info(sdata, "Connection to AP %pM lost\n",
|
||||
ifmgd->bssid);
|
||||
__ieee80211_disconnect(sdata);
|
||||
ifmgd->connection_loss = false;
|
||||
} else if (ifmgd->driver_disconnect) {
|
||||
sdata_info(sdata,
|
||||
"Driver requested disconnection from AP %pM\n",
|
||||
ifmgd->bssid);
|
||||
__ieee80211_disconnect(sdata);
|
||||
ifmgd->driver_disconnect = false;
|
||||
} else {
|
||||
ieee80211_mgd_probe_ap(sdata, true);
|
||||
}
|
||||
@ -2827,6 +2864,21 @@ void ieee80211_connection_loss(struct ieee80211_vif *vif)
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_connection_loss);
|
||||
|
||||
void ieee80211_disconnect(struct ieee80211_vif *vif, bool reconnect)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
struct ieee80211_hw *hw = &sdata->local->hw;
|
||||
|
||||
trace_api_disconnect(sdata, reconnect);
|
||||
|
||||
if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
|
||||
return;
|
||||
|
||||
sdata->u.mgd.driver_disconnect = true;
|
||||
sdata->u.mgd.reconnect = reconnect;
|
||||
ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_disconnect);
|
||||
|
||||
static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
|
||||
bool assoc)
|
||||
@ -3130,7 +3182,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
|
||||
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
|
||||
|
||||
ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false,
|
||||
reason_code);
|
||||
reason_code, false);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3179,7 +3231,8 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
|
||||
|
||||
ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false, reason_code);
|
||||
ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false, reason_code,
|
||||
false);
|
||||
}
|
||||
|
||||
static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
|
||||
@ -3199,8 +3252,8 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
|
||||
*have_higher_than_11mbit = true;
|
||||
|
||||
/*
|
||||
* Skip HT, VHT and HE BSS membership selectors since they're
|
||||
* not rates.
|
||||
* Skip HT, VHT, HE and SAE H2E only BSS membership selectors
|
||||
* since they're not rates.
|
||||
*
|
||||
* Note: Even though the membership selector and the basic
|
||||
* rate flag share the same bit, they are not exactly
|
||||
@ -3208,7 +3261,8 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
|
||||
*/
|
||||
if (supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY) ||
|
||||
supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY) ||
|
||||
supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_HE_PHY))
|
||||
supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_HE_PHY) ||
|
||||
supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E))
|
||||
continue;
|
||||
|
||||
for (j = 0; j < sband->n_bitrates; j++) {
|
||||
@ -3494,14 +3548,6 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
||||
le32_get_bits(elems->he_operation->he_oper_params,
|
||||
IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK);
|
||||
|
||||
bss_conf->multi_sta_back_32bit =
|
||||
sta->sta.he_cap.he_cap_elem.mac_cap_info[2] &
|
||||
IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP;
|
||||
|
||||
bss_conf->ack_enabled =
|
||||
sta->sta.he_cap.he_cap_elem.mac_cap_info[2] &
|
||||
IEEE80211_HE_MAC_CAP2_ACK_EN;
|
||||
|
||||
bss_conf->uora_exists = !!elems->uora_element;
|
||||
if (elems->uora_element)
|
||||
bss_conf->uora_ocw_range = elems->uora_element[0];
|
||||
@ -4199,7 +4245,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
true, deauth_buf);
|
||||
ieee80211_report_disconnect(sdata, deauth_buf,
|
||||
sizeof(deauth_buf), true,
|
||||
WLAN_REASON_DEAUTH_LEAVING);
|
||||
WLAN_REASON_DEAUTH_LEAVING,
|
||||
false);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4344,7 +4391,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
|
||||
tx, frame_buf);
|
||||
|
||||
ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true,
|
||||
reason);
|
||||
reason, false);
|
||||
}
|
||||
|
||||
static int ieee80211_auth(struct ieee80211_sub_if_data *sdata)
|
||||
@ -4716,7 +4763,8 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata)
|
||||
if (ifmgd->auth_data)
|
||||
ieee80211_destroy_auth_data(sdata, false);
|
||||
cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
|
||||
IEEE80211_DEAUTH_FRAME_LEN);
|
||||
IEEE80211_DEAUTH_FRAME_LEN,
|
||||
false);
|
||||
}
|
||||
|
||||
/* This is a bit of a hack - we should find a better and more generic
|
||||
@ -5430,7 +5478,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
ieee80211_report_disconnect(sdata, frame_buf,
|
||||
sizeof(frame_buf), true,
|
||||
WLAN_REASON_UNSPECIFIED);
|
||||
WLAN_REASON_UNSPECIFIED,
|
||||
false);
|
||||
}
|
||||
|
||||
sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
|
||||
@ -5471,6 +5520,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_mgd_assoc_data *assoc_data;
|
||||
const struct cfg80211_bss_ies *beacon_ies;
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
|
||||
const u8 *ssidie, *ht_ie, *vht_ie;
|
||||
int i, err;
|
||||
bool override = false;
|
||||
@ -5488,6 +5538,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
memcpy(assoc_data->ssid, ssidie + 2, ssidie[1]);
|
||||
assoc_data->ssid_len = ssidie[1];
|
||||
memcpy(bss_conf->ssid, assoc_data->ssid, assoc_data->ssid_len);
|
||||
bss_conf->ssid_len = assoc_data->ssid_len;
|
||||
rcu_read_unlock();
|
||||
|
||||
if (ifmgd->associated) {
|
||||
@ -5502,7 +5554,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
ieee80211_report_disconnect(sdata, frame_buf,
|
||||
sizeof(frame_buf), true,
|
||||
WLAN_REASON_UNSPECIFIED);
|
||||
WLAN_REASON_UNSPECIFIED,
|
||||
false);
|
||||
}
|
||||
|
||||
if (ifmgd->auth_data && !ifmgd->auth_data->done) {
|
||||
@ -5801,7 +5854,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
|
||||
ieee80211_destroy_auth_data(sdata, false);
|
||||
ieee80211_report_disconnect(sdata, frame_buf,
|
||||
sizeof(frame_buf), true,
|
||||
req->reason_code);
|
||||
req->reason_code, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -5821,7 +5874,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
|
||||
ieee80211_destroy_assoc_data(sdata, false, true);
|
||||
ieee80211_report_disconnect(sdata, frame_buf,
|
||||
sizeof(frame_buf), true,
|
||||
req->reason_code);
|
||||
req->reason_code, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -5836,7 +5889,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
|
||||
req->reason_code, tx, frame_buf);
|
||||
ieee80211_report_disconnect(sdata, frame_buf,
|
||||
sizeof(frame_buf), true,
|
||||
req->reason_code);
|
||||
req->reason_code, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -5869,7 +5922,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
|
||||
frame_buf);
|
||||
|
||||
ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true,
|
||||
req->reason_code);
|
||||
req->reason_code, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -32,16 +32,6 @@
|
||||
#include "wme.h"
|
||||
#include "rate.h"
|
||||
|
||||
static inline void ieee80211_rx_stats(struct net_device *dev, u32 len)
|
||||
{
|
||||
struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
|
||||
|
||||
u64_stats_update_begin(&tstats->syncp);
|
||||
tstats->rx_packets++;
|
||||
tstats->rx_bytes += len;
|
||||
u64_stats_update_end(&tstats->syncp);
|
||||
}
|
||||
|
||||
/*
|
||||
* monitor mode reception
|
||||
*
|
||||
@ -842,7 +832,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
|
||||
|
||||
if (skb) {
|
||||
skb->dev = sdata->dev;
|
||||
ieee80211_rx_stats(skb->dev, skb->len);
|
||||
dev_sw_netstats_rx_add(skb->dev, skb->len);
|
||||
netif_receive_skb(skb);
|
||||
}
|
||||
}
|
||||
@ -1757,7 +1747,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
||||
} else if (rx->sdata->vif.type == NL80211_IFTYPE_OCB) {
|
||||
sta->rx_stats.last_rx = jiffies;
|
||||
} else if (!ieee80211_is_s1g_beacon(hdr->frame_control) &&
|
||||
is_multicast_ether_addr(hdr->addr1)) {
|
||||
!is_multicast_ether_addr(hdr->addr1)) {
|
||||
/*
|
||||
* Mesh beacons will update last_rx when if they are found to
|
||||
* match the current local configuration when processed.
|
||||
@ -2559,7 +2549,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
|
||||
skb = rx->skb;
|
||||
xmit_skb = NULL;
|
||||
|
||||
ieee80211_rx_stats(dev, skb->len);
|
||||
dev_sw_netstats_rx_add(dev, skb->len);
|
||||
|
||||
if (rx->sta) {
|
||||
/* The seqno index has the same property as needed
|
||||
@ -3698,7 +3688,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
|
||||
}
|
||||
|
||||
prev_dev = sdata->dev;
|
||||
ieee80211_rx_stats(sdata->dev, skb->len);
|
||||
dev_sw_netstats_rx_add(sdata->dev, skb->len);
|
||||
}
|
||||
|
||||
if (prev_dev) {
|
||||
@ -4411,7 +4401,7 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
|
||||
|
||||
skb->dev = fast_rx->dev;
|
||||
|
||||
ieee80211_rx_stats(fast_rx->dev, skb->len);
|
||||
dev_sw_netstats_rx_add(fast_rx->dev, skb->len);
|
||||
|
||||
/* The seqno index has the same property as needed
|
||||
* for the rx_msdu field, i.e. it is IEEE80211_NUM_TIDS
|
||||
|
@ -2,7 +2,7 @@
|
||||
/*
|
||||
* Portions of this file
|
||||
* Copyright(c) 2016-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 - 2019 Intel Corporation
|
||||
* Copyright (C) 2018 - 2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#if !defined(__MAC80211_DRIVER_TRACE) || defined(TRACE_HEADER_MULTI_READ)
|
||||
@ -2086,6 +2086,27 @@ TRACE_EVENT(api_connection_loss,
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(api_disconnect,
|
||||
TP_PROTO(struct ieee80211_sub_if_data *sdata, bool reconnect),
|
||||
|
||||
TP_ARGS(sdata, reconnect),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
VIF_ENTRY
|
||||
__field(int, reconnect)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
VIF_ASSIGN;
|
||||
__entry->reconnect = reconnect;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
VIF_PR_FMT " reconnect:%d",
|
||||
VIF_PR_ARG, __entry->reconnect
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(api_cqm_rssi_notify,
|
||||
TP_PROTO(struct ieee80211_sub_if_data *sdata,
|
||||
enum nl80211_cqm_rssi_threshold_event rssi_event,
|
||||
|
@ -38,16 +38,6 @@
|
||||
|
||||
/* misc utils */
|
||||
|
||||
static inline void ieee80211_tx_stats(struct net_device *dev, u32 len)
|
||||
{
|
||||
struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
|
||||
|
||||
u64_stats_update_begin(&tstats->syncp);
|
||||
tstats->tx_packets++;
|
||||
tstats->tx_bytes += len;
|
||||
u64_stats_update_end(&tstats->syncp);
|
||||
}
|
||||
|
||||
static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
|
||||
struct sk_buff *skb, int group_addr,
|
||||
int next_frag_len)
|
||||
@ -3386,7 +3376,7 @@ static void ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sdata,
|
||||
if (key)
|
||||
info->control.hw_key = &key->conf;
|
||||
|
||||
ieee80211_tx_stats(skb->dev, skb->len);
|
||||
dev_sw_netstats_tx_add(skb->dev, 1, skb->len);
|
||||
|
||||
if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
|
||||
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
|
||||
@ -4004,7 +3994,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ieee80211_tx_stats(dev, skb->len);
|
||||
dev_sw_netstats_tx_add(dev, 1, skb->len);
|
||||
|
||||
ieee80211_xmit(sdata, sta, skb);
|
||||
}
|
||||
@ -4231,7 +4221,7 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
|
||||
|
||||
ieee80211_tx_stats(dev, skb->len);
|
||||
dev_sw_netstats_tx_add(dev, 1, skb->len);
|
||||
|
||||
sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len;
|
||||
sta->tx_stats.packets[skb_get_queue_mapping(skb)]++;
|
||||
|
@ -3666,6 +3666,7 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
|
||||
u64 ts = status->mactime;
|
||||
struct rate_info ri;
|
||||
u16 rate;
|
||||
u8 n_ltf;
|
||||
|
||||
if (WARN_ON(!ieee80211_have_rx_timestamp(status)))
|
||||
return 0;
|
||||
@ -3676,11 +3677,58 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
|
||||
|
||||
/* Fill cfg80211 rate info */
|
||||
switch (status->encoding) {
|
||||
case RX_ENC_HE:
|
||||
ri.flags |= RATE_INFO_FLAGS_HE_MCS;
|
||||
ri.mcs = status->rate_idx;
|
||||
ri.nss = status->nss;
|
||||
ri.he_ru_alloc = status->he_ru;
|
||||
if (status->enc_flags & RX_ENC_FLAG_SHORT_GI)
|
||||
ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
|
||||
/*
|
||||
* See P802.11ax_D6.0, section 27.3.4 for
|
||||
* VHT PPDU format.
|
||||
*/
|
||||
if (status->flag & RX_FLAG_MACTIME_PLCP_START) {
|
||||
mpdu_offset += 2;
|
||||
ts += 36;
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* For HE MU PPDU, add the HE-SIG-B.
|
||||
* For HE ER PPDU, add 8us for the HE-SIG-A.
|
||||
* For HE TB PPDU, add 4us for the HE-STF.
|
||||
* Add the HE-LTF durations - variable.
|
||||
*/
|
||||
}
|
||||
|
||||
break;
|
||||
case RX_ENC_HT:
|
||||
ri.mcs = status->rate_idx;
|
||||
ri.flags |= RATE_INFO_FLAGS_MCS;
|
||||
if (status->enc_flags & RX_ENC_FLAG_SHORT_GI)
|
||||
ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
|
||||
/*
|
||||
* See P802.11REVmd_D3.0, section 19.3.2 for
|
||||
* HT PPDU format.
|
||||
*/
|
||||
if (status->flag & RX_FLAG_MACTIME_PLCP_START) {
|
||||
mpdu_offset += 2;
|
||||
if (status->enc_flags & RX_ENC_FLAG_HT_GF)
|
||||
ts += 24;
|
||||
else
|
||||
ts += 32;
|
||||
|
||||
/*
|
||||
* Add Data HT-LTFs per streams
|
||||
* TODO: add Extension HT-LTFs, 4us per LTF
|
||||
*/
|
||||
n_ltf = ((ri.mcs >> 3) & 3) + 1;
|
||||
n_ltf = n_ltf == 3 ? 4 : n_ltf;
|
||||
ts += n_ltf * 4;
|
||||
}
|
||||
|
||||
break;
|
||||
case RX_ENC_VHT:
|
||||
ri.flags |= RATE_INFO_FLAGS_VHT_MCS;
|
||||
@ -3688,6 +3736,23 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
|
||||
ri.nss = status->nss;
|
||||
if (status->enc_flags & RX_ENC_FLAG_SHORT_GI)
|
||||
ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
|
||||
/*
|
||||
* See P802.11REVmd_D3.0, section 21.3.2 for
|
||||
* VHT PPDU format.
|
||||
*/
|
||||
if (status->flag & RX_FLAG_MACTIME_PLCP_START) {
|
||||
mpdu_offset += 2;
|
||||
ts += 36;
|
||||
|
||||
/*
|
||||
* Add VHT-LTFs per streams
|
||||
*/
|
||||
n_ltf = (ri.nss != 1) && (ri.nss % 2) ?
|
||||
ri.nss + 1 : ri.nss;
|
||||
ts += 4 * n_ltf;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
@ -3711,7 +3776,6 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
|
||||
ri.legacy = DIV_ROUND_UP(bitrate, (1 << shift));
|
||||
|
||||
if (status->flag & RX_FLAG_MACTIME_PLCP_START) {
|
||||
/* TODO: handle HT/VHT preambles */
|
||||
if (status->band == NL80211_BAND_5GHZ) {
|
||||
ts += 20 << shift;
|
||||
mpdu_offset += 2;
|
||||
|
@ -465,12 +465,18 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta)
|
||||
* IEEE80211-2016 specification makes higher bandwidth operation
|
||||
* possible on the TDLS link if the peers have wider bandwidth
|
||||
* capability.
|
||||
*
|
||||
* However, in this case, and only if the TDLS peer is authorized,
|
||||
* limit to the tdls_chandef so that the configuration here isn't
|
||||
* wider than what's actually requested on the channel context.
|
||||
*/
|
||||
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
|
||||
test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW))
|
||||
return bw;
|
||||
|
||||
bw = min(bw, ieee80211_chan_width_to_rx_bw(bss_width));
|
||||
test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW) &&
|
||||
test_sta_flag(sta, WLAN_STA_AUTHORIZED) &&
|
||||
sta->tdls_chandef.chan)
|
||||
bw = min(bw, ieee80211_chan_width_to_rx_bw(sta->tdls_chandef.width));
|
||||
else
|
||||
bw = min(bw, ieee80211_chan_width_to_rx_bw(bss_width));
|
||||
|
||||
return bw;
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ struct rfkill {
|
||||
enum rfkill_type type;
|
||||
|
||||
unsigned long state;
|
||||
unsigned long hard_block_reasons;
|
||||
|
||||
u32 idx;
|
||||
|
||||
@ -265,6 +266,7 @@ static void rfkill_fill_event(struct rfkill_event *ev, struct rfkill *rfkill,
|
||||
ev->hard = !!(rfkill->state & RFKILL_BLOCK_HW);
|
||||
ev->soft = !!(rfkill->state & (RFKILL_BLOCK_SW |
|
||||
RFKILL_BLOCK_SW_PREV));
|
||||
ev->hard_block_reasons = rfkill->hard_block_reasons;
|
||||
spin_unlock_irqrestore(&rfkill->lock, flags);
|
||||
}
|
||||
|
||||
@ -522,19 +524,29 @@ bool rfkill_get_global_sw_state(const enum rfkill_type type)
|
||||
}
|
||||
#endif
|
||||
|
||||
bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked)
|
||||
bool rfkill_set_hw_state_reason(struct rfkill *rfkill,
|
||||
bool blocked, unsigned long reason)
|
||||
{
|
||||
unsigned long flags;
|
||||
bool ret, prev;
|
||||
|
||||
BUG_ON(!rfkill);
|
||||
|
||||
if (WARN(reason &
|
||||
~(RFKILL_HARD_BLOCK_SIGNAL | RFKILL_HARD_BLOCK_NOT_OWNER),
|
||||
"hw_state reason not supported: 0x%lx", reason))
|
||||
return blocked;
|
||||
|
||||
spin_lock_irqsave(&rfkill->lock, flags);
|
||||
prev = !!(rfkill->state & RFKILL_BLOCK_HW);
|
||||
if (blocked)
|
||||
prev = !!(rfkill->hard_block_reasons & reason);
|
||||
if (blocked) {
|
||||
rfkill->state |= RFKILL_BLOCK_HW;
|
||||
else
|
||||
rfkill->state &= ~RFKILL_BLOCK_HW;
|
||||
rfkill->hard_block_reasons |= reason;
|
||||
} else {
|
||||
rfkill->hard_block_reasons &= ~reason;
|
||||
if (!rfkill->hard_block_reasons)
|
||||
rfkill->state &= ~RFKILL_BLOCK_HW;
|
||||
}
|
||||
ret = !!(rfkill->state & RFKILL_BLOCK_ANY);
|
||||
spin_unlock_irqrestore(&rfkill->lock, flags);
|
||||
|
||||
@ -546,7 +558,7 @@ bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked)
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rfkill_set_hw_state);
|
||||
EXPORT_SYMBOL(rfkill_set_hw_state_reason);
|
||||
|
||||
static void __rfkill_set_sw_state(struct rfkill *rfkill, bool blocked)
|
||||
{
|
||||
@ -744,6 +756,16 @@ static ssize_t soft_store(struct device *dev, struct device_attribute *attr,
|
||||
}
|
||||
static DEVICE_ATTR_RW(soft);
|
||||
|
||||
static ssize_t hard_block_reasons_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
|
||||
return sprintf(buf, "0x%lx\n", rfkill->hard_block_reasons);
|
||||
}
|
||||
static DEVICE_ATTR_RO(hard_block_reasons);
|
||||
|
||||
static u8 user_state_from_blocked(unsigned long state)
|
||||
{
|
||||
if (state & RFKILL_BLOCK_HW)
|
||||
@ -796,6 +818,7 @@ static struct attribute *rfkill_dev_attrs[] = {
|
||||
&dev_attr_state.attr,
|
||||
&dev_attr_soft.attr,
|
||||
&dev_attr_hard.attr,
|
||||
&dev_attr_hard_block_reasons.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(rfkill_dev);
|
||||
@ -811,6 +834,7 @@ static int rfkill_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
unsigned long flags;
|
||||
unsigned long reasons;
|
||||
u32 state;
|
||||
int error;
|
||||
|
||||
@ -823,10 +847,13 @@ static int rfkill_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
return error;
|
||||
spin_lock_irqsave(&rfkill->lock, flags);
|
||||
state = rfkill->state;
|
||||
reasons = rfkill->hard_block_reasons;
|
||||
spin_unlock_irqrestore(&rfkill->lock, flags);
|
||||
error = add_uevent_var(env, "RFKILL_STATE=%d",
|
||||
user_state_from_blocked(state));
|
||||
return error;
|
||||
if (error)
|
||||
return error;
|
||||
return add_uevent_var(env, "RFKILL_HW_BLOCK_REASON=0x%lx", reasons);
|
||||
}
|
||||
|
||||
void rfkill_pause_polling(struct rfkill *rfkill)
|
||||
|
@ -433,6 +433,8 @@ void cfg80211_sme_abandon_assoc(struct wireless_dev *wdev);
|
||||
|
||||
/* internal helpers */
|
||||
bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher);
|
||||
bool cfg80211_valid_key_idx(struct cfg80211_registered_device *rdev,
|
||||
int key_idx, bool pairwise);
|
||||
int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
|
||||
struct key_params *params, int key_idx,
|
||||
bool pairwise, const u8 *mac_addr);
|
||||
|
@ -4,7 +4,7 @@
|
||||
*
|
||||
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2015 Intel Deutschland GmbH
|
||||
* Copyright (C) 2019 Intel Corporation
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@ -81,7 +81,8 @@ static void cfg80211_process_auth(struct wireless_dev *wdev,
|
||||
}
|
||||
|
||||
static void cfg80211_process_deauth(struct wireless_dev *wdev,
|
||||
const u8 *buf, size_t len)
|
||||
const u8 *buf, size_t len,
|
||||
bool reconnect)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
|
||||
@ -89,7 +90,7 @@ static void cfg80211_process_deauth(struct wireless_dev *wdev,
|
||||
u16 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
|
||||
bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr);
|
||||
|
||||
nl80211_send_deauth(rdev, wdev->netdev, buf, len, GFP_KERNEL);
|
||||
nl80211_send_deauth(rdev, wdev->netdev, buf, len, reconnect, GFP_KERNEL);
|
||||
|
||||
if (!wdev->current_bss ||
|
||||
!ether_addr_equal(wdev->current_bss->pub.bssid, bssid))
|
||||
@ -100,7 +101,8 @@ static void cfg80211_process_deauth(struct wireless_dev *wdev,
|
||||
}
|
||||
|
||||
static void cfg80211_process_disassoc(struct wireless_dev *wdev,
|
||||
const u8 *buf, size_t len)
|
||||
const u8 *buf, size_t len,
|
||||
bool reconnect)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
|
||||
@ -108,7 +110,8 @@ static void cfg80211_process_disassoc(struct wireless_dev *wdev,
|
||||
u16 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
|
||||
bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr);
|
||||
|
||||
nl80211_send_disassoc(rdev, wdev->netdev, buf, len, GFP_KERNEL);
|
||||
nl80211_send_disassoc(rdev, wdev->netdev, buf, len, reconnect,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (WARN_ON(!wdev->current_bss ||
|
||||
!ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
|
||||
@ -133,9 +136,9 @@ void cfg80211_rx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len)
|
||||
if (ieee80211_is_auth(mgmt->frame_control))
|
||||
cfg80211_process_auth(wdev, buf, len);
|
||||
else if (ieee80211_is_deauth(mgmt->frame_control))
|
||||
cfg80211_process_deauth(wdev, buf, len);
|
||||
cfg80211_process_deauth(wdev, buf, len, false);
|
||||
else if (ieee80211_is_disassoc(mgmt->frame_control))
|
||||
cfg80211_process_disassoc(wdev, buf, len);
|
||||
cfg80211_process_disassoc(wdev, buf, len, false);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_rx_mlme_mgmt);
|
||||
|
||||
@ -180,22 +183,23 @@ void cfg80211_abandon_assoc(struct net_device *dev, struct cfg80211_bss *bss)
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_abandon_assoc);
|
||||
|
||||
void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len)
|
||||
void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len,
|
||||
bool reconnect)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct ieee80211_mgmt *mgmt = (void *)buf;
|
||||
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
||||
trace_cfg80211_tx_mlme_mgmt(dev, buf, len);
|
||||
trace_cfg80211_tx_mlme_mgmt(dev, buf, len, reconnect);
|
||||
|
||||
if (WARN_ON(len < 2))
|
||||
return;
|
||||
|
||||
if (ieee80211_is_deauth(mgmt->frame_control))
|
||||
cfg80211_process_deauth(wdev, buf, len);
|
||||
cfg80211_process_deauth(wdev, buf, len, reconnect);
|
||||
else
|
||||
cfg80211_process_disassoc(wdev, buf, len);
|
||||
cfg80211_process_disassoc(wdev, buf, len, reconnect);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_tx_mlme_mgmt);
|
||||
|
||||
|
@ -399,6 +399,18 @@ nl80211_unsol_bcast_probe_resp_policy[NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX +
|
||||
.len = IEEE80211_MAX_DATA_LEN }
|
||||
};
|
||||
|
||||
static const struct nla_policy
|
||||
sar_specs_policy[NL80211_SAR_ATTR_SPECS_MAX + 1] = {
|
||||
[NL80211_SAR_ATTR_SPECS_POWER] = { .type = NLA_S32 },
|
||||
[NL80211_SAR_ATTR_SPECS_RANGE_INDEX] = {.type = NLA_U32 },
|
||||
};
|
||||
|
||||
static const struct nla_policy
|
||||
sar_policy[NL80211_SAR_ATTR_MAX + 1] = {
|
||||
[NL80211_SAR_ATTR_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_SAR_TYPE),
|
||||
[NL80211_SAR_ATTR_SPECS] = NLA_POLICY_NESTED_ARRAY(sar_specs_policy),
|
||||
};
|
||||
|
||||
static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
||||
[0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
|
||||
[NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
|
||||
@ -718,6 +730,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
||||
[NL80211_ATTR_SAE_PWE] =
|
||||
NLA_POLICY_RANGE(NLA_U8, NL80211_SAE_PWE_HUNT_AND_PECK,
|
||||
NL80211_SAE_PWE_BOTH),
|
||||
[NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT },
|
||||
[NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy),
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
@ -2094,6 +2108,56 @@ fail:
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
static int
|
||||
nl80211_put_sar_specs(struct cfg80211_registered_device *rdev,
|
||||
struct sk_buff *msg)
|
||||
{
|
||||
struct nlattr *sar_capa, *specs, *sub_freq_range;
|
||||
u8 num_freq_ranges;
|
||||
int i;
|
||||
|
||||
if (!rdev->wiphy.sar_capa)
|
||||
return 0;
|
||||
|
||||
num_freq_ranges = rdev->wiphy.sar_capa->num_freq_ranges;
|
||||
|
||||
sar_capa = nla_nest_start(msg, NL80211_ATTR_SAR_SPEC);
|
||||
if (!sar_capa)
|
||||
return -ENOSPC;
|
||||
|
||||
if (nla_put_u32(msg, NL80211_SAR_ATTR_TYPE, rdev->wiphy.sar_capa->type))
|
||||
goto fail;
|
||||
|
||||
specs = nla_nest_start(msg, NL80211_SAR_ATTR_SPECS);
|
||||
if (!specs)
|
||||
goto fail;
|
||||
|
||||
/* report supported freq_ranges */
|
||||
for (i = 0; i < num_freq_ranges; i++) {
|
||||
sub_freq_range = nla_nest_start(msg, i + 1);
|
||||
if (!sub_freq_range)
|
||||
goto fail;
|
||||
|
||||
if (nla_put_u32(msg, NL80211_SAR_ATTR_SPECS_START_FREQ,
|
||||
rdev->wiphy.sar_capa->freq_ranges[i].start_freq))
|
||||
goto fail;
|
||||
|
||||
if (nla_put_u32(msg, NL80211_SAR_ATTR_SPECS_END_FREQ,
|
||||
rdev->wiphy.sar_capa->freq_ranges[i].end_freq))
|
||||
goto fail;
|
||||
|
||||
nla_nest_end(msg, sub_freq_range);
|
||||
}
|
||||
|
||||
nla_nest_end(msg, specs);
|
||||
nla_nest_end(msg, sar_capa);
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
nla_nest_cancel(msg, sar_capa);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
struct nl80211_dump_wiphy_state {
|
||||
s64 filter_wiphy;
|
||||
long start;
|
||||
@ -2343,6 +2407,8 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
||||
CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST);
|
||||
CMD(update_connect_params, UPDATE_CONNECT_PARAMS);
|
||||
CMD(update_ft_ies, UPDATE_FT_IES);
|
||||
if (rdev->wiphy.sar_capa)
|
||||
CMD(set_sar_specs, SET_SAR_SPECS);
|
||||
}
|
||||
#undef CMD
|
||||
|
||||
@ -2668,6 +2734,11 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
||||
|
||||
if (nl80211_put_tid_config_support(rdev, msg))
|
||||
goto nla_put_failure;
|
||||
state->split_start++;
|
||||
break;
|
||||
case 16:
|
||||
if (nl80211_put_sar_specs(rdev, msg))
|
||||
goto nla_put_failure;
|
||||
|
||||
/* done */
|
||||
state->split_start = 0;
|
||||
@ -4239,9 +4310,6 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (key.idx < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (info->attrs[NL80211_ATTR_MAC])
|
||||
mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
|
||||
|
||||
@ -4257,6 +4325,10 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
|
||||
key.type != NL80211_KEYTYPE_GROUP)
|
||||
return -EINVAL;
|
||||
|
||||
if (!cfg80211_valid_key_idx(rdev, key.idx,
|
||||
key.type == NL80211_KEYTYPE_PAIRWISE))
|
||||
return -EINVAL;
|
||||
|
||||
if (!rdev->ops->del_key)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
@ -5017,6 +5089,8 @@ static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params,
|
||||
params->vht_required = true;
|
||||
if (rates[2 + i] == BSS_MEMBERSHIP_SELECTOR_HE_PHY)
|
||||
params->he_required = true;
|
||||
if (rates[2 + i] == BSS_MEMBERSHIP_SELECTOR_SAE_H2E)
|
||||
params->sae_h2e_required = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -8241,12 +8315,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]) {
|
||||
if (!wiphy_ext_feature_isset(wiphy,
|
||||
NL80211_EXT_FEATURE_SET_SCAN_DWELL)) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
request->duration =
|
||||
nla_get_u16(info->attrs[NL80211_ATTR_MEASUREMENT_DURATION]);
|
||||
request->duration_mandatory =
|
||||
@ -11175,6 +11243,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
|
||||
return -EINVAL;
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
@ -14669,6 +14738,111 @@ static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
|
||||
}
|
||||
}
|
||||
|
||||
static int nl80211_set_sar_sub_specs(struct cfg80211_registered_device *rdev,
|
||||
struct cfg80211_sar_specs *sar_specs,
|
||||
struct nlattr *spec[], int index)
|
||||
{
|
||||
u32 range_index, i;
|
||||
|
||||
if (!sar_specs || !spec)
|
||||
return -EINVAL;
|
||||
|
||||
if (!spec[NL80211_SAR_ATTR_SPECS_POWER] ||
|
||||
!spec[NL80211_SAR_ATTR_SPECS_RANGE_INDEX])
|
||||
return -EINVAL;
|
||||
|
||||
range_index = nla_get_u32(spec[NL80211_SAR_ATTR_SPECS_RANGE_INDEX]);
|
||||
|
||||
/* check if range_index exceeds num_freq_ranges */
|
||||
if (range_index >= rdev->wiphy.sar_capa->num_freq_ranges)
|
||||
return -EINVAL;
|
||||
|
||||
/* check if range_index duplicates */
|
||||
for (i = 0; i < index; i++) {
|
||||
if (sar_specs->sub_specs[i].freq_range_index == range_index)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sar_specs->sub_specs[index].power =
|
||||
nla_get_s32(spec[NL80211_SAR_ATTR_SPECS_POWER]);
|
||||
|
||||
sar_specs->sub_specs[index].freq_range_index = range_index;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_set_sar_specs(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct nlattr *spec[NL80211_SAR_ATTR_SPECS_MAX + 1];
|
||||
struct nlattr *tb[NL80211_SAR_ATTR_MAX + 1];
|
||||
struct cfg80211_sar_specs *sar_spec;
|
||||
enum nl80211_sar_type type;
|
||||
struct nlattr *spec_list;
|
||||
u32 specs;
|
||||
int rem, err;
|
||||
|
||||
if (!rdev->wiphy.sar_capa || !rdev->ops->set_sar_specs)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!info->attrs[NL80211_ATTR_SAR_SPEC])
|
||||
return -EINVAL;
|
||||
|
||||
nla_parse_nested(tb, NL80211_SAR_ATTR_MAX,
|
||||
info->attrs[NL80211_ATTR_SAR_SPEC],
|
||||
NULL, NULL);
|
||||
|
||||
if (!tb[NL80211_SAR_ATTR_TYPE] || !tb[NL80211_SAR_ATTR_SPECS])
|
||||
return -EINVAL;
|
||||
|
||||
type = nla_get_u32(tb[NL80211_SAR_ATTR_TYPE]);
|
||||
if (type != rdev->wiphy.sar_capa->type)
|
||||
return -EINVAL;
|
||||
|
||||
specs = 0;
|
||||
nla_for_each_nested(spec_list, tb[NL80211_SAR_ATTR_SPECS], rem)
|
||||
specs++;
|
||||
|
||||
if (specs > rdev->wiphy.sar_capa->num_freq_ranges)
|
||||
return -EINVAL;
|
||||
|
||||
sar_spec = kzalloc(sizeof(*sar_spec) +
|
||||
specs * sizeof(struct cfg80211_sar_sub_specs),
|
||||
GFP_KERNEL);
|
||||
if (!sar_spec)
|
||||
return -ENOMEM;
|
||||
|
||||
sar_spec->type = type;
|
||||
specs = 0;
|
||||
nla_for_each_nested(spec_list, tb[NL80211_SAR_ATTR_SPECS], rem) {
|
||||
nla_parse_nested(spec, NL80211_SAR_ATTR_SPECS_MAX,
|
||||
spec_list, NULL, NULL);
|
||||
|
||||
switch (type) {
|
||||
case NL80211_SAR_TYPE_POWER:
|
||||
if (nl80211_set_sar_sub_specs(rdev, sar_spec,
|
||||
spec, specs)) {
|
||||
err = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
specs++;
|
||||
}
|
||||
|
||||
sar_spec->num_sub_specs = specs;
|
||||
|
||||
rdev->cur_cmd_info = info;
|
||||
err = rdev_set_sar_specs(rdev, sar_spec);
|
||||
rdev->cur_cmd_info = NULL;
|
||||
error:
|
||||
kfree(sar_spec);
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct genl_ops nl80211_ops[] = {
|
||||
{
|
||||
.cmd = NL80211_CMD_GET_WIPHY,
|
||||
@ -15522,6 +15696,14 @@ static const struct genl_small_ops nl80211_small_ops[] = {
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
{
|
||||
.cmd = NL80211_CMD_SET_SAR_SPECS,
|
||||
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
|
||||
.doit = nl80211_set_sar_specs,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WIPHY |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
};
|
||||
|
||||
static struct genl_family nl80211_fam __ro_after_init = {
|
||||
@ -15857,7 +16039,7 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
|
||||
const u8 *buf, size_t len,
|
||||
enum nl80211_commands cmd, gfp_t gfp,
|
||||
int uapsd_queues, const u8 *req_ies,
|
||||
size_t req_ies_len)
|
||||
size_t req_ies_len, bool reconnect)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
@ -15879,6 +16061,9 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
|
||||
nla_put(msg, NL80211_ATTR_REQ_IE, req_ies_len, req_ies)))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (reconnect && nla_put_flag(msg, NL80211_ATTR_RECONNECT_REQUESTED))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (uapsd_queues >= 0) {
|
||||
struct nlattr *nla_wmm =
|
||||
nla_nest_start_noflag(msg, NL80211_ATTR_STA_WME);
|
||||
@ -15907,7 +16092,8 @@ void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
|
||||
size_t len, gfp_t gfp)
|
||||
{
|
||||
nl80211_send_mlme_event(rdev, netdev, buf, len,
|
||||
NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0);
|
||||
NL80211_CMD_AUTHENTICATE, gfp, -1, NULL, 0,
|
||||
false);
|
||||
}
|
||||
|
||||
void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
|
||||
@ -15917,23 +16103,25 @@ void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
|
||||
{
|
||||
nl80211_send_mlme_event(rdev, netdev, buf, len,
|
||||
NL80211_CMD_ASSOCIATE, gfp, uapsd_queues,
|
||||
req_ies, req_ies_len);
|
||||
req_ies, req_ies_len, false);
|
||||
}
|
||||
|
||||
void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev, const u8 *buf,
|
||||
size_t len, gfp_t gfp)
|
||||
size_t len, bool reconnect, gfp_t gfp)
|
||||
{
|
||||
nl80211_send_mlme_event(rdev, netdev, buf, len,
|
||||
NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0);
|
||||
NL80211_CMD_DEAUTHENTICATE, gfp, -1, NULL, 0,
|
||||
reconnect);
|
||||
}
|
||||
|
||||
void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev, const u8 *buf,
|
||||
size_t len, gfp_t gfp)
|
||||
size_t len, bool reconnect, gfp_t gfp)
|
||||
{
|
||||
nl80211_send_mlme_event(rdev, netdev, buf, len,
|
||||
NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0);
|
||||
NL80211_CMD_DISASSOCIATE, gfp, -1, NULL, 0,
|
||||
reconnect);
|
||||
}
|
||||
|
||||
void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
|
||||
@ -15964,7 +16152,7 @@ void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
|
||||
|
||||
trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
|
||||
nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1,
|
||||
NULL, 0);
|
||||
NULL, 0, false);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt);
|
||||
|
||||
@ -17065,7 +17253,7 @@ static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
gfp_t gfp,
|
||||
enum nl80211_commands notif,
|
||||
u8 count)
|
||||
u8 count, bool quiet)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
@ -17086,9 +17274,13 @@ static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
|
||||
if (nl80211_send_chandef(msg, chandef))
|
||||
goto nla_put_failure;
|
||||
|
||||
if ((notif == NL80211_CMD_CH_SWITCH_STARTED_NOTIFY) &&
|
||||
(nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT, count)))
|
||||
if (notif == NL80211_CMD_CH_SWITCH_STARTED_NOTIFY) {
|
||||
if (nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT, count))
|
||||
goto nla_put_failure;
|
||||
if (quiet &&
|
||||
nla_put_flag(msg, NL80211_ATTR_CH_SWITCH_BLOCK_TX))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
|
||||
@ -17121,13 +17313,13 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
|
||||
cfg80211_sched_dfs_chan_update(rdev);
|
||||
|
||||
nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
|
||||
NL80211_CMD_CH_SWITCH_NOTIFY, 0);
|
||||
NL80211_CMD_CH_SWITCH_NOTIFY, 0, false);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_ch_switch_notify);
|
||||
|
||||
void cfg80211_ch_switch_started_notify(struct net_device *dev,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
u8 count)
|
||||
u8 count, bool quiet)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct wiphy *wiphy = wdev->wiphy;
|
||||
@ -17136,7 +17328,8 @@ void cfg80211_ch_switch_started_notify(struct net_device *dev,
|
||||
trace_cfg80211_ch_switch_started_notify(dev, chandef);
|
||||
|
||||
nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
|
||||
NL80211_CMD_CH_SWITCH_STARTED_NOTIFY, count);
|
||||
NL80211_CMD_CH_SWITCH_STARTED_NOTIFY,
|
||||
count, quiet);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Portions of this file
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
* Copyright (C) 2018, 2020 Intel Corporation
|
||||
*/
|
||||
#ifndef __NET_WIRELESS_NL80211_H
|
||||
#define __NET_WIRELESS_NL80211_H
|
||||
@ -69,10 +69,12 @@ void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
|
||||
const u8 *req_ies, size_t req_ies_len);
|
||||
void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev,
|
||||
const u8 *buf, size_t len, gfp_t gfp);
|
||||
const u8 *buf, size_t len,
|
||||
bool reconnect, gfp_t gfp);
|
||||
void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev,
|
||||
const u8 *buf, size_t len, gfp_t gfp);
|
||||
const u8 *buf, size_t len,
|
||||
bool reconnect, gfp_t gfp);
|
||||
void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev,
|
||||
const u8 *addr, gfp_t gfp);
|
||||
|
@ -1346,4 +1346,16 @@ static inline int rdev_reset_tid_config(struct cfg80211_registered_device *rdev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int rdev_set_sar_specs(struct cfg80211_registered_device *rdev,
|
||||
struct cfg80211_sar_specs *sar)
|
||||
{
|
||||
int ret;
|
||||
|
||||
trace_rdev_set_sar_specs(&rdev->wiphy, sar);
|
||||
ret = rdev->ops->set_sar_specs(&rdev->wiphy, sar);
|
||||
trace_rdev_return_int(&rdev->wiphy, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* __CFG80211_RDEV_OPS */
|
||||
|
@ -1616,7 +1616,7 @@ static const struct ieee80211_reg_rule *
|
||||
__freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 min_bw)
|
||||
{
|
||||
const struct ieee80211_regdomain *regd = reg_get_regdomain(wiphy);
|
||||
const u32 bws[] = {0, 1, 2, 4, 5, 8, 10, 16, 20};
|
||||
static const u32 bws[] = {0, 1, 2, 4, 5, 8, 10, 16, 20};
|
||||
const struct ieee80211_reg_rule *reg_rule;
|
||||
int i = ARRAY_SIZE(bws) - 1;
|
||||
u32 bw;
|
||||
@ -2547,6 +2547,7 @@ static void handle_band_custom(struct wiphy *wiphy,
|
||||
void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
|
||||
const struct ieee80211_regdomain *regd)
|
||||
{
|
||||
const struct ieee80211_regdomain *new_regd, *tmp;
|
||||
enum nl80211_band band;
|
||||
unsigned int bands_set = 0;
|
||||
|
||||
@ -2566,6 +2567,13 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
|
||||
* on your device's supported bands.
|
||||
*/
|
||||
WARN_ON(!bands_set);
|
||||
new_regd = reg_copy_regd(regd);
|
||||
if (IS_ERR(new_regd))
|
||||
return;
|
||||
|
||||
tmp = get_wiphy_regdom(wiphy);
|
||||
rcu_assign_pointer(wiphy->regd, new_regd);
|
||||
rcu_free_regdom(tmp);
|
||||
}
|
||||
EXPORT_SYMBOL(wiphy_apply_custom_regulatory);
|
||||
|
||||
|
@ -726,7 +726,7 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev)
|
||||
int n_channels, count = 0, err;
|
||||
struct cfg80211_scan_request *request, *rdev_req = rdev->scan_req;
|
||||
LIST_HEAD(coloc_ap_list);
|
||||
bool need_scan_psc;
|
||||
bool need_scan_psc = true;
|
||||
const struct ieee80211_sband_iftype_data *iftd;
|
||||
|
||||
rdev_req->scan_6ghz = true;
|
||||
@ -770,20 +770,18 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev)
|
||||
(void *)&request->channels[n_channels];
|
||||
|
||||
/*
|
||||
* PSC channels should not be scanned if all the reported co-located APs
|
||||
* are indicating that all APs in the same ESS are co-located
|
||||
* PSC channels should not be scanned in case of direct scan with 1 SSID
|
||||
* and at least one of the reported co-located APs with same SSID
|
||||
* indicating that all APs in the same ESS are co-located
|
||||
*/
|
||||
if (count) {
|
||||
need_scan_psc = false;
|
||||
|
||||
if (count && request->n_ssids == 1 && request->ssids[0].ssid_len) {
|
||||
list_for_each_entry(ap, &coloc_ap_list, list) {
|
||||
if (!ap->colocated_ess) {
|
||||
need_scan_psc = true;
|
||||
if (ap->colocated_ess &&
|
||||
cfg80211_find_ssid_match(ap, request)) {
|
||||
need_scan_psc = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
need_scan_psc = true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1901,6 +1899,9 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
|
||||
tmp.pub.beacon_interval = beacon_interval;
|
||||
tmp.pub.capability = capability;
|
||||
tmp.ts_boottime = data->boottime_ns;
|
||||
tmp.parent_tsf = data->parent_tsf;
|
||||
ether_addr_copy(tmp.parent_bssid, data->parent_bssid);
|
||||
|
||||
if (non_tx_data) {
|
||||
tmp.pub.transmitted_bss = non_tx_data->tx_bss;
|
||||
ts = bss_from_pub(non_tx_data->tx_bss)->ts;
|
||||
|
@ -2679,19 +2679,23 @@ DEFINE_EVENT(netdev_frame_event, cfg80211_rx_mlme_mgmt,
|
||||
);
|
||||
|
||||
TRACE_EVENT(cfg80211_tx_mlme_mgmt,
|
||||
TP_PROTO(struct net_device *netdev, const u8 *buf, int len),
|
||||
TP_ARGS(netdev, buf, len),
|
||||
TP_PROTO(struct net_device *netdev, const u8 *buf, int len,
|
||||
bool reconnect),
|
||||
TP_ARGS(netdev, buf, len, reconnect),
|
||||
TP_STRUCT__entry(
|
||||
NETDEV_ENTRY
|
||||
__dynamic_array(u8, frame, len)
|
||||
__field(int, reconnect)
|
||||
),
|
||||
TP_fast_assign(
|
||||
NETDEV_ASSIGN;
|
||||
memcpy(__get_dynamic_array(frame), buf, len);
|
||||
__entry->reconnect = reconnect;
|
||||
),
|
||||
TP_printk(NETDEV_PR_FMT ", ftype:0x%.2x",
|
||||
TP_printk(NETDEV_PR_FMT ", ftype:0x%.2x reconnect:%d",
|
||||
NETDEV_PR_ARG,
|
||||
le16_to_cpup((__le16 *)__get_dynamic_array(frame)))
|
||||
le16_to_cpup((__le16 *)__get_dynamic_array(frame)),
|
||||
__entry->reconnect)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(netdev_mac_evt,
|
||||
@ -3542,6 +3546,25 @@ TRACE_EVENT(rdev_reset_tid_config,
|
||||
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT ", tids: 0x%x",
|
||||
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->tids)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rdev_set_sar_specs,
|
||||
TP_PROTO(struct wiphy *wiphy, struct cfg80211_sar_specs *sar),
|
||||
TP_ARGS(wiphy, sar),
|
||||
TP_STRUCT__entry(
|
||||
WIPHY_ENTRY
|
||||
__field(u16, type)
|
||||
__field(u16, num)
|
||||
),
|
||||
TP_fast_assign(
|
||||
WIPHY_ASSIGN;
|
||||
__entry->type = sar->type;
|
||||
__entry->num = sar->num_sub_specs;
|
||||
|
||||
),
|
||||
TP_printk(WIPHY_PR_FMT ", Set type:%d, num_specs:%d",
|
||||
WIPHY_PR_ARG, __entry->type, __entry->num)
|
||||
);
|
||||
|
||||
#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
|
@ -272,18 +272,53 @@ bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
cfg80211_igtk_cipher_supported(struct cfg80211_registered_device *rdev)
|
||||
{
|
||||
struct wiphy *wiphy = &rdev->wiphy;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < wiphy->n_cipher_suites; i++) {
|
||||
switch (wiphy->cipher_suites[i]) {
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cfg80211_valid_key_idx(struct cfg80211_registered_device *rdev,
|
||||
int key_idx, bool pairwise)
|
||||
{
|
||||
int max_key_idx;
|
||||
|
||||
if (pairwise)
|
||||
max_key_idx = 3;
|
||||
else if (wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_BEACON_PROTECTION) ||
|
||||
wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
|
||||
max_key_idx = 7;
|
||||
else if (cfg80211_igtk_cipher_supported(rdev))
|
||||
max_key_idx = 5;
|
||||
else
|
||||
max_key_idx = 3;
|
||||
|
||||
if (key_idx < 0 || key_idx > max_key_idx)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
|
||||
struct key_params *params, int key_idx,
|
||||
bool pairwise, const u8 *mac_addr)
|
||||
{
|
||||
int max_key_idx = 5;
|
||||
|
||||
if (wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_BEACON_PROTECTION) ||
|
||||
wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
|
||||
max_key_idx = 7;
|
||||
if (key_idx < 0 || key_idx > max_key_idx)
|
||||
if (!cfg80211_valid_key_idx(rdev, key_idx, pairwise))
|
||||
return -EINVAL;
|
||||
|
||||
if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
|
||||
@ -335,6 +370,7 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
if (key_idx > 3)
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1421,39 +1421,78 @@ static int cfg80211_wext_siwpmksa(struct net_device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
#define DEFINE_WEXT_COMPAT_STUB(func, type) \
|
||||
static int __ ## func(struct net_device *dev, \
|
||||
struct iw_request_info *info, \
|
||||
union iwreq_data *wrqu, \
|
||||
char *extra) \
|
||||
{ \
|
||||
return func(dev, info, (type *)wrqu, extra); \
|
||||
}
|
||||
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwname, char)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwfreq, struct iw_freq)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwfreq, struct iw_freq)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwmode, u32)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwmode, u32)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwrange, struct iw_point)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwap, struct sockaddr)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwap, struct sockaddr)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwmlme, struct iw_point)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwscan, struct iw_point)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwessid, struct iw_point)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwessid, struct iw_point)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwrate, struct iw_param)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwrate, struct iw_param)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwrts, struct iw_param)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwrts, struct iw_param)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwfrag, struct iw_param)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwfrag, struct iw_param)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwretry, struct iw_param)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwretry, struct iw_param)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwencode, struct iw_point)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwencode, struct iw_point)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwpower, struct iw_param)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwpower, struct iw_param)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwgenie, struct iw_point)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_giwauth, struct iw_param)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwauth, struct iw_param)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwencodeext, struct iw_point)
|
||||
DEFINE_WEXT_COMPAT_STUB(cfg80211_wext_siwpmksa, struct iw_point)
|
||||
|
||||
static const iw_handler cfg80211_handlers[] = {
|
||||
[IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname,
|
||||
[IW_IOCTL_IDX(SIOCSIWFREQ)] = (iw_handler) cfg80211_wext_siwfreq,
|
||||
[IW_IOCTL_IDX(SIOCGIWFREQ)] = (iw_handler) cfg80211_wext_giwfreq,
|
||||
[IW_IOCTL_IDX(SIOCSIWMODE)] = (iw_handler) cfg80211_wext_siwmode,
|
||||
[IW_IOCTL_IDX(SIOCGIWMODE)] = (iw_handler) cfg80211_wext_giwmode,
|
||||
[IW_IOCTL_IDX(SIOCGIWRANGE)] = (iw_handler) cfg80211_wext_giwrange,
|
||||
[IW_IOCTL_IDX(SIOCSIWAP)] = (iw_handler) cfg80211_wext_siwap,
|
||||
[IW_IOCTL_IDX(SIOCGIWAP)] = (iw_handler) cfg80211_wext_giwap,
|
||||
[IW_IOCTL_IDX(SIOCSIWMLME)] = (iw_handler) cfg80211_wext_siwmlme,
|
||||
[IW_IOCTL_IDX(SIOCSIWSCAN)] = (iw_handler) cfg80211_wext_siwscan,
|
||||
[IW_IOCTL_IDX(SIOCGIWSCAN)] = (iw_handler) cfg80211_wext_giwscan,
|
||||
[IW_IOCTL_IDX(SIOCSIWESSID)] = (iw_handler) cfg80211_wext_siwessid,
|
||||
[IW_IOCTL_IDX(SIOCGIWESSID)] = (iw_handler) cfg80211_wext_giwessid,
|
||||
[IW_IOCTL_IDX(SIOCSIWRATE)] = (iw_handler) cfg80211_wext_siwrate,
|
||||
[IW_IOCTL_IDX(SIOCGIWRATE)] = (iw_handler) cfg80211_wext_giwrate,
|
||||
[IW_IOCTL_IDX(SIOCSIWRTS)] = (iw_handler) cfg80211_wext_siwrts,
|
||||
[IW_IOCTL_IDX(SIOCGIWRTS)] = (iw_handler) cfg80211_wext_giwrts,
|
||||
[IW_IOCTL_IDX(SIOCSIWFRAG)] = (iw_handler) cfg80211_wext_siwfrag,
|
||||
[IW_IOCTL_IDX(SIOCGIWFRAG)] = (iw_handler) cfg80211_wext_giwfrag,
|
||||
[IW_IOCTL_IDX(SIOCSIWTXPOW)] = (iw_handler) cfg80211_wext_siwtxpower,
|
||||
[IW_IOCTL_IDX(SIOCGIWTXPOW)] = (iw_handler) cfg80211_wext_giwtxpower,
|
||||
[IW_IOCTL_IDX(SIOCSIWRETRY)] = (iw_handler) cfg80211_wext_siwretry,
|
||||
[IW_IOCTL_IDX(SIOCGIWRETRY)] = (iw_handler) cfg80211_wext_giwretry,
|
||||
[IW_IOCTL_IDX(SIOCSIWENCODE)] = (iw_handler) cfg80211_wext_siwencode,
|
||||
[IW_IOCTL_IDX(SIOCGIWENCODE)] = (iw_handler) cfg80211_wext_giwencode,
|
||||
[IW_IOCTL_IDX(SIOCSIWPOWER)] = (iw_handler) cfg80211_wext_siwpower,
|
||||
[IW_IOCTL_IDX(SIOCGIWPOWER)] = (iw_handler) cfg80211_wext_giwpower,
|
||||
[IW_IOCTL_IDX(SIOCSIWGENIE)] = (iw_handler) cfg80211_wext_siwgenie,
|
||||
[IW_IOCTL_IDX(SIOCSIWAUTH)] = (iw_handler) cfg80211_wext_siwauth,
|
||||
[IW_IOCTL_IDX(SIOCGIWAUTH)] = (iw_handler) cfg80211_wext_giwauth,
|
||||
[IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext,
|
||||
[IW_IOCTL_IDX(SIOCSIWPMKSA)] = (iw_handler) cfg80211_wext_siwpmksa,
|
||||
[IW_IOCTL_IDX(SIOCGIWNAME)] = __cfg80211_wext_giwname,
|
||||
[IW_IOCTL_IDX(SIOCSIWFREQ)] = __cfg80211_wext_siwfreq,
|
||||
[IW_IOCTL_IDX(SIOCGIWFREQ)] = __cfg80211_wext_giwfreq,
|
||||
[IW_IOCTL_IDX(SIOCSIWMODE)] = __cfg80211_wext_siwmode,
|
||||
[IW_IOCTL_IDX(SIOCGIWMODE)] = __cfg80211_wext_giwmode,
|
||||
[IW_IOCTL_IDX(SIOCGIWRANGE)] = __cfg80211_wext_giwrange,
|
||||
[IW_IOCTL_IDX(SIOCSIWAP)] = __cfg80211_wext_siwap,
|
||||
[IW_IOCTL_IDX(SIOCGIWAP)] = __cfg80211_wext_giwap,
|
||||
[IW_IOCTL_IDX(SIOCSIWMLME)] = __cfg80211_wext_siwmlme,
|
||||
[IW_IOCTL_IDX(SIOCSIWSCAN)] = cfg80211_wext_siwscan,
|
||||
[IW_IOCTL_IDX(SIOCGIWSCAN)] = __cfg80211_wext_giwscan,
|
||||
[IW_IOCTL_IDX(SIOCSIWESSID)] = __cfg80211_wext_siwessid,
|
||||
[IW_IOCTL_IDX(SIOCGIWESSID)] = __cfg80211_wext_giwessid,
|
||||
[IW_IOCTL_IDX(SIOCSIWRATE)] = __cfg80211_wext_siwrate,
|
||||
[IW_IOCTL_IDX(SIOCGIWRATE)] = __cfg80211_wext_giwrate,
|
||||
[IW_IOCTL_IDX(SIOCSIWRTS)] = __cfg80211_wext_siwrts,
|
||||
[IW_IOCTL_IDX(SIOCGIWRTS)] = __cfg80211_wext_giwrts,
|
||||
[IW_IOCTL_IDX(SIOCSIWFRAG)] = __cfg80211_wext_siwfrag,
|
||||
[IW_IOCTL_IDX(SIOCGIWFRAG)] = __cfg80211_wext_giwfrag,
|
||||
[IW_IOCTL_IDX(SIOCSIWTXPOW)] = cfg80211_wext_siwtxpower,
|
||||
[IW_IOCTL_IDX(SIOCGIWTXPOW)] = cfg80211_wext_giwtxpower,
|
||||
[IW_IOCTL_IDX(SIOCSIWRETRY)] = __cfg80211_wext_siwretry,
|
||||
[IW_IOCTL_IDX(SIOCGIWRETRY)] = __cfg80211_wext_giwretry,
|
||||
[IW_IOCTL_IDX(SIOCSIWENCODE)] = __cfg80211_wext_siwencode,
|
||||
[IW_IOCTL_IDX(SIOCGIWENCODE)] = __cfg80211_wext_giwencode,
|
||||
[IW_IOCTL_IDX(SIOCSIWPOWER)] = __cfg80211_wext_siwpower,
|
||||
[IW_IOCTL_IDX(SIOCGIWPOWER)] = __cfg80211_wext_giwpower,
|
||||
[IW_IOCTL_IDX(SIOCSIWGENIE)] = __cfg80211_wext_siwgenie,
|
||||
[IW_IOCTL_IDX(SIOCSIWAUTH)] = __cfg80211_wext_siwauth,
|
||||
[IW_IOCTL_IDX(SIOCGIWAUTH)] = __cfg80211_wext_giwauth,
|
||||
[IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= __cfg80211_wext_siwencodeext,
|
||||
[IW_IOCTL_IDX(SIOCSIWPMKSA)] = __cfg80211_wext_siwpmksa,
|
||||
};
|
||||
|
||||
const struct iw_handler_def cfg80211_wext_handler = {
|
||||
|
Loading…
Reference in New Issue
Block a user