forked from luck/tmp_suning_uos_patched
This time we have:
* some code to support SAE (WPA3) offload in AP mode * many documentation (wording) fixes/updates * netlink policy updates, including the use of NLA_RANGE with binary attributes * regulatory improvements for adjacent frequency bands * and a few other small additions/refactorings/cleanups -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAl9I2GQACgkQB8qZga/f l8R3QhAAkVkBKrjRG26/LILGfeznpqIXgZW9jaUA6KhXHrd5hXEu2aXb+iBIETK6 CUIKcEIsuO8Uvonu0q0BbAxinVdXIZdxdmY283z4zOS3ngh5ia9GPeNoh50qbEf3 v6h2qitqRLzIuTDnFneK8UQe5WtFWcuyYKaJjr1YjYZFBkTkoUVTQ2AA8BHKA/Qa Ng6PgSx5fo5uOztFGJOvF0y2LMvoSgGGggn6ODKYIrwNI+95iE2W9nG1nUVSzy7e N6Codaqnh4/TnyQABA1REl7OPHe5ZJrApytS3H/pqqsLfMcYByGC3ebThesNDwzM ptLGhAbDZq7f1vmYMwkUowha8iOD0LzibDBIl8235Z3oIDrgvwGRonERZnmo+aCa vEQS8MFmseCrsxheicrzo5FWLc4rt9fU5nC4IgpZLZozU8ZFP+rKo7haHpO7a69k xED3SYoB461y+5TQgNPWSeSjvv3P0LjoS29xHAVsu0pp2Gf/cKg75bPJLbsrTYlX oKUMF3djN0e9+LOvtuuQYvaZfilpsd/6nBbz5r3sEeRXkJkUcOsGkgVTwX4VtsNT oPGjF2yOmj/r6J1blOZYxnSWiyWLYk3r8Hkym8bp3esJhJbJKgTDziJm+g0kGiJt FGTlQVGNKRdHRRzgMTOSGonI2nmaE5CWSJCHcSSMX8rfZFgT1ng= =Ys45 -----END PGP SIGNATURE----- Merge tag 'mac80211-next-for-davem-2020-08-28' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next Johannes Berg says: ==================== This time we have: * some code to support SAE (WPA3) offload in AP mode * many documentation (wording) fixes/updates * netlink policy updates, including the use of NLA_RANGE with binary attributes * regulatory improvements for adjacent frequency bands * and a few other small additions/refactorings/cleanups ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ae9a138f06
|
@ -2019,8 +2019,8 @@ static void ath10k_mac_vif_ap_csa_count_down(struct ath10k_vif *arvif)
|
|||
if (!arvif->is_up)
|
||||
return;
|
||||
|
||||
if (!ieee80211_csa_is_complete(vif)) {
|
||||
ieee80211_csa_update_counter(vif);
|
||||
if (!ieee80211_beacon_cntdwn_is_complete(vif)) {
|
||||
ieee80211_beacon_update_cntdwn(vif);
|
||||
|
||||
ret = ath10k_mac_setup_bcn_tmpl(arvif);
|
||||
if (ret)
|
||||
|
|
|
@ -3878,7 +3878,7 @@ void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
|
|||
* actual channel switch is done
|
||||
*/
|
||||
if (arvif->vif->csa_active &&
|
||||
ieee80211_csa_is_complete(arvif->vif)) {
|
||||
ieee80211_beacon_cntdwn_is_complete(arvif->vif)) {
|
||||
ieee80211_csa_finish(arvif->vif);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -1593,8 +1593,8 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
|
|||
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
|
||||
cmd->vdev_id = vdev_id;
|
||||
cmd->tim_ie_offset = offs->tim_offset;
|
||||
cmd->csa_switch_count_offset = offs->csa_counter_offs[0];
|
||||
cmd->ext_csa_switch_count_offset = offs->csa_counter_offs[1];
|
||||
cmd->csa_switch_count_offset = offs->cntdwn_counter_offs[0];
|
||||
cmd->ext_csa_switch_count_offset = offs->cntdwn_counter_offs[1];
|
||||
cmd->buf_len = bcn->len;
|
||||
|
||||
ptr = skb->data + sizeof(*cmd);
|
||||
|
|
|
@ -365,7 +365,7 @@ bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif)
|
|||
if (!vif || !vif->csa_active)
|
||||
return false;
|
||||
|
||||
if (!ieee80211_csa_is_complete(vif))
|
||||
if (!ieee80211_beacon_cntdwn_is_complete(vif))
|
||||
return false;
|
||||
|
||||
ieee80211_csa_finish(vif);
|
||||
|
|
|
@ -514,7 +514,7 @@ bool ath9k_htc_csa_is_finished(struct ath9k_htc_priv *priv)
|
|||
if (!vif || !vif->csa_active)
|
||||
return false;
|
||||
|
||||
if (!ieee80211_csa_is_complete(vif))
|
||||
if (!ieee80211_beacon_cntdwn_is_complete(vif))
|
||||
return false;
|
||||
|
||||
ieee80211_csa_finish(vif);
|
||||
|
|
|
@ -1300,8 +1300,8 @@ static void iwl_mvm_csa_count_down(struct iwl_mvm *mvm,
|
|||
|
||||
mvmvif->csa_countdown = true;
|
||||
|
||||
if (!ieee80211_csa_is_complete(csa_vif)) {
|
||||
int c = ieee80211_csa_update_counter(csa_vif);
|
||||
if (!ieee80211_beacon_cntdwn_is_complete(csa_vif)) {
|
||||
int c = ieee80211_beacon_update_cntdwn(csa_vif);
|
||||
|
||||
iwl_mvm_mac_ctxt_beacon_changed(mvm, csa_vif);
|
||||
if (csa_vif->p2p &&
|
||||
|
@ -1543,7 +1543,7 @@ void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm,
|
|||
|
||||
if (notif->csa_counter != IWL_PROBE_RESP_DATA_NO_CSA &&
|
||||
notif->csa_counter >= 1)
|
||||
ieee80211_csa_set_counter(vif, notif->csa_counter);
|
||||
ieee80211_beacon_set_cntdwn(vif, notif->csa_counter);
|
||||
}
|
||||
|
||||
void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
|
||||
|
|
|
@ -172,7 +172,7 @@ static void iwl_mvm_csa_noa_start(struct iwl_mvm *mvm)
|
|||
* So we just do nothing here and the switch
|
||||
* will be performed on the last TBTT.
|
||||
*/
|
||||
if (!ieee80211_csa_is_complete(csa_vif)) {
|
||||
if (!ieee80211_beacon_cntdwn_is_complete(csa_vif)) {
|
||||
IWL_WARN(mvm, "CSA NOA started too early\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
|
|
|
@ -1699,7 +1699,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
|
|||
rcu_dereference(vif->chanctx_conf)->def.chan);
|
||||
}
|
||||
|
||||
if (vif->csa_active && ieee80211_csa_is_complete(vif))
|
||||
if (vif->csa_active && ieee80211_beacon_cntdwn_is_complete(vif))
|
||||
ieee80211_csa_finish(vif);
|
||||
}
|
||||
|
||||
|
|
|
@ -1095,7 +1095,7 @@ EXPORT_SYMBOL_GPL(mt76_get_txpower);
|
|||
static void
|
||||
__mt76_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
if (vif->csa_active && ieee80211_csa_is_complete(vif))
|
||||
if (vif->csa_active && ieee80211_beacon_cntdwn_is_complete(vif))
|
||||
ieee80211_csa_finish(vif);
|
||||
}
|
||||
|
||||
|
@ -1120,7 +1120,7 @@ __mt76_csa_check(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
|||
if (!vif->csa_active)
|
||||
return;
|
||||
|
||||
dev->csa_complete |= ieee80211_csa_is_complete(vif);
|
||||
dev->csa_complete |= ieee80211_beacon_cntdwn_is_complete(vif);
|
||||
}
|
||||
|
||||
void mt76_csa_check(struct mt76_dev *dev)
|
||||
|
|
|
@ -650,12 +650,12 @@ mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev,
|
|||
memcpy(req.pkt + MT_TXD_SIZE, skb->data, skb->len);
|
||||
req.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
|
||||
req.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset);
|
||||
if (offs.csa_counter_offs[0]) {
|
||||
if (offs.cntdwn_counter_offs[0]) {
|
||||
u16 csa_offs;
|
||||
|
||||
csa_offs = MT_TXD_SIZE + offs.csa_counter_offs[0] - 4;
|
||||
csa_offs = MT_TXD_SIZE + offs.cntdwn_counter_offs[0] - 4;
|
||||
req.csa_ie_pos = cpu_to_le16(csa_offs);
|
||||
req.csa_cnt = skb->data[offs.csa_counter_offs[0]];
|
||||
req.csa_cnt = skb->data[offs.cntdwn_counter_offs[0]];
|
||||
}
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
|
@ -1713,10 +1713,10 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev,
|
|||
req.beacon_tlv.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
|
||||
req.beacon_tlv.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset);
|
||||
|
||||
if (offs.csa_counter_offs[0]) {
|
||||
if (offs.cntdwn_counter_offs[0]) {
|
||||
u16 csa_offs;
|
||||
|
||||
csa_offs = MT_TXD_SIZE + offs.csa_counter_offs[0] - 4;
|
||||
csa_offs = MT_TXD_SIZE + offs.cntdwn_counter_offs[0] - 4;
|
||||
req.beacon_tlv.csa_ie_pos = cpu_to_le16(csa_offs);
|
||||
}
|
||||
dev_kfree_skb(skb);
|
||||
|
|
|
@ -2282,7 +2282,7 @@ mt7915_mcu_beacon_csa(struct sk_buff *rskb, struct sk_buff *skb,
|
|||
struct bss_info_bcn *bcn,
|
||||
struct ieee80211_mutable_offsets *offs)
|
||||
{
|
||||
if (offs->csa_counter_offs[0]) {
|
||||
if (offs->cntdwn_counter_offs[0]) {
|
||||
struct tlv *tlv;
|
||||
struct bss_info_bcn_csa *csa;
|
||||
|
||||
|
@ -2290,7 +2290,7 @@ mt7915_mcu_beacon_csa(struct sk_buff *rskb, struct sk_buff *skb,
|
|||
sizeof(*csa), &bcn->sub_ntlv,
|
||||
&bcn->len);
|
||||
csa = (struct bss_info_bcn_csa *)tlv;
|
||||
csa->cnt = skb->data[offs->csa_counter_offs[0]];
|
||||
csa->cnt = skb->data[offs->cntdwn_counter_offs[0]];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2312,8 +2312,8 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct sk_buff *rskb,
|
|||
cont->pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
|
||||
cont->tim_ofs = cpu_to_le16(offs->tim_offset);
|
||||
|
||||
if (offs->csa_counter_offs[0])
|
||||
cont->csa_ofs = cpu_to_le16(offs->csa_counter_offs[0] - 4);
|
||||
if (offs->cntdwn_counter_offs[0])
|
||||
cont->csa_ofs = cpu_to_le16(offs->cntdwn_counter_offs[0] - 4);
|
||||
|
||||
buf = (u8 *)tlv + sizeof(*cont);
|
||||
mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL,
|
||||
|
|
|
@ -678,7 +678,10 @@ struct cfg80211_bitrate_mask {
|
|||
u32 legacy;
|
||||
u8 ht_mcs[IEEE80211_HT_MCS_MASK_LEN];
|
||||
u16 vht_mcs[NL80211_VHT_NSS_MAX];
|
||||
u16 he_mcs[NL80211_HE_NSS_MAX];
|
||||
enum nl80211_txrate_gi gi;
|
||||
enum nl80211_he_gi he_gi;
|
||||
enum nl80211_he_ltf he_ltf;
|
||||
} control[NUM_NL80211_BANDS];
|
||||
};
|
||||
|
||||
|
|
|
@ -3736,7 +3736,7 @@ enum ieee80211_reconfig_type {
|
|||
* decremented, and when they reach 1 the driver must call
|
||||
* ieee80211_csa_finish(). Drivers which use ieee80211_beacon_get()
|
||||
* get the csa counter decremented by mac80211, but must check if it is
|
||||
* 1 using ieee80211_csa_is_complete() after the beacon has been
|
||||
* 1 using ieee80211_beacon_counter_is_complete() after the beacon has been
|
||||
* transmitted and then call ieee80211_csa_finish().
|
||||
* If the CSA count starts as zero or 1, this function will not be called,
|
||||
* since there won't be any time to beacon before the switch anyway.
|
||||
|
@ -4763,21 +4763,21 @@ void ieee80211_tx_status_8023(struct ieee80211_hw *hw,
|
|||
*/
|
||||
void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets);
|
||||
|
||||
#define IEEE80211_MAX_CSA_COUNTERS_NUM 2
|
||||
#define IEEE80211_MAX_CNTDWN_COUNTERS_NUM 2
|
||||
|
||||
/**
|
||||
* struct ieee80211_mutable_offsets - mutable beacon offsets
|
||||
* @tim_offset: position of TIM element
|
||||
* @tim_length: size of TIM element
|
||||
* @csa_counter_offs: array of IEEE80211_MAX_CSA_COUNTERS_NUM offsets
|
||||
* to CSA counters. This array can contain zero values which
|
||||
* @cntdwn_counter_offs: array of IEEE80211_MAX_CNTDWN_COUNTERS_NUM offsets
|
||||
* to countdown counters. This array can contain zero values which
|
||||
* should be ignored.
|
||||
*/
|
||||
struct ieee80211_mutable_offsets {
|
||||
u16 tim_offset;
|
||||
u16 tim_length;
|
||||
|
||||
u16 csa_counter_offs[IEEE80211_MAX_CSA_COUNTERS_NUM];
|
||||
u16 cntdwn_counter_offs[IEEE80211_MAX_CNTDWN_COUNTERS_NUM];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -4846,31 +4846,31 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
/**
|
||||
* ieee80211_csa_update_counter - request mac80211 to decrement the csa counter
|
||||
* ieee80211_beacon_update_cntdwn - request mac80211 to decrement the beacon countdown
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
*
|
||||
* The csa counter should be updated after each beacon transmission.
|
||||
* The beacon counter should be updated after each beacon transmission.
|
||||
* This function is called implicitly when
|
||||
* ieee80211_beacon_get/ieee80211_beacon_get_tim are called, however if the
|
||||
* beacon frames are generated by the device, the driver should call this
|
||||
* function after each beacon transmission to sync mac80211's csa counters.
|
||||
* function after each beacon transmission to sync mac80211's beacon countdown.
|
||||
*
|
||||
* Return: new csa counter value
|
||||
* Return: new countdown value
|
||||
*/
|
||||
u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif);
|
||||
u8 ieee80211_beacon_update_cntdwn(struct ieee80211_vif *vif);
|
||||
|
||||
/**
|
||||
* ieee80211_csa_set_counter - request mac80211 to set csa counter
|
||||
* ieee80211_beacon_set_cntdwn - request mac80211 to set beacon countdown
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
* @counter: the new value for the counter
|
||||
*
|
||||
* The csa counter can be changed by the device, this API should be
|
||||
* The beacon countdown can be changed by the device, this API should be
|
||||
* used by the device driver to update csa counter in mac80211.
|
||||
*
|
||||
* It should never be used together with ieee80211_csa_update_counter(),
|
||||
* It should never be used together with ieee80211_beacon_update_cntdwn(),
|
||||
* as it will cause a race condition around the counter value.
|
||||
*/
|
||||
void ieee80211_csa_set_counter(struct ieee80211_vif *vif, u8 counter);
|
||||
void ieee80211_beacon_set_cntdwn(struct ieee80211_vif *vif, u8 counter);
|
||||
|
||||
/**
|
||||
* ieee80211_csa_finish - notify mac80211 about channel switch
|
||||
|
@ -4883,13 +4883,12 @@ void ieee80211_csa_set_counter(struct ieee80211_vif *vif, u8 counter);
|
|||
void ieee80211_csa_finish(struct ieee80211_vif *vif);
|
||||
|
||||
/**
|
||||
* ieee80211_csa_is_complete - find out if counters reached 1
|
||||
* ieee80211_beacon_cntdwn_is_complete - find out if countdown reached 1
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
*
|
||||
* This function returns whether the channel switch counters reached zero.
|
||||
* This function returns whether the countdown reached zero.
|
||||
*/
|
||||
bool ieee80211_csa_is_complete(struct ieee80211_vif *vif);
|
||||
|
||||
bool ieee80211_beacon_cntdwn_is_complete(struct ieee80211_vif *vif);
|
||||
|
||||
/**
|
||||
* ieee80211_proberesp_get - retrieve a Probe Response template
|
||||
|
|
|
@ -252,9 +252,13 @@
|
|||
* DOC: SAE authentication offload
|
||||
*
|
||||
* By setting @NL80211_EXT_FEATURE_SAE_OFFLOAD flag drivers can indicate they
|
||||
* support offloading SAE authentication for WPA3-Personal networks. In
|
||||
* %NL80211_CMD_CONNECT the password for SAE should be specified using
|
||||
* %NL80211_ATTR_SAE_PASSWORD.
|
||||
* support offloading SAE authentication for WPA3-Personal networks in station
|
||||
* mode. Similarly @NL80211_EXT_FEATURE_SAE_OFFLOAD_AP flag can be set by
|
||||
* drivers indicating the offload support in AP mode.
|
||||
*
|
||||
* The password for SAE should be specified using %NL80211_ATTR_SAE_PASSWORD in
|
||||
* %NL80211_CMD_CONNECT and %NL80211_CMD_START_AP for station and AP mode
|
||||
* respectively.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -647,13 +651,9 @@
|
|||
* authentication/association or not receiving a response from the AP.
|
||||
* Non-zero %NL80211_ATTR_STATUS_CODE value is indicated in that case as
|
||||
* well to remain backwards compatible.
|
||||
* When establishing a security association, drivers that support 4 way
|
||||
* handshake offload should send %NL80211_CMD_PORT_AUTHORIZED event when
|
||||
* the 4 way handshake is completed successfully.
|
||||
* @NL80211_CMD_ROAM: Notification indicating the card/driver roamed by itself.
|
||||
* When a security association was established with the new AP (e.g. if
|
||||
* the FT protocol was used for roaming or the driver completed the 4 way
|
||||
* handshake), this event should be followed by an
|
||||
* When a security association was established on an 802.1X network using
|
||||
* fast transition, this event should be followed by an
|
||||
* %NL80211_CMD_PORT_AUTHORIZED event.
|
||||
* @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify
|
||||
* userspace that a connection was dropped by the AP or due to other
|
||||
|
@ -1067,13 +1067,11 @@
|
|||
* @NL80211_CMD_DEL_PMK: For offloaded 4-Way handshake, delete the previously
|
||||
* configured PMK for the authenticator address identified by
|
||||
* %NL80211_ATTR_MAC.
|
||||
* @NL80211_CMD_PORT_AUTHORIZED: An event that indicates that the 4 way
|
||||
* handshake was completed successfully by the driver. The BSSID is
|
||||
* specified with %NL80211_ATTR_MAC. Drivers that support 4 way handshake
|
||||
* offload should send this event after indicating 802.11 association with
|
||||
* %NL80211_CMD_CONNECT or %NL80211_CMD_ROAM. If the 4 way handshake failed
|
||||
* %NL80211_CMD_DISCONNECT should be indicated instead.
|
||||
*
|
||||
* @NL80211_CMD_PORT_AUTHORIZED: An event that indicates an 802.1X FT roam was
|
||||
* completed successfully. Drivers that support 4 way handshake offload
|
||||
* should send this event after indicating 802.1X FT assocation with
|
||||
* %NL80211_CMD_ROAM. If the 4 way handshake failed %NL80211_CMD_DISCONNECT
|
||||
* should be indicated instead.
|
||||
* @NL80211_CMD_CONTROL_PORT_FRAME: Control Port (e.g. PAE) frame TX request
|
||||
* and RX notification. This command is used both as a request to transmit
|
||||
* a control port frame and as a notification that a control port frame
|
||||
|
@ -2082,10 +2080,10 @@ enum nl80211_commands {
|
|||
* operation).
|
||||
* @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information
|
||||
* for the time while performing a channel switch.
|
||||
* @NL80211_ATTR_CSA_C_OFF_BEACON: An array of offsets (u16) to the channel
|
||||
* switch counters in the beacons tail (%NL80211_ATTR_BEACON_TAIL).
|
||||
* @NL80211_ATTR_CSA_C_OFF_PRESP: An array of offsets (u16) to the channel
|
||||
* switch counters in the probe response (%NL80211_ATTR_PROBE_RESP).
|
||||
* @NL80211_ATTR_CNTDWN_OFFS_BEACON: An array of offsets (u16) to the channel
|
||||
* switch or color change counters in the beacons tail (%NL80211_ATTR_BEACON_TAIL).
|
||||
* @NL80211_ATTR_CNTDWN_OFFS_PRESP: An array of offsets (u16) to the channel
|
||||
* switch or color change counters in the probe response (%NL80211_ATTR_PROBE_RESP).
|
||||
*
|
||||
* @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32.
|
||||
* As specified in the &enum nl80211_rxmgmt_flags.
|
||||
|
@ -2821,8 +2819,8 @@ enum nl80211_attrs {
|
|||
NL80211_ATTR_CH_SWITCH_COUNT,
|
||||
NL80211_ATTR_CH_SWITCH_BLOCK_TX,
|
||||
NL80211_ATTR_CSA_IES,
|
||||
NL80211_ATTR_CSA_C_OFF_BEACON,
|
||||
NL80211_ATTR_CSA_C_OFF_PRESP,
|
||||
NL80211_ATTR_CNTDWN_OFFS_BEACON,
|
||||
NL80211_ATTR_CNTDWN_OFFS_PRESP,
|
||||
|
||||
NL80211_ATTR_RXMGMT_FLAGS,
|
||||
|
||||
|
@ -3009,6 +3007,8 @@ enum nl80211_attrs {
|
|||
#define NL80211_ATTR_MESH_PARAMS NL80211_ATTR_MESH_CONFIG
|
||||
#define NL80211_ATTR_IFACE_SOCKET_OWNER NL80211_ATTR_SOCKET_OWNER
|
||||
#define NL80211_ATTR_SAE_DATA NL80211_ATTR_AUTH_DATA
|
||||
#define NL80211_ATTR_CSA_C_OFF_BEACON NL80211_ATTR_CNTDWN_OFFS_BEACON
|
||||
#define NL80211_ATTR_CSA_C_OFF_PRESP NL80211_ATTR_CNTDWN_OFFS_PRESP
|
||||
|
||||
/*
|
||||
* Allow user space programs to use #ifdef on new attributes by defining them
|
||||
|
@ -3186,6 +3186,18 @@ enum nl80211_he_gi {
|
|||
NL80211_RATE_INFO_HE_GI_3_2,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nl80211_he_ltf - HE long training field
|
||||
* @NL80211_RATE_INFO_HE_1xLTF: 3.2 usec
|
||||
* @NL80211_RATE_INFO_HE_2xLTF: 6.4 usec
|
||||
* @NL80211_RATE_INFO_HE_4xLTF: 12.8 usec
|
||||
*/
|
||||
enum nl80211_he_ltf {
|
||||
NL80211_RATE_INFO_HE_1XLTF,
|
||||
NL80211_RATE_INFO_HE_2XLTF,
|
||||
NL80211_RATE_INFO_HE_4XLTF,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nl80211_he_ru_alloc - HE RU allocation values
|
||||
* @NL80211_RATE_INFO_HE_RU_ALLOC_26: 26-tone RU allocation
|
||||
|
@ -4741,6 +4753,10 @@ enum nl80211_key_attributes {
|
|||
* @NL80211_TXRATE_VHT: VHT rates allowed for TX rate selection,
|
||||
* see &struct nl80211_txrate_vht
|
||||
* @NL80211_TXRATE_GI: configure GI, see &enum nl80211_txrate_gi
|
||||
* @NL80211_TXRATE_HE: HE rates allowed for TX rate selection,
|
||||
* see &struct nl80211_txrate_he
|
||||
* @NL80211_TXRATE_HE_GI: configure HE GI, 0.8us, 1.6us and 3.2us.
|
||||
* @NL80211_TXRATE_HE_LTF: configure HE LTF, 1XLTF, 2XLTF and 4XLTF.
|
||||
* @__NL80211_TXRATE_AFTER_LAST: internal
|
||||
* @NL80211_TXRATE_MAX: highest TX rate attribute
|
||||
*/
|
||||
|
@ -4750,6 +4766,9 @@ enum nl80211_tx_rate_attributes {
|
|||
NL80211_TXRATE_HT,
|
||||
NL80211_TXRATE_VHT,
|
||||
NL80211_TXRATE_GI,
|
||||
NL80211_TXRATE_HE,
|
||||
NL80211_TXRATE_HE_GI,
|
||||
NL80211_TXRATE_HE_LTF,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_TXRATE_AFTER_LAST,
|
||||
|
@ -4767,6 +4786,15 @@ struct nl80211_txrate_vht {
|
|||
__u16 mcs[NL80211_VHT_NSS_MAX];
|
||||
};
|
||||
|
||||
#define NL80211_HE_NSS_MAX 8
|
||||
/**
|
||||
* struct nl80211_txrate_he - HE MCS/NSS txrate bitmap
|
||||
* @mcs: MCS bitmap table for each NSS (array index 0 for 1 stream, etc.)
|
||||
*/
|
||||
struct nl80211_txrate_he {
|
||||
__u16 mcs[NL80211_HE_NSS_MAX];
|
||||
};
|
||||
|
||||
enum nl80211_txrate_gi {
|
||||
NL80211_TXRATE_DEFAULT_GI,
|
||||
NL80211_TXRATE_FORCE_SGI,
|
||||
|
@ -5821,6 +5849,9 @@ enum nl80211_feature_flags {
|
|||
* handshake with PSK in AP mode (PSK is passed as part of the start AP
|
||||
* command).
|
||||
*
|
||||
* @NL80211_EXT_FEATURE_SAE_OFFLOAD_AP: Device wants to do SAE authentication
|
||||
* in AP mode (SAE password is passed as part of the start AP command).
|
||||
*
|
||||
* @NUM_NL80211_EXT_FEATURES: number of extended features.
|
||||
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
|
||||
*/
|
||||
|
@ -5878,6 +5909,7 @@ enum nl80211_ext_feature_index {
|
|||
NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS,
|
||||
NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION,
|
||||
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK,
|
||||
NL80211_EXT_FEATURE_SAE_OFFLOAD_AP,
|
||||
|
||||
/* add new features before the definition below */
|
||||
NUM_NL80211_EXT_FEATURES,
|
||||
|
|
|
@ -350,7 +350,7 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
|
|||
sta->sta.addr, tid);
|
||||
/* We have no API to update the timeout value in the
|
||||
* driver so reject the timeout update if the timeout
|
||||
* changed. If if did not change, i.e., no real update,
|
||||
* changed. If it did not change, i.e., no real update,
|
||||
* just reply with success.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
|
|
|
@ -826,9 +826,9 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
|
|||
memcpy(new->data, resp, resp_len);
|
||||
|
||||
if (csa)
|
||||
memcpy(new->csa_counter_offsets, csa->counter_offsets_presp,
|
||||
memcpy(new->cntdwn_counter_offsets, csa->counter_offsets_presp,
|
||||
csa->n_counter_offsets_presp *
|
||||
sizeof(new->csa_counter_offsets[0]));
|
||||
sizeof(new->cntdwn_counter_offsets[0]));
|
||||
|
||||
rcu_assign_pointer(sdata->u.ap.probe_resp, new);
|
||||
if (old)
|
||||
|
@ -926,10 +926,10 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
|
|||
new->tail_len = new_tail_len;
|
||||
|
||||
if (csa) {
|
||||
new->csa_current_counter = csa->count;
|
||||
memcpy(new->csa_counter_offsets, csa->counter_offsets_beacon,
|
||||
new->cntdwn_current_counter = csa->count;
|
||||
memcpy(new->cntdwn_counter_offsets, csa->counter_offsets_beacon,
|
||||
csa->n_counter_offsets_beacon *
|
||||
sizeof(new->csa_counter_offsets[0]));
|
||||
sizeof(new->cntdwn_counter_offsets[0]));
|
||||
}
|
||||
|
||||
/* copy in head */
|
||||
|
@ -3186,9 +3186,9 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
|||
break;
|
||||
|
||||
if ((params->n_counter_offsets_beacon >
|
||||
IEEE80211_MAX_CSA_COUNTERS_NUM) ||
|
||||
IEEE80211_MAX_CNTDWN_COUNTERS_NUM) ||
|
||||
(params->n_counter_offsets_presp >
|
||||
IEEE80211_MAX_CSA_COUNTERS_NUM))
|
||||
IEEE80211_MAX_CNTDWN_COUNTERS_NUM))
|
||||
return -EINVAL;
|
||||
|
||||
csa.counter_offsets_beacon = params->counter_offsets_beacon;
|
||||
|
|
|
@ -145,9 +145,9 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata,
|
|||
*pos++ = csa_settings->block_tx ? 1 : 0;
|
||||
*pos++ = ieee80211_frequency_to_channel(
|
||||
csa_settings->chandef.chan->center_freq);
|
||||
presp->csa_counter_offsets[0] = (pos - presp->head);
|
||||
presp->cntdwn_counter_offsets[0] = (pos - presp->head);
|
||||
*pos++ = csa_settings->count;
|
||||
presp->csa_current_counter = csa_settings->count;
|
||||
presp->cntdwn_current_counter = csa_settings->count;
|
||||
}
|
||||
|
||||
/* put the remaining rates in WLAN_EID_EXT_SUPP_RATES */
|
||||
|
|
|
@ -259,15 +259,15 @@ struct beacon_data {
|
|||
u8 *head, *tail;
|
||||
int head_len, tail_len;
|
||||
struct ieee80211_meshconf_ie *meshconf;
|
||||
u16 csa_counter_offsets[IEEE80211_MAX_CSA_COUNTERS_NUM];
|
||||
u8 csa_current_counter;
|
||||
u16 cntdwn_counter_offsets[IEEE80211_MAX_CNTDWN_COUNTERS_NUM];
|
||||
u8 cntdwn_current_counter;
|
||||
struct rcu_head rcu_head;
|
||||
};
|
||||
|
||||
struct probe_resp {
|
||||
struct rcu_head rcu_head;
|
||||
int len;
|
||||
u16 csa_counter_offsets[IEEE80211_MAX_CSA_COUNTERS_NUM];
|
||||
u16 cntdwn_counter_offsets[IEEE80211_MAX_CNTDWN_COUNTERS_NUM];
|
||||
u8 data[];
|
||||
};
|
||||
|
||||
|
|
|
@ -1168,7 +1168,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||
WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT;
|
||||
}
|
||||
|
||||
local->hw.wiphy->max_num_csa_counters = IEEE80211_MAX_CSA_COUNTERS_NUM;
|
||||
local->hw.wiphy->max_num_csa_counters = IEEE80211_MAX_CNTDWN_COUNTERS_NUM;
|
||||
|
||||
/*
|
||||
* We use the number of queues for feature tests (QoS, HT) internally
|
||||
|
|
|
@ -672,7 +672,7 @@ void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh)
|
|||
* @hdr: 802.11 frame header
|
||||
* @fc: frame control field
|
||||
* @meshda: destination address in the mesh
|
||||
* @meshsa: source address address in the mesh. Same as TA, as frame is
|
||||
* @meshsa: source address in the mesh. Same as TA, as frame is
|
||||
* locally originated.
|
||||
*
|
||||
* Return the length of the 802.11 (does not include a mesh control header)
|
||||
|
@ -864,8 +864,8 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
|
|||
*pos++ = 0x0;
|
||||
*pos++ = ieee80211_frequency_to_channel(
|
||||
csa->settings.chandef.chan->center_freq);
|
||||
bcn->csa_current_counter = csa->settings.count;
|
||||
bcn->csa_counter_offsets[0] = hdr_len + 6;
|
||||
bcn->cntdwn_current_counter = csa->settings.count;
|
||||
bcn->cntdwn_counter_offsets[0] = hdr_len + 6;
|
||||
*pos++ = csa->settings.count;
|
||||
*pos++ = WLAN_EID_CHAN_SWITCH_PARAM;
|
||||
*pos++ = 6;
|
||||
|
|
|
@ -916,7 +916,7 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|||
if (beacon)
|
||||
for (i = 0; i < params->n_csa_offsets; i++)
|
||||
data[params->csa_offsets[i]] =
|
||||
beacon->csa_current_counter;
|
||||
beacon->cntdwn_current_counter;
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
|
|
@ -4538,14 +4538,14 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ieee80211_set_csa(struct ieee80211_sub_if_data *sdata,
|
||||
struct beacon_data *beacon)
|
||||
static void ieee80211_set_beacon_cntdwn(struct ieee80211_sub_if_data *sdata,
|
||||
struct beacon_data *beacon)
|
||||
{
|
||||
struct probe_resp *resp;
|
||||
u8 *beacon_data;
|
||||
size_t beacon_data_len;
|
||||
int i;
|
||||
u8 count = beacon->csa_current_counter;
|
||||
u8 count = beacon->cntdwn_current_counter;
|
||||
|
||||
switch (sdata->vif.type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
|
@ -4565,36 +4565,36 @@ static void ieee80211_set_csa(struct ieee80211_sub_if_data *sdata,
|
|||
}
|
||||
|
||||
rcu_read_lock();
|
||||
for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; ++i) {
|
||||
for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; ++i) {
|
||||
resp = rcu_dereference(sdata->u.ap.probe_resp);
|
||||
|
||||
if (beacon->csa_counter_offsets[i]) {
|
||||
if (WARN_ON_ONCE(beacon->csa_counter_offsets[i] >=
|
||||
if (beacon->cntdwn_counter_offsets[i]) {
|
||||
if (WARN_ON_ONCE(beacon->cntdwn_counter_offsets[i] >=
|
||||
beacon_data_len)) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
beacon_data[beacon->csa_counter_offsets[i]] = count;
|
||||
beacon_data[beacon->cntdwn_counter_offsets[i]] = count;
|
||||
}
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP && resp)
|
||||
resp->data[resp->csa_counter_offsets[i]] = count;
|
||||
resp->data[resp->cntdwn_counter_offsets[i]] = count;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static u8 __ieee80211_csa_update_counter(struct beacon_data *beacon)
|
||||
static u8 __ieee80211_beacon_update_cntdwn(struct beacon_data *beacon)
|
||||
{
|
||||
beacon->csa_current_counter--;
|
||||
beacon->cntdwn_current_counter--;
|
||||
|
||||
/* the counter should never reach 0 */
|
||||
WARN_ON_ONCE(!beacon->csa_current_counter);
|
||||
WARN_ON_ONCE(!beacon->cntdwn_current_counter);
|
||||
|
||||
return beacon->csa_current_counter;
|
||||
return beacon->cntdwn_current_counter;
|
||||
}
|
||||
|
||||
u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif)
|
||||
u8 ieee80211_beacon_update_cntdwn(struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
struct beacon_data *beacon = NULL;
|
||||
|
@ -4612,15 +4612,15 @@ u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif)
|
|||
if (!beacon)
|
||||
goto unlock;
|
||||
|
||||
count = __ieee80211_csa_update_counter(beacon);
|
||||
count = __ieee80211_beacon_update_cntdwn(beacon);
|
||||
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
return count;
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_csa_update_counter);
|
||||
EXPORT_SYMBOL(ieee80211_beacon_update_cntdwn);
|
||||
|
||||
void ieee80211_csa_set_counter(struct ieee80211_vif *vif, u8 counter)
|
||||
void ieee80211_beacon_set_cntdwn(struct ieee80211_vif *vif, u8 counter)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
struct beacon_data *beacon = NULL;
|
||||
|
@ -4637,15 +4637,15 @@ void ieee80211_csa_set_counter(struct ieee80211_vif *vif, u8 counter)
|
|||
if (!beacon)
|
||||
goto unlock;
|
||||
|
||||
if (counter < beacon->csa_current_counter)
|
||||
beacon->csa_current_counter = counter;
|
||||
if (counter < beacon->cntdwn_current_counter)
|
||||
beacon->cntdwn_current_counter = counter;
|
||||
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_csa_set_counter);
|
||||
EXPORT_SYMBOL(ieee80211_beacon_set_cntdwn);
|
||||
|
||||
bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
|
||||
bool ieee80211_beacon_cntdwn_is_complete(struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
struct beacon_data *beacon = NULL;
|
||||
|
@ -4688,20 +4688,21 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (!beacon->csa_counter_offsets[0])
|
||||
if (!beacon->cntdwn_counter_offsets[0])
|
||||
goto out;
|
||||
|
||||
if (WARN_ON_ONCE(beacon->csa_counter_offsets[0] > beacon_data_len))
|
||||
if (WARN_ON_ONCE(beacon->cntdwn_counter_offsets[0] > beacon_data_len))
|
||||
goto out;
|
||||
|
||||
if (beacon_data[beacon->csa_counter_offsets[0]] == 1)
|
||||
if (beacon_data[beacon->cntdwn_counter_offsets[0]] == 1)
|
||||
ret = true;
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_csa_is_complete);
|
||||
EXPORT_SYMBOL(ieee80211_beacon_cntdwn_is_complete);
|
||||
|
||||
static int ieee80211_beacon_protect(struct sk_buff *skb,
|
||||
struct ieee80211_local *local,
|
||||
|
@ -4761,11 +4762,11 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
|
|||
|
||||
beacon = rcu_dereference(ap->beacon);
|
||||
if (beacon) {
|
||||
if (beacon->csa_counter_offsets[0]) {
|
||||
if (beacon->cntdwn_counter_offsets[0]) {
|
||||
if (!is_template)
|
||||
__ieee80211_csa_update_counter(beacon);
|
||||
ieee80211_beacon_update_cntdwn(vif);
|
||||
|
||||
ieee80211_set_csa(sdata, beacon);
|
||||
ieee80211_set_beacon_cntdwn(sdata, beacon);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4809,11 +4810,11 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
|
|||
if (!beacon)
|
||||
goto out;
|
||||
|
||||
if (beacon->csa_counter_offsets[0]) {
|
||||
if (beacon->cntdwn_counter_offsets[0]) {
|
||||
if (!is_template)
|
||||
__ieee80211_csa_update_counter(beacon);
|
||||
__ieee80211_beacon_update_cntdwn(beacon);
|
||||
|
||||
ieee80211_set_csa(sdata, beacon);
|
||||
ieee80211_set_beacon_cntdwn(sdata, beacon);
|
||||
}
|
||||
|
||||
skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
|
||||
|
@ -4833,16 +4834,16 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
|
|||
if (!beacon)
|
||||
goto out;
|
||||
|
||||
if (beacon->csa_counter_offsets[0]) {
|
||||
if (beacon->cntdwn_counter_offsets[0]) {
|
||||
if (!is_template)
|
||||
/* TODO: For mesh csa_counter is in TU, so
|
||||
* decrementing it by one isn't correct, but
|
||||
* for now we leave it consistent with overall
|
||||
* mac80211's behavior.
|
||||
*/
|
||||
__ieee80211_csa_update_counter(beacon);
|
||||
__ieee80211_beacon_update_cntdwn(beacon);
|
||||
|
||||
ieee80211_set_csa(sdata, beacon);
|
||||
ieee80211_set_beacon_cntdwn(sdata, beacon);
|
||||
}
|
||||
|
||||
if (ifmsh->sync_ops)
|
||||
|
@ -4874,13 +4875,13 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
|
|||
if (offs && beacon) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; i++) {
|
||||
u16 csa_off = beacon->csa_counter_offsets[i];
|
||||
for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; i++) {
|
||||
u16 csa_off = beacon->cntdwn_counter_offsets[i];
|
||||
|
||||
if (!csa_off)
|
||||
continue;
|
||||
|
||||
offs->csa_counter_offs[i] = csa_off_base + csa_off;
|
||||
offs->cntdwn_counter_offs[i] = csa_off_base + csa_off;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -957,7 +957,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
|
|||
if (!ht_cap->ht_supported &&
|
||||
chandef->chan->band != NL80211_BAND_6GHZ)
|
||||
return false;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||
prohibited_flags |= IEEE80211_CHAN_NO_20MHZ;
|
||||
width = 20;
|
||||
|
@ -983,7 +983,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
|
|||
if (chandef->chan->band != NL80211_BAND_6GHZ &&
|
||||
cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
|
||||
return false;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case NL80211_CHAN_WIDTH_80:
|
||||
prohibited_flags |= IEEE80211_CHAN_NO_80MHZ;
|
||||
width = 80;
|
||||
|
|
|
@ -466,8 +466,8 @@ extern struct work_struct cfg80211_disconnect_work;
|
|||
*
|
||||
* Checks if chandef is usable and we can/need start CAC on such channel.
|
||||
*
|
||||
* Return: Return true if all channels available and at least
|
||||
* one channel require CAC (NL80211_DFS_USABLE)
|
||||
* Return: true if all channels available and at least
|
||||
* one channel requires CAC (NL80211_DFS_USABLE)
|
||||
*/
|
||||
bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
|
||||
const struct cfg80211_chan_def *chandef);
|
||||
|
|
|
@ -941,7 +941,7 @@ void cfg80211_cac_event(struct net_device *netdev,
|
|||
sizeof(struct cfg80211_chan_def));
|
||||
queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk);
|
||||
cfg80211_sched_dfs_chan_update(rdev);
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case NL80211_RADAR_CAC_ABORTED:
|
||||
wdev->cac_started = false;
|
||||
break;
|
||||
|
|
|
@ -336,6 +336,13 @@ static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = {
|
|||
.len = NL80211_MAX_SUPP_HT_RATES },
|
||||
[NL80211_TXRATE_VHT] = NLA_POLICY_EXACT_LEN_WARN(sizeof(struct nl80211_txrate_vht)),
|
||||
[NL80211_TXRATE_GI] = { .type = NLA_U8 },
|
||||
[NL80211_TXRATE_HE] = NLA_POLICY_EXACT_LEN(sizeof(struct nl80211_txrate_he)),
|
||||
[NL80211_TXRATE_HE_GI] = NLA_POLICY_RANGE(NLA_U8,
|
||||
NL80211_RATE_INFO_HE_GI_0_8,
|
||||
NL80211_RATE_INFO_HE_GI_3_2),
|
||||
[NL80211_TXRATE_HE_LTF] = NLA_POLICY_RANGE(NLA_U8,
|
||||
NL80211_RATE_INFO_HE_1XLTF,
|
||||
NL80211_RATE_INFO_HE_4XLTF),
|
||||
};
|
||||
|
||||
static const struct nla_policy
|
||||
|
@ -539,7 +546,10 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
|||
[NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
|
||||
[NL80211_ATTR_WDEV] = { .type = NLA_U64 },
|
||||
[NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_AUTH_DATA] = { .type = NLA_BINARY, },
|
||||
|
||||
/* need to include at least Auth Transaction and Status Code */
|
||||
[NL80211_ATTR_AUTH_DATA] = NLA_POLICY_MIN_LEN(4),
|
||||
|
||||
[NL80211_ATTR_VHT_CAPABILITY] = NLA_POLICY_EXACT_LEN_WARN(NL80211_VHT_CAPABILITY_LEN),
|
||||
[NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_P2P_CTWINDOW] = NLA_POLICY_MAX(NLA_U8, 127),
|
||||
|
@ -561,23 +571,30 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
|||
[NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
|
||||
.len = IEEE80211_MAX_DATA_LEN },
|
||||
[NL80211_ATTR_CRIT_PROT_ID] = { .type = NLA_U16 },
|
||||
[NL80211_ATTR_MAX_CRIT_PROT_DURATION] = { .type = NLA_U16 },
|
||||
[NL80211_ATTR_MAX_CRIT_PROT_DURATION] =
|
||||
NLA_POLICY_MAX(NLA_U16, NL80211_CRIT_PROTO_MAX_DURATION),
|
||||
[NL80211_ATTR_PEER_AID] =
|
||||
NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
|
||||
[NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },
|
||||
[NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
|
||||
[NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_BINARY },
|
||||
[NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_BINARY },
|
||||
[NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY },
|
||||
[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY },
|
||||
[NL80211_ATTR_CNTDWN_OFFS_BEACON] = { .type = NLA_BINARY },
|
||||
[NL80211_ATTR_CNTDWN_OFFS_PRESP] = { .type = NLA_BINARY },
|
||||
[NL80211_ATTR_STA_SUPPORTED_CHANNELS] = NLA_POLICY_MIN_LEN(2),
|
||||
/*
|
||||
* The value of the Length field of the Supported Operating
|
||||
* Classes element is between 2 and 253.
|
||||
*/
|
||||
[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] =
|
||||
NLA_POLICY_RANGE(NLA_BINARY, 2, 253),
|
||||
[NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
|
||||
[NL80211_ATTR_OPMODE_NOTIF] = { .type = NLA_U8 },
|
||||
[NL80211_ATTR_VENDOR_ID] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
|
||||
[NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY,
|
||||
.len = IEEE80211_QOS_MAP_LEN_MAX },
|
||||
[NL80211_ATTR_QOS_MAP] = NLA_POLICY_RANGE(NLA_BINARY,
|
||||
IEEE80211_QOS_MAP_LEN_MIN,
|
||||
IEEE80211_QOS_MAP_LEN_MAX),
|
||||
[NL80211_ATTR_MAC_HINT] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN),
|
||||
[NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
|
||||
|
@ -625,15 +642,17 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
|||
.len = FILS_ERP_MAX_RRK_LEN },
|
||||
[NL80211_ATTR_FILS_CACHE_ID] = NLA_POLICY_EXACT_LEN_WARN(2),
|
||||
[NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
|
||||
[NL80211_ATTR_PMKR0_NAME] = NLA_POLICY_EXACT_LEN(WLAN_PMK_NAME_LEN),
|
||||
[NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },
|
||||
[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG },
|
||||
|
||||
[NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_HE_CAPABILITY] = { .type = NLA_BINARY,
|
||||
.len = NL80211_HE_MAX_CAPABILITY_LEN },
|
||||
|
||||
[NL80211_ATTR_HE_CAPABILITY] =
|
||||
NLA_POLICY_RANGE(NLA_BINARY,
|
||||
NL80211_HE_MIN_CAPABILITY_LEN,
|
||||
NL80211_HE_MAX_CAPABILITY_LEN),
|
||||
[NL80211_ATTR_FTM_RESPONDER] =
|
||||
NLA_POLICY_NESTED(nl80211_ftm_responder_policy),
|
||||
[NL80211_ATTR_TIMEOUT] = NLA_POLICY_MIN(NLA_U32, 1),
|
||||
|
@ -736,7 +755,7 @@ nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
|
|||
.type = NLA_BINARY,
|
||||
.len = NL80211_KCK_EXT_LEN
|
||||
},
|
||||
[NL80211_REKEY_DATA_REPLAY_CTR] = NLA_POLICY_EXACT_LEN_WARN(NL80211_REPLAY_CTR_LEN),
|
||||
[NL80211_REKEY_DATA_REPLAY_CTR] = NLA_POLICY_EXACT_LEN(NL80211_REPLAY_CTR_LEN),
|
||||
[NL80211_REKEY_DATA_AKM] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
|
@ -776,7 +795,8 @@ nl80211_bss_select_policy[NL80211_BSS_SELECT_ATTR_MAX + 1] = {
|
|||
/* policy for NAN function attributes */
|
||||
static const struct nla_policy
|
||||
nl80211_nan_func_policy[NL80211_NAN_FUNC_ATTR_MAX + 1] = {
|
||||
[NL80211_NAN_FUNC_TYPE] = { .type = NLA_U8 },
|
||||
[NL80211_NAN_FUNC_TYPE] =
|
||||
NLA_POLICY_MAX(NLA_U8, NL80211_NAN_FUNC_MAX_TYPE),
|
||||
[NL80211_NAN_FUNC_SERVICE_ID] = {
|
||||
.len = NL80211_NAN_FUNC_SERVICE_ID_LEN },
|
||||
[NL80211_NAN_FUNC_PUBLISH_TYPE] = { .type = NLA_U8 },
|
||||
|
@ -2105,7 +2125,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
state->split_start++;
|
||||
if (state->split)
|
||||
break;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case 1:
|
||||
if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES,
|
||||
sizeof(u32) * rdev->wiphy.n_cipher_suites,
|
||||
|
@ -2152,7 +2172,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
state->split_start++;
|
||||
if (state->split)
|
||||
break;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case 2:
|
||||
if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES,
|
||||
rdev->wiphy.interface_modes))
|
||||
|
@ -2160,7 +2180,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
state->split_start++;
|
||||
if (state->split)
|
||||
break;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case 3:
|
||||
nl_bands = nla_nest_start_noflag(msg,
|
||||
NL80211_ATTR_WIPHY_BANDS);
|
||||
|
@ -2187,7 +2207,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
state->chan_start++;
|
||||
if (state->split)
|
||||
break;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
default:
|
||||
/* add frequencies */
|
||||
nl_freqs = nla_nest_start_noflag(msg,
|
||||
|
@ -2242,7 +2262,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
state->split_start++;
|
||||
if (state->split)
|
||||
break;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case 4:
|
||||
nl_cmds = nla_nest_start_noflag(msg,
|
||||
NL80211_ATTR_SUPPORTED_COMMANDS);
|
||||
|
@ -2271,7 +2291,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
state->split_start++;
|
||||
if (state->split)
|
||||
break;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case 5:
|
||||
if (rdev->ops->remain_on_channel &&
|
||||
(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) &&
|
||||
|
@ -2289,7 +2309,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
state->split_start++;
|
||||
if (state->split)
|
||||
break;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case 6:
|
||||
#ifdef CONFIG_PM
|
||||
if (nl80211_send_wowlan(msg, rdev, state->split))
|
||||
|
@ -2300,7 +2320,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
#else
|
||||
state->split_start++;
|
||||
#endif
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case 7:
|
||||
if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
|
||||
rdev->wiphy.software_iftypes))
|
||||
|
@ -2313,7 +2333,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
state->split_start++;
|
||||
if (state->split)
|
||||
break;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case 8:
|
||||
if ((rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) &&
|
||||
nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME,
|
||||
|
@ -4417,21 +4437,106 @@ static bool vht_set_mcs_mask(struct ieee80211_supported_band *sband,
|
|||
return true;
|
||||
}
|
||||
|
||||
static u16 he_mcs_map_to_mcs_mask(u8 he_mcs_map)
|
||||
{
|
||||
switch (he_mcs_map) {
|
||||
case IEEE80211_HE_MCS_NOT_SUPPORTED:
|
||||
return 0;
|
||||
case IEEE80211_HE_MCS_SUPPORT_0_7:
|
||||
return 0x00FF;
|
||||
case IEEE80211_HE_MCS_SUPPORT_0_9:
|
||||
return 0x03FF;
|
||||
case IEEE80211_HE_MCS_SUPPORT_0_11:
|
||||
return 0xFFF;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void he_build_mcs_mask(u16 he_mcs_map,
|
||||
u16 he_mcs_mask[NL80211_HE_NSS_MAX])
|
||||
{
|
||||
u8 nss;
|
||||
|
||||
for (nss = 0; nss < NL80211_HE_NSS_MAX; nss++) {
|
||||
he_mcs_mask[nss] = he_mcs_map_to_mcs_mask(he_mcs_map & 0x03);
|
||||
he_mcs_map >>= 2;
|
||||
}
|
||||
}
|
||||
|
||||
static u16 he_get_txmcsmap(struct genl_info *info,
|
||||
const struct ieee80211_sta_he_cap *he_cap)
|
||||
{
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
__le16 tx_mcs;
|
||||
|
||||
switch (wdev->chandef.width) {
|
||||
case NL80211_CHAN_WIDTH_80P80:
|
||||
tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80p80;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_160:
|
||||
tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_160;
|
||||
break;
|
||||
default:
|
||||
tx_mcs = he_cap->he_mcs_nss_supp.tx_mcs_80;
|
||||
break;
|
||||
}
|
||||
return le16_to_cpu(tx_mcs);
|
||||
}
|
||||
|
||||
static bool he_set_mcs_mask(struct genl_info *info,
|
||||
struct wireless_dev *wdev,
|
||||
struct ieee80211_supported_band *sband,
|
||||
struct nl80211_txrate_he *txrate,
|
||||
u16 mcs[NL80211_HE_NSS_MAX])
|
||||
{
|
||||
const struct ieee80211_sta_he_cap *he_cap;
|
||||
u16 tx_mcs_mask[NL80211_HE_NSS_MAX] = {};
|
||||
u16 tx_mcs_map = 0;
|
||||
u8 i;
|
||||
|
||||
he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
|
||||
if (!he_cap)
|
||||
return false;
|
||||
|
||||
memset(mcs, 0, sizeof(u16) * NL80211_HE_NSS_MAX);
|
||||
|
||||
tx_mcs_map = he_get_txmcsmap(info, he_cap);
|
||||
|
||||
/* Build he_mcs_mask from HE capabilities */
|
||||
he_build_mcs_mask(tx_mcs_map, tx_mcs_mask);
|
||||
|
||||
for (i = 0; i < NL80211_HE_NSS_MAX; i++) {
|
||||
if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i])
|
||||
mcs[i] = txrate->mcs[i];
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,
|
||||
struct nlattr *attrs[],
|
||||
enum nl80211_attrs attr,
|
||||
struct cfg80211_bitrate_mask *mask)
|
||||
struct cfg80211_bitrate_mask *mask,
|
||||
struct net_device *dev)
|
||||
{
|
||||
struct nlattr *tb[NL80211_TXRATE_MAX + 1];
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
int rem, i;
|
||||
struct nlattr *tx_rates;
|
||||
struct ieee80211_supported_band *sband;
|
||||
u16 vht_tx_mcs_map;
|
||||
u16 vht_tx_mcs_map, he_tx_mcs_map;
|
||||
|
||||
memset(mask, 0, sizeof(*mask));
|
||||
/* Default to all rates enabled */
|
||||
for (i = 0; i < NUM_NL80211_BANDS; i++) {
|
||||
const struct ieee80211_sta_he_cap *he_cap;
|
||||
|
||||
sband = rdev->wiphy.bands[i];
|
||||
|
||||
if (!sband)
|
||||
|
@ -4447,6 +4552,16 @@ static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,
|
|||
|
||||
vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
|
||||
vht_build_mcs_mask(vht_tx_mcs_map, mask->control[i].vht_mcs);
|
||||
|
||||
he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype);
|
||||
if (!he_cap)
|
||||
continue;
|
||||
|
||||
he_tx_mcs_map = he_get_txmcsmap(info, he_cap);
|
||||
he_build_mcs_mask(he_tx_mcs_map, mask->control[i].he_mcs);
|
||||
|
||||
mask->control[i].he_gi = 0xFF;
|
||||
mask->control[i].he_ltf = 0xFF;
|
||||
}
|
||||
|
||||
/* if no rates are given set it back to the defaults */
|
||||
|
@ -4502,13 +4617,25 @@ static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,
|
|||
if (mask->control[band].gi > NL80211_TXRATE_FORCE_LGI)
|
||||
return -EINVAL;
|
||||
}
|
||||
if (tb[NL80211_TXRATE_HE] &&
|
||||
!he_set_mcs_mask(info, wdev, sband,
|
||||
nla_data(tb[NL80211_TXRATE_HE]),
|
||||
mask->control[band].he_mcs))
|
||||
return -EINVAL;
|
||||
if (tb[NL80211_TXRATE_HE_GI])
|
||||
mask->control[band].he_gi =
|
||||
nla_get_u8(tb[NL80211_TXRATE_HE_GI]);
|
||||
if (tb[NL80211_TXRATE_HE_LTF])
|
||||
mask->control[band].he_ltf =
|
||||
nla_get_u8(tb[NL80211_TXRATE_HE_LTF]);
|
||||
|
||||
if (mask->control[band].legacy == 0) {
|
||||
/* don't allow empty legacy rates if HT or VHT
|
||||
/* don't allow empty legacy rates if HT, VHT or HE
|
||||
* are not even supported.
|
||||
*/
|
||||
if (!(rdev->wiphy.bands[band]->ht_cap.ht_supported ||
|
||||
rdev->wiphy.bands[band]->vht_cap.vht_supported))
|
||||
rdev->wiphy.bands[band]->vht_cap.vht_supported ||
|
||||
ieee80211_get_he_iftype_cap(sband, wdev->iftype)))
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
|
||||
|
@ -4519,6 +4646,10 @@ static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,
|
|||
if (mask->control[band].vht_mcs[i])
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < NL80211_HE_NSS_MAX; i++)
|
||||
if (mask->control[band].he_mcs[i])
|
||||
goto out;
|
||||
|
||||
/* legacy and mcs rates may not be both empty */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -4829,8 +4960,9 @@ static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev,
|
|||
return false;
|
||||
return true;
|
||||
case NL80211_CMD_START_AP:
|
||||
/* SAE not supported yet */
|
||||
if (auth_type == NL80211_AUTHTYPE_SAE)
|
||||
if (!wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_SAE_OFFLOAD_AP) &&
|
||||
auth_type == NL80211_AUTHTYPE_SAE)
|
||||
return false;
|
||||
/* FILS not supported yet */
|
||||
if (auth_type == NL80211_AUTHTYPE_FILS_SK ||
|
||||
|
@ -4894,8 +5026,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
|||
params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
|
||||
params.ssid_len =
|
||||
nla_len(info->attrs[NL80211_ATTR_SSID]);
|
||||
if (params.ssid_len == 0 ||
|
||||
params.ssid_len > IEEE80211_MAX_SSID_LEN)
|
||||
if (params.ssid_len == 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -4964,7 +5095,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
|||
if (info->attrs[NL80211_ATTR_TX_RATES]) {
|
||||
err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
|
||||
NL80211_ATTR_TX_RATES,
|
||||
¶ms.beacon_rate);
|
||||
¶ms.beacon_rate,
|
||||
dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -5205,7 +5337,7 @@ bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
|
|||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case RATE_INFO_BW_20:
|
||||
rate_flg = 0;
|
||||
break;
|
||||
|
@ -5835,11 +5967,9 @@ static int nl80211_parse_sta_channel_info(struct genl_info *info,
|
|||
nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
|
||||
/*
|
||||
* Need to include at least one (first channel, number of
|
||||
* channels) tuple for each subband, and must have proper
|
||||
* tuples for the rest of the data as well.
|
||||
* channels) tuple for each subband (checked in policy),
|
||||
* and must have proper tuples for the rest of the data as well.
|
||||
*/
|
||||
if (params->supported_channels_len < 2)
|
||||
return -EINVAL;
|
||||
if (params->supported_channels_len % 2)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -5849,13 +5979,6 @@ static int nl80211_parse_sta_channel_info(struct genl_info *info,
|
|||
nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
|
||||
params->supported_oper_classes_len =
|
||||
nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
|
||||
/*
|
||||
* The value of the Length field of the Supported Operating
|
||||
* Classes element is between 2 and 253.
|
||||
*/
|
||||
if (params->supported_oper_classes_len < 2 ||
|
||||
params->supported_oper_classes_len > 253)
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -5878,9 +6001,6 @@ static int nl80211_set_station_tdls(struct genl_info *info,
|
|||
nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
|
||||
params->he_capa_len =
|
||||
nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
|
||||
|
||||
if (params->he_capa_len < NL80211_HE_MIN_CAPABILITY_LEN)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = nl80211_parse_sta_channel_info(info, params);
|
||||
|
@ -6139,10 +6259,6 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
|
|||
nla_data(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
|
||||
params.he_capa_len =
|
||||
nla_len(info->attrs[NL80211_ATTR_HE_CAPABILITY]);
|
||||
|
||||
/* max len is validated in nla policy */
|
||||
if (params.he_capa_len < NL80211_HE_MIN_CAPABILITY_LEN)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_HE_6GHZ_CAPABILITY])
|
||||
|
@ -8414,23 +8530,14 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|||
}
|
||||
|
||||
if (ssid) {
|
||||
if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) {
|
||||
err = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
memcpy(request->match_sets[i].ssid.ssid,
|
||||
nla_data(ssid), nla_len(ssid));
|
||||
request->match_sets[i].ssid.ssid_len =
|
||||
nla_len(ssid);
|
||||
}
|
||||
if (bssid) {
|
||||
if (nla_len(bssid) != ETH_ALEN) {
|
||||
err = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
if (bssid)
|
||||
memcpy(request->match_sets[i].bssid,
|
||||
nla_data(bssid), ETH_ALEN);
|
||||
}
|
||||
|
||||
/* special attribute - old implementation w/a */
|
||||
request->match_sets[i].rssi_thold = default_match_rssi;
|
||||
|
@ -8785,10 +8892,10 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
if (!csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON])
|
||||
if (!csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON])
|
||||
return -EINVAL;
|
||||
|
||||
len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]);
|
||||
len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
|
||||
if (!len || (len % sizeof(u16)))
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -8799,7 +8906,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
|
|||
return -EINVAL;
|
||||
|
||||
params.counter_offsets_beacon =
|
||||
nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]);
|
||||
nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
|
||||
|
||||
/* sanity checks - counters should fit and be the same */
|
||||
for (i = 0; i < params.n_counter_offsets_beacon; i++) {
|
||||
|
@ -8812,8 +8919,8 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]) {
|
||||
len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]);
|
||||
if (csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]) {
|
||||
len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
|
||||
if (!len || (len % sizeof(u16)))
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -8824,7 +8931,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
|
|||
return -EINVAL;
|
||||
|
||||
params.counter_offsets_presp =
|
||||
nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]);
|
||||
nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
|
||||
|
||||
/* sanity checks - counters should fit and be the same */
|
||||
for (i = 0; i < params.n_counter_offsets_presp; i++) {
|
||||
|
@ -9307,9 +9414,6 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
|
|||
return -EINVAL;
|
||||
auth_data = nla_data(info->attrs[NL80211_ATTR_AUTH_DATA]);
|
||||
auth_data_len = nla_len(info->attrs[NL80211_ATTR_AUTH_DATA]);
|
||||
/* need to include at least Auth Transaction and Status Code */
|
||||
if (auth_data_len < 4)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
|
||||
|
@ -9449,7 +9553,9 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
|
|||
|
||||
if (info->attrs[NL80211_ATTR_SAE_PASSWORD]) {
|
||||
if (!wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_SAE_OFFLOAD))
|
||||
NL80211_EXT_FEATURE_SAE_OFFLOAD) &&
|
||||
!wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_SAE_OFFLOAD_AP))
|
||||
return -EINVAL;
|
||||
settings->sae_pwd =
|
||||
nla_data(info->attrs[NL80211_ATTR_SAE_PASSWORD]);
|
||||
|
@ -10796,7 +10902,8 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
|
|||
return -EOPNOTSUPP;
|
||||
|
||||
err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
|
||||
NL80211_ATTR_TX_RATES, &mask);
|
||||
NL80211_ATTR_TX_RATES, &mask,
|
||||
dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -11404,7 +11511,8 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
|
|||
if (info->attrs[NL80211_ATTR_TX_RATES]) {
|
||||
err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
|
||||
NL80211_ATTR_TX_RATES,
|
||||
&setup.beacon_rate);
|
||||
&setup.beacon_rate,
|
||||
dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -12356,8 +12464,6 @@ static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
|
|||
if (!tb[NL80211_REKEY_DATA_REPLAY_CTR] || !tb[NL80211_REKEY_DATA_KEK] ||
|
||||
!tb[NL80211_REKEY_DATA_KCK])
|
||||
return -EINVAL;
|
||||
if (nla_len(tb[NL80211_REKEY_DATA_REPLAY_CTR]) != NL80211_REPLAY_CTR_LEN)
|
||||
return -ERANGE;
|
||||
if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN &&
|
||||
!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK &&
|
||||
nla_len(tb[NL80211_REKEY_DATA_KEK]) == NL80211_KEK_EXT_LEN))
|
||||
|
@ -12682,8 +12788,7 @@ static int nl80211_nan_add_func(struct sk_buff *skb,
|
|||
|
||||
func->cookie = cfg80211_assign_cookie(rdev);
|
||||
|
||||
if (!tb[NL80211_NAN_FUNC_TYPE] ||
|
||||
nla_get_u8(tb[NL80211_NAN_FUNC_TYPE]) > NL80211_NAN_FUNC_MAX_TYPE) {
|
||||
if (!tb[NL80211_NAN_FUNC_TYPE]) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -13173,9 +13278,6 @@ static int nl80211_crit_protocol_start(struct sk_buff *skb,
|
|||
duration =
|
||||
nla_get_u16(info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION]);
|
||||
|
||||
if (duration > NL80211_CRIT_PROTO_MAX_DURATION)
|
||||
return -ERANGE;
|
||||
|
||||
ret = rdev_crit_proto_start(rdev, wdev, proto, duration);
|
||||
if (!ret)
|
||||
rdev->crit_proto_nlportid = info->snd_portid;
|
||||
|
@ -13560,8 +13662,7 @@ static int nl80211_set_qos_map(struct sk_buff *skb,
|
|||
pos = nla_data(info->attrs[NL80211_ATTR_QOS_MAP]);
|
||||
len = nla_len(info->attrs[NL80211_ATTR_QOS_MAP]);
|
||||
|
||||
if (len % 2 || len < IEEE80211_QOS_MAP_LEN_MIN ||
|
||||
len > IEEE80211_QOS_MAP_LEN_MAX)
|
||||
if (len % 2)
|
||||
return -EINVAL;
|
||||
|
||||
qos_map = kzalloc(sizeof(struct cfg80211_qos_map), GFP_KERNEL);
|
||||
|
@ -13829,17 +13930,9 @@ static int nl80211_set_pmk(struct sk_buff *skb, struct genl_info *info)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_PMKR0_NAME]) {
|
||||
int r0_name_len = nla_len(info->attrs[NL80211_ATTR_PMKR0_NAME]);
|
||||
|
||||
if (r0_name_len != WLAN_PMK_NAME_LEN) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_PMKR0_NAME])
|
||||
pmk_conf.pmk_r0_name =
|
||||
nla_data(info->attrs[NL80211_ATTR_PMKR0_NAME]);
|
||||
}
|
||||
|
||||
ret = rdev_set_pmk(rdev, dev, &pmk_conf);
|
||||
out:
|
||||
|
@ -13898,8 +13991,7 @@ static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
if (info->attrs[NL80211_ATTR_SSID]) {
|
||||
params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
|
||||
if (params.ssid.ssid_len == 0 ||
|
||||
params.ssid.ssid_len > IEEE80211_MAX_SSID_LEN)
|
||||
if (params.ssid.ssid_len == 0)
|
||||
return -EINVAL;
|
||||
memcpy(params.ssid.ssid,
|
||||
nla_data(info->attrs[NL80211_ATTR_SSID]),
|
||||
|
@ -14200,7 +14292,7 @@ static int parse_tid_conf(struct cfg80211_registered_device *rdev,
|
|||
if (tid_conf->txrate_type != NL80211_TX_RATE_AUTOMATIC) {
|
||||
attr = NL80211_TID_CONFIG_ATTR_TX_RATE;
|
||||
err = nl80211_parse_tx_bitrate_mask(info, attrs, attr,
|
||||
&tid_conf->txrate_mask);
|
||||
&tid_conf->txrate_mask, dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
|
|
@ -1594,7 +1594,7 @@ freq_reg_info_regd(u32 center_freq,
|
|||
|
||||
/*
|
||||
* We only need to know if one frequency rule was
|
||||
* was in center_freq's band, that's enough, so lets
|
||||
* in center_freq's band, that's enough, so let's
|
||||
* not overwrite it once found
|
||||
*/
|
||||
if (!band_rule_found)
|
||||
|
@ -1691,57 +1691,18 @@ static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd
|
|||
return bw_flags;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that right now we assume the desired channel bandwidth
|
||||
* is always 20 MHz for each individual channel (HT40 uses 20 MHz
|
||||
* per channel, the primary and the extension channel).
|
||||
*/
|
||||
static void handle_channel(struct wiphy *wiphy,
|
||||
enum nl80211_reg_initiator initiator,
|
||||
struct ieee80211_channel *chan)
|
||||
static void handle_channel_single_rule(struct wiphy *wiphy,
|
||||
enum nl80211_reg_initiator initiator,
|
||||
struct ieee80211_channel *chan,
|
||||
u32 flags,
|
||||
struct regulatory_request *lr,
|
||||
struct wiphy *request_wiphy,
|
||||
const struct ieee80211_reg_rule *reg_rule)
|
||||
{
|
||||
u32 flags, bw_flags = 0;
|
||||
const struct ieee80211_reg_rule *reg_rule = NULL;
|
||||
u32 bw_flags = 0;
|
||||
const struct ieee80211_power_rule *power_rule = NULL;
|
||||
struct wiphy *request_wiphy = NULL;
|
||||
struct regulatory_request *lr = get_last_request();
|
||||
const struct ieee80211_regdomain *regd;
|
||||
|
||||
request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx);
|
||||
|
||||
flags = chan->orig_flags;
|
||||
|
||||
reg_rule = freq_reg_info(wiphy, ieee80211_channel_to_khz(chan));
|
||||
if (IS_ERR(reg_rule)) {
|
||||
/*
|
||||
* We will disable all channels that do not match our
|
||||
* received regulatory rule unless the hint is coming
|
||||
* from a Country IE and the Country IE had no information
|
||||
* about a band. The IEEE 802.11 spec allows for an AP
|
||||
* to send only a subset of the regulatory rules allowed,
|
||||
* so an AP in the US that only supports 2.4 GHz may only send
|
||||
* a country IE with information for the 2.4 GHz band
|
||||
* while 5 GHz is still supported.
|
||||
*/
|
||||
if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
|
||||
PTR_ERR(reg_rule) == -ERANGE)
|
||||
return;
|
||||
|
||||
if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
|
||||
request_wiphy && request_wiphy == wiphy &&
|
||||
request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
|
||||
pr_debug("Disabling freq %d.%03d MHz for good\n",
|
||||
chan->center_freq, chan->freq_offset);
|
||||
chan->orig_flags |= IEEE80211_CHAN_DISABLED;
|
||||
chan->flags = chan->orig_flags;
|
||||
} else {
|
||||
pr_debug("Disabling freq %d.%03d MHz\n",
|
||||
chan->center_freq, chan->freq_offset);
|
||||
chan->flags |= IEEE80211_CHAN_DISABLED;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
regd = reg_get_regdomain(wiphy);
|
||||
|
||||
power_rule = ®_rule->power_rule;
|
||||
|
@ -1803,6 +1764,204 @@ static void handle_channel(struct wiphy *wiphy,
|
|||
chan->max_power = chan->max_reg_power;
|
||||
}
|
||||
|
||||
static void handle_channel_adjacent_rules(struct wiphy *wiphy,
|
||||
enum nl80211_reg_initiator initiator,
|
||||
struct ieee80211_channel *chan,
|
||||
u32 flags,
|
||||
struct regulatory_request *lr,
|
||||
struct wiphy *request_wiphy,
|
||||
const struct ieee80211_reg_rule *rrule1,
|
||||
const struct ieee80211_reg_rule *rrule2,
|
||||
struct ieee80211_freq_range *comb_range)
|
||||
{
|
||||
u32 bw_flags1 = 0;
|
||||
u32 bw_flags2 = 0;
|
||||
const struct ieee80211_power_rule *power_rule1 = NULL;
|
||||
const struct ieee80211_power_rule *power_rule2 = NULL;
|
||||
const struct ieee80211_regdomain *regd;
|
||||
|
||||
regd = reg_get_regdomain(wiphy);
|
||||
|
||||
power_rule1 = &rrule1->power_rule;
|
||||
power_rule2 = &rrule2->power_rule;
|
||||
bw_flags1 = reg_rule_to_chan_bw_flags(regd, rrule1, chan);
|
||||
bw_flags2 = reg_rule_to_chan_bw_flags(regd, rrule2, chan);
|
||||
|
||||
if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
|
||||
request_wiphy && request_wiphy == wiphy &&
|
||||
request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
|
||||
/* This guarantees the driver's requested regulatory domain
|
||||
* will always be used as a base for further regulatory
|
||||
* settings
|
||||
*/
|
||||
chan->flags =
|
||||
map_regdom_flags(rrule1->flags) |
|
||||
map_regdom_flags(rrule2->flags) |
|
||||
bw_flags1 |
|
||||
bw_flags2;
|
||||
chan->orig_flags = chan->flags;
|
||||
chan->max_antenna_gain =
|
||||
min_t(int, MBI_TO_DBI(power_rule1->max_antenna_gain),
|
||||
MBI_TO_DBI(power_rule2->max_antenna_gain));
|
||||
chan->orig_mag = chan->max_antenna_gain;
|
||||
chan->max_reg_power =
|
||||
min_t(int, MBM_TO_DBM(power_rule1->max_eirp),
|
||||
MBM_TO_DBM(power_rule2->max_eirp));
|
||||
chan->max_power = chan->max_reg_power;
|
||||
chan->orig_mpwr = chan->max_reg_power;
|
||||
|
||||
if (chan->flags & IEEE80211_CHAN_RADAR) {
|
||||
chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
|
||||
if (rrule1->dfs_cac_ms || rrule2->dfs_cac_ms)
|
||||
chan->dfs_cac_ms = max_t(unsigned int,
|
||||
rrule1->dfs_cac_ms,
|
||||
rrule2->dfs_cac_ms);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
chan->dfs_state = NL80211_DFS_USABLE;
|
||||
chan->dfs_state_entered = jiffies;
|
||||
|
||||
chan->beacon_found = false;
|
||||
chan->flags = flags | bw_flags1 | bw_flags2 |
|
||||
map_regdom_flags(rrule1->flags) |
|
||||
map_regdom_flags(rrule2->flags);
|
||||
|
||||
/* reg_rule_to_chan_bw_flags may forbids 10 and forbids 20 MHz
|
||||
* (otherwise no adj. rule case), recheck therefore
|
||||
*/
|
||||
if (cfg80211_does_bw_fit_range(comb_range,
|
||||
ieee80211_channel_to_khz(chan),
|
||||
MHZ_TO_KHZ(10)))
|
||||
chan->flags &= ~IEEE80211_CHAN_NO_10MHZ;
|
||||
if (cfg80211_does_bw_fit_range(comb_range,
|
||||
ieee80211_channel_to_khz(chan),
|
||||
MHZ_TO_KHZ(20)))
|
||||
chan->flags &= ~IEEE80211_CHAN_NO_20MHZ;
|
||||
|
||||
chan->max_antenna_gain =
|
||||
min_t(int, chan->orig_mag,
|
||||
min_t(int,
|
||||
MBI_TO_DBI(power_rule1->max_antenna_gain),
|
||||
MBI_TO_DBI(power_rule2->max_antenna_gain)));
|
||||
chan->max_reg_power = min_t(int,
|
||||
MBM_TO_DBM(power_rule1->max_eirp),
|
||||
MBM_TO_DBM(power_rule2->max_eirp));
|
||||
|
||||
if (chan->flags & IEEE80211_CHAN_RADAR) {
|
||||
if (rrule1->dfs_cac_ms || rrule2->dfs_cac_ms)
|
||||
chan->dfs_cac_ms = max_t(unsigned int,
|
||||
rrule1->dfs_cac_ms,
|
||||
rrule2->dfs_cac_ms);
|
||||
else
|
||||
chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
|
||||
}
|
||||
|
||||
if (chan->orig_mpwr) {
|
||||
/* Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER
|
||||
* will always follow the passed country IE power settings.
|
||||
*/
|
||||
if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
|
||||
wiphy->regulatory_flags & REGULATORY_COUNTRY_IE_FOLLOW_POWER)
|
||||
chan->max_power = chan->max_reg_power;
|
||||
else
|
||||
chan->max_power = min(chan->orig_mpwr,
|
||||
chan->max_reg_power);
|
||||
} else {
|
||||
chan->max_power = chan->max_reg_power;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note that right now we assume the desired channel bandwidth
|
||||
* is always 20 MHz for each individual channel (HT40 uses 20 MHz
|
||||
* per channel, the primary and the extension channel).
|
||||
*/
|
||||
static void handle_channel(struct wiphy *wiphy,
|
||||
enum nl80211_reg_initiator initiator,
|
||||
struct ieee80211_channel *chan)
|
||||
{
|
||||
const u32 orig_chan_freq = ieee80211_channel_to_khz(chan);
|
||||
struct regulatory_request *lr = get_last_request();
|
||||
struct wiphy *request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx);
|
||||
const struct ieee80211_reg_rule *rrule = NULL;
|
||||
const struct ieee80211_reg_rule *rrule1 = NULL;
|
||||
const struct ieee80211_reg_rule *rrule2 = NULL;
|
||||
|
||||
u32 flags = chan->orig_flags;
|
||||
|
||||
rrule = freq_reg_info(wiphy, orig_chan_freq);
|
||||
if (IS_ERR(rrule)) {
|
||||
/* check for adjacent match, therefore get rules for
|
||||
* chan - 20 MHz and chan + 20 MHz and test
|
||||
* if reg rules are adjacent
|
||||
*/
|
||||
rrule1 = freq_reg_info(wiphy,
|
||||
orig_chan_freq - MHZ_TO_KHZ(20));
|
||||
rrule2 = freq_reg_info(wiphy,
|
||||
orig_chan_freq + MHZ_TO_KHZ(20));
|
||||
if (!IS_ERR(rrule1) && !IS_ERR(rrule2)) {
|
||||
struct ieee80211_freq_range comb_range;
|
||||
|
||||
if (rrule1->freq_range.end_freq_khz !=
|
||||
rrule2->freq_range.start_freq_khz)
|
||||
goto disable_chan;
|
||||
|
||||
comb_range.start_freq_khz =
|
||||
rrule1->freq_range.start_freq_khz;
|
||||
comb_range.end_freq_khz =
|
||||
rrule2->freq_range.end_freq_khz;
|
||||
comb_range.max_bandwidth_khz =
|
||||
min_t(u32,
|
||||
rrule1->freq_range.max_bandwidth_khz,
|
||||
rrule2->freq_range.max_bandwidth_khz);
|
||||
|
||||
if (!cfg80211_does_bw_fit_range(&comb_range,
|
||||
orig_chan_freq,
|
||||
MHZ_TO_KHZ(20)))
|
||||
goto disable_chan;
|
||||
|
||||
handle_channel_adjacent_rules(wiphy, initiator, chan,
|
||||
flags, lr, request_wiphy,
|
||||
rrule1, rrule2,
|
||||
&comb_range);
|
||||
return;
|
||||
}
|
||||
|
||||
disable_chan:
|
||||
/* We will disable all channels that do not match our
|
||||
* received regulatory rule unless the hint is coming
|
||||
* from a Country IE and the Country IE had no information
|
||||
* about a band. The IEEE 802.11 spec allows for an AP
|
||||
* to send only a subset of the regulatory rules allowed,
|
||||
* so an AP in the US that only supports 2.4 GHz may only send
|
||||
* a country IE with information for the 2.4 GHz band
|
||||
* while 5 GHz is still supported.
|
||||
*/
|
||||
if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
|
||||
PTR_ERR(rrule) == -ERANGE)
|
||||
return;
|
||||
|
||||
if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
|
||||
request_wiphy && request_wiphy == wiphy &&
|
||||
request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
|
||||
pr_debug("Disabling freq %d.%03d MHz for good\n",
|
||||
chan->center_freq, chan->freq_offset);
|
||||
chan->orig_flags |= IEEE80211_CHAN_DISABLED;
|
||||
chan->flags = chan->orig_flags;
|
||||
} else {
|
||||
pr_debug("Disabling freq %d.%03d MHz\n",
|
||||
chan->center_freq, chan->freq_offset);
|
||||
chan->flags |= IEEE80211_CHAN_DISABLED;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
handle_channel_single_rule(wiphy, initiator, chan, flags, lr,
|
||||
request_wiphy, rrule);
|
||||
}
|
||||
|
||||
static void handle_band(struct wiphy *wiphy,
|
||||
enum nl80211_reg_initiator initiator,
|
||||
struct ieee80211_supported_band *sband)
|
||||
|
@ -3167,7 +3326,7 @@ static void restore_custom_reg_settings(struct wiphy *wiphy)
|
|||
* - send a user regulatory hint if applicable
|
||||
*
|
||||
* Device drivers that send a regulatory hint for a specific country
|
||||
* keep their own regulatory domain on wiphy->regd so that does does
|
||||
* keep their own regulatory domain on wiphy->regd so that does
|
||||
* not need to be remembered.
|
||||
*/
|
||||
static void restore_regulatory_settings(bool reset_user, bool cached)
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
*
|
||||
* Also note that the hidden_beacon_bss pointer is only relevant
|
||||
* if the driver uses something other than the IEs, e.g. private
|
||||
* data stored stored in the BSS struct, since the beacon IEs are
|
||||
* data stored in the BSS struct, since the beacon IEs are
|
||||
* also linked into the probe response struct.
|
||||
*/
|
||||
|
||||
|
@ -1433,7 +1433,7 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
|
|||
switch (ftype) {
|
||||
case CFG80211_BSS_FTYPE_BEACON:
|
||||
ies->from_beacon = true;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case CFG80211_BSS_FTYPE_UNKNOWN:
|
||||
rcu_assign_pointer(tmp.pub.beacon_ies, ies);
|
||||
break;
|
||||
|
@ -1488,7 +1488,7 @@ static const struct element
|
|||
ielen - (mbssid_end - ie));
|
||||
|
||||
/*
|
||||
* If is is not the last subelement in current MBSSID IE or there isn't
|
||||
* If it is not the last subelement in current MBSSID IE or there isn't
|
||||
* a next MBSSID IE - profile is complete.
|
||||
*/
|
||||
if ((sub_elem->data + sub_elem->datalen < mbssid_end - 1) ||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
/*
|
||||
* Software SME in cfg80211, using auth/assoc/deauth calls to the
|
||||
* driver. This is is for implementing nl80211's connect/disconnect
|
||||
* driver. This is for implementing nl80211's connect/disconnect
|
||||
* and wireless extensions (if configured.)
|
||||
*/
|
||||
|
||||
|
@ -205,7 +205,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev,
|
|||
return err;
|
||||
case CFG80211_CONN_ASSOC_FAILED_TIMEOUT:
|
||||
*treason = NL80211_TIMEOUT_ASSOC;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case CFG80211_CONN_ASSOC_FAILED:
|
||||
cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
|
||||
NULL, 0,
|
||||
|
@ -215,7 +215,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev,
|
|||
cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
|
||||
NULL, 0,
|
||||
WLAN_REASON_DEAUTH_LEAVING, false);
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case CFG80211_CONN_ABANDON:
|
||||
/* free directly, disconnected event already sent */
|
||||
cfg80211_sme_free(wdev);
|
||||
|
|
|
@ -198,7 +198,7 @@ static void set_mandatory_flags_band(struct ieee80211_supported_band *sband)
|
|||
sband->bitrates[i].flags |=
|
||||
IEEE80211_RATE_MANDATORY_G;
|
||||
want--;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
default:
|
||||
sband->bitrates[i].flags |=
|
||||
IEEE80211_RATE_ERP_G;
|
||||
|
@ -1008,7 +1008,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
|||
case NL80211_IFTYPE_STATION:
|
||||
if (dev->ieee80211_ptr->use_4addr)
|
||||
break;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case NL80211_IFTYPE_OCB:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
|
|
|
@ -497,7 +497,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
|
|||
|
||||
/*
|
||||
* We only need to store WEP keys, since they're the only keys that
|
||||
* can be be set before a connection is established and persist after
|
||||
* can be set before a connection is established and persist after
|
||||
* disconnecting.
|
||||
*/
|
||||
if (!addr && (params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
|
||||
|
@ -1334,7 +1334,7 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
|
|||
wstats.qual.qual = sig + 110;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case CFG80211_SIGNAL_TYPE_UNSPEC:
|
||||
if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_SIGNAL)) {
|
||||
wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
|
||||
|
@ -1343,7 +1343,7 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
|
|||
wstats.qual.qual = sinfo.signal;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
default:
|
||||
wstats.qual.updated |= IW_QUAL_LEVEL_INVALID;
|
||||
wstats.qual.updated |= IW_QUAL_QUAL_INVALID;
|
||||
|
|
Loading…
Reference in New Issue
Block a user