A fair number of fixes:
* fix more fallout from RTNL locking changes * fixes for some of the bugs found by syzbot * drop multicast fragments in mac80211 to align with the spec and what drivers are doing now * fix NULL-ptr deref in radiotap injection -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAmDAz24ACgkQB8qZga/f l8S1LQ/8CVe2fweF6mps0gktCgAAiLhCCpcqCiGqPFe6cmDfSJp7bvCj9YNL7LaG YvCwXlBAN7xpBwnGAXSvBpYC2Ru7KNfzTSqFfThbzPh4DLKxUfKsOK6Yel3yx6B3 gWDjT4zKpZ93k7DO1wdgO/MOvaOVbTe0F+wcLCvcZ3dpqHZuFqAK5FWlHUtlM2c3 Uc08O2WN2DrQR/Qnw0ErXK6pd8N87bnrTNd7vYf69Cmcp53GC4rQGRATQxEtm8LC DdlAQ4ensIfrexlFG+oCSISufwlKYBNW9PY0L10qNUzB6DJyRDVz1UybWEPcTZEy sS8nK4O98bGALWMi98Dqf/s/mQMrjs6THJIyJUQi+p2pHimDH43qwfcIAqoMcw0g 37aG67dEZDXkSYx+CPloBFPgELfDP726BFcVkRyUzdHEIZyGvIIEnEfr6LsIKXNS pDRrDyJOaNoHjGq0VzYvZ+7ETo8rqJHDWkNjEQX13jfa2r3kDTUAvauXkNTmez5N xTNN5XttlfNXvUgb+QWp35ZgfvwimLzVKGfPGBNl8vKaFc5tOGVnzaHU3WahOa1d ttzGRuiNuvb0OWZqIlxG8U8FPtXXpSy/+oKdP4ZbFOLeZXRqpJ85dMSpUAIOwYT5 E0bdOpgbx5C5LFhK4GXUT/Mx6nLBr3c3Jj5flhrGx2wg9+z+PVU= =evzy -----END PGP SIGNATURE----- Merge tag 'mac80211-for-net-2021-06-09' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211 Johannes berg says: ==================== A fair number of fixes: * fix more fallout from RTNL locking changes * fixes for some of the bugs found by syzbot * drop multicast fragments in mac80211 to align with the spec and what drivers are doing now * fix NULL-ptr deref in radiotap injection ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
93124d4a90
|
@ -1693,8 +1693,13 @@ static int mac80211_hwsim_start(struct ieee80211_hw *hw)
|
||||||
static void mac80211_hwsim_stop(struct ieee80211_hw *hw)
|
static void mac80211_hwsim_stop(struct ieee80211_hw *hw)
|
||||||
{
|
{
|
||||||
struct mac80211_hwsim_data *data = hw->priv;
|
struct mac80211_hwsim_data *data = hw->priv;
|
||||||
|
|
||||||
data->started = false;
|
data->started = false;
|
||||||
hrtimer_cancel(&data->beacon_timer);
|
hrtimer_cancel(&data->beacon_timer);
|
||||||
|
|
||||||
|
while (!skb_queue_empty(&data->pending))
|
||||||
|
ieee80211_free_txskb(hw, skb_dequeue(&data->pending));
|
||||||
|
|
||||||
wiphy_dbg(hw->wiphy, "%s\n", __func__);
|
wiphy_dbg(hw->wiphy, "%s\n", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2284,7 +2284,7 @@ static int rtw_cfg80211_add_monitor_if(struct adapter *padapter, char *name, str
|
||||||
mon_wdev->iftype = NL80211_IFTYPE_MONITOR;
|
mon_wdev->iftype = NL80211_IFTYPE_MONITOR;
|
||||||
mon_ndev->ieee80211_ptr = mon_wdev;
|
mon_ndev->ieee80211_ptr = mon_wdev;
|
||||||
|
|
||||||
ret = register_netdevice(mon_ndev);
|
ret = cfg80211_register_netdevice(mon_ndev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -2360,7 +2360,7 @@ static int cfg80211_rtw_del_virtual_intf(struct wiphy *wiphy,
|
||||||
adapter = rtw_netdev_priv(ndev);
|
adapter = rtw_netdev_priv(ndev);
|
||||||
pwdev_priv = adapter_wdev_data(adapter);
|
pwdev_priv = adapter_wdev_data(adapter);
|
||||||
|
|
||||||
unregister_netdevice(ndev);
|
cfg80211_unregister_netdevice(ndev);
|
||||||
|
|
||||||
if (ndev == pwdev_priv->pmon_ndev) {
|
if (ndev == pwdev_priv->pmon_ndev) {
|
||||||
pwdev_priv->pmon_ndev = NULL;
|
pwdev_priv->pmon_ndev = NULL;
|
||||||
|
|
|
@ -5537,7 +5537,7 @@ void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw,
|
||||||
*
|
*
|
||||||
* This function iterates over the interfaces associated with a given
|
* This function iterates over the interfaces associated with a given
|
||||||
* hardware that are currently active and calls the callback for them.
|
* hardware that are currently active and calls the callback for them.
|
||||||
* This version can only be used while holding the RTNL.
|
* This version can only be used while holding the wiphy mutex.
|
||||||
*
|
*
|
||||||
* @hw: the hardware struct of which the interfaces should be iterated over
|
* @hw: the hardware struct of which the interfaces should be iterated over
|
||||||
* @iter_flags: iteration flags, see &enum ieee80211_interface_iteration_flags
|
* @iter_flags: iteration flags, see &enum ieee80211_interface_iteration_flags
|
||||||
|
@ -6392,7 +6392,12 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ieee80211_parse_tx_radiotap - Sanity-check and parse the radiotap header
|
* ieee80211_parse_tx_radiotap - Sanity-check and parse the radiotap header
|
||||||
* of injected frames
|
* of injected frames.
|
||||||
|
*
|
||||||
|
* To accurately parse and take into account rate and retransmission fields,
|
||||||
|
* you must initialize the chandef field in the ieee80211_tx_info structure
|
||||||
|
* of the skb before calling this function.
|
||||||
|
*
|
||||||
* @skb: packet injected by userspace
|
* @skb: packet injected by userspace
|
||||||
* @dev: the &struct device of this 802.11 device
|
* @dev: the &struct device of this 802.11 device
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*
|
*
|
||||||
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
|
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
|
||||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||||
* Copyright (C) 2018 - 2019 Intel Corporation
|
* Copyright (C) 2018 - 2019, 2021 Intel Corporation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
|
@ -387,10 +387,17 @@ static ssize_t reset_write(struct file *file, const char __user *user_buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct ieee80211_local *local = file->private_data;
|
struct ieee80211_local *local = file->private_data;
|
||||||
|
int ret;
|
||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
|
wiphy_lock(local->hw.wiphy);
|
||||||
__ieee80211_suspend(&local->hw, NULL);
|
__ieee80211_suspend(&local->hw, NULL);
|
||||||
__ieee80211_resume(&local->hw);
|
ret = __ieee80211_resume(&local->hw);
|
||||||
|
wiphy_unlock(local->hw.wiphy);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
cfg80211_shutdown_all_interfaces(local->hw.wiphy);
|
||||||
|
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
|
|
@ -1442,7 +1442,7 @@ ieee80211_get_sband(struct ieee80211_sub_if_data *sdata)
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
||||||
|
|
||||||
if (WARN_ON_ONCE(!chanctx_conf)) {
|
if (!chanctx_conf) {
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -476,14 +476,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* APs need special treatment */
|
|
||||||
if (sdata->vif.type == NL80211_IFTYPE_AP) {
|
if (sdata->vif.type == NL80211_IFTYPE_AP) {
|
||||||
struct ieee80211_sub_if_data *vlan, *tmpsdata;
|
|
||||||
|
|
||||||
/* down all dependent devices, that is VLANs */
|
|
||||||
list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans,
|
|
||||||
u.vlan.list)
|
|
||||||
dev_close(vlan->dev);
|
|
||||||
WARN_ON(!list_empty(&sdata->u.ap.vlans));
|
WARN_ON(!list_empty(&sdata->u.ap.vlans));
|
||||||
} else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
|
} else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
|
||||||
/* remove all packets in parent bc_buf pointing to this dev */
|
/* remove all packets in parent bc_buf pointing to this dev */
|
||||||
|
@ -641,6 +634,15 @@ static int ieee80211_stop(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
|
|
||||||
|
/* close all dependent VLAN interfaces before locking wiphy */
|
||||||
|
if (sdata->vif.type == NL80211_IFTYPE_AP) {
|
||||||
|
struct ieee80211_sub_if_data *vlan, *tmpsdata;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans,
|
||||||
|
u.vlan.list)
|
||||||
|
dev_close(vlan->dev);
|
||||||
|
}
|
||||||
|
|
||||||
wiphy_lock(sdata->local->hw.wiphy);
|
wiphy_lock(sdata->local->hw.wiphy);
|
||||||
ieee80211_do_stop(sdata, true);
|
ieee80211_do_stop(sdata, true);
|
||||||
wiphy_unlock(sdata->local->hw.wiphy);
|
wiphy_unlock(sdata->local->hw.wiphy);
|
||||||
|
@ -1591,6 +1593,9 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata,
|
||||||
|
|
||||||
switch (sdata->vif.type) {
|
switch (sdata->vif.type) {
|
||||||
case NL80211_IFTYPE_AP:
|
case NL80211_IFTYPE_AP:
|
||||||
|
if (!list_empty(&sdata->u.ap.vlans))
|
||||||
|
return -EBUSY;
|
||||||
|
break;
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
case NL80211_IFTYPE_ADHOC:
|
case NL80211_IFTYPE_ADHOC:
|
||||||
case NL80211_IFTYPE_OCB:
|
case NL80211_IFTYPE_OCB:
|
||||||
|
|
|
@ -252,6 +252,7 @@ static void ieee80211_restart_work(struct work_struct *work)
|
||||||
struct ieee80211_local *local =
|
struct ieee80211_local *local =
|
||||||
container_of(work, struct ieee80211_local, restart_work);
|
container_of(work, struct ieee80211_local, restart_work);
|
||||||
struct ieee80211_sub_if_data *sdata;
|
struct ieee80211_sub_if_data *sdata;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* wait for scan work complete */
|
/* wait for scan work complete */
|
||||||
flush_workqueue(local->workqueue);
|
flush_workqueue(local->workqueue);
|
||||||
|
@ -301,8 +302,12 @@ static void ieee80211_restart_work(struct work_struct *work)
|
||||||
/* wait for all packet processing to be done */
|
/* wait for all packet processing to be done */
|
||||||
synchronize_net();
|
synchronize_net();
|
||||||
|
|
||||||
ieee80211_reconfig(local);
|
ret = ieee80211_reconfig(local);
|
||||||
wiphy_unlock(local->hw.wiphy);
|
wiphy_unlock(local->hw.wiphy);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
cfg80211_shutdown_all_interfaces(local->hw.wiphy);
|
||||||
|
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2240,17 +2240,15 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
||||||
sc = le16_to_cpu(hdr->seq_ctrl);
|
sc = le16_to_cpu(hdr->seq_ctrl);
|
||||||
frag = sc & IEEE80211_SCTL_FRAG;
|
frag = sc & IEEE80211_SCTL_FRAG;
|
||||||
|
|
||||||
if (is_multicast_ether_addr(hdr->addr1)) {
|
|
||||||
I802_DEBUG_INC(rx->local->dot11MulticastReceivedFrameCount);
|
|
||||||
goto out_no_led;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rx->sta)
|
if (rx->sta)
|
||||||
cache = &rx->sta->frags;
|
cache = &rx->sta->frags;
|
||||||
|
|
||||||
if (likely(!ieee80211_has_morefrags(fc) && frag == 0))
|
if (likely(!ieee80211_has_morefrags(fc) && frag == 0))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
if (is_multicast_ether_addr(hdr->addr1))
|
||||||
|
return RX_DROP_MONITOR;
|
||||||
|
|
||||||
I802_DEBUG_INC(rx->local->rx_handlers_fragments);
|
I802_DEBUG_INC(rx->local->rx_handlers_fragments);
|
||||||
|
|
||||||
if (skb_linearize(rx->skb))
|
if (skb_linearize(rx->skb))
|
||||||
|
@ -2376,7 +2374,6 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
||||||
|
|
||||||
out:
|
out:
|
||||||
ieee80211_led_rx(rx->local);
|
ieee80211_led_rx(rx->local);
|
||||||
out_no_led:
|
|
||||||
if (rx->sta)
|
if (rx->sta)
|
||||||
rx->sta->rx_stats.packets++;
|
rx->sta->rx_stats.packets++;
|
||||||
return RX_CONTINUE;
|
return RX_CONTINUE;
|
||||||
|
|
|
@ -251,13 +251,24 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
|
||||||
struct ieee80211_mgmt *mgmt = (void *)skb->data;
|
struct ieee80211_mgmt *mgmt = (void *)skb->data;
|
||||||
struct ieee80211_bss *bss;
|
struct ieee80211_bss *bss;
|
||||||
struct ieee80211_channel *channel;
|
struct ieee80211_channel *channel;
|
||||||
|
size_t min_hdr_len = offsetof(struct ieee80211_mgmt,
|
||||||
|
u.probe_resp.variable);
|
||||||
|
|
||||||
|
if (!ieee80211_is_probe_resp(mgmt->frame_control) &&
|
||||||
|
!ieee80211_is_beacon(mgmt->frame_control) &&
|
||||||
|
!ieee80211_is_s1g_beacon(mgmt->frame_control))
|
||||||
|
return;
|
||||||
|
|
||||||
if (ieee80211_is_s1g_beacon(mgmt->frame_control)) {
|
if (ieee80211_is_s1g_beacon(mgmt->frame_control)) {
|
||||||
if (skb->len < 15)
|
if (ieee80211_is_s1g_short_beacon(mgmt->frame_control))
|
||||||
return;
|
min_hdr_len = offsetof(struct ieee80211_ext,
|
||||||
} else if (skb->len < 24 ||
|
u.s1g_short_beacon.variable);
|
||||||
(!ieee80211_is_probe_resp(mgmt->frame_control) &&
|
else
|
||||||
!ieee80211_is_beacon(mgmt->frame_control)))
|
min_hdr_len = offsetof(struct ieee80211_ext,
|
||||||
|
u.s1g_beacon);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skb->len < min_hdr_len)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sdata1 = rcu_dereference(local->scan_sdata);
|
sdata1 = rcu_dereference(local->scan_sdata);
|
||||||
|
|
|
@ -2014,27 +2014,10 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
|
||||||
ieee80211_tx(sdata, sta, skb, false);
|
ieee80211_tx(sdata, sta, skb, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
|
static bool ieee80211_validate_radiotap_len(struct sk_buff *skb)
|
||||||
struct net_device *dev)
|
|
||||||
{
|
{
|
||||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
|
||||||
struct ieee80211_radiotap_iterator iterator;
|
|
||||||
struct ieee80211_radiotap_header *rthdr =
|
struct ieee80211_radiotap_header *rthdr =
|
||||||
(struct ieee80211_radiotap_header *) skb->data;
|
(struct ieee80211_radiotap_header *)skb->data;
|
||||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
|
||||||
struct ieee80211_supported_band *sband =
|
|
||||||
local->hw.wiphy->bands[info->band];
|
|
||||||
int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
|
|
||||||
NULL);
|
|
||||||
u16 txflags;
|
|
||||||
u16 rate = 0;
|
|
||||||
bool rate_found = false;
|
|
||||||
u8 rate_retries = 0;
|
|
||||||
u16 rate_flags = 0;
|
|
||||||
u8 mcs_known, mcs_flags, mcs_bw;
|
|
||||||
u16 vht_known;
|
|
||||||
u8 vht_mcs = 0, vht_nss = 0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* check for not even having the fixed radiotap header part */
|
/* check for not even having the fixed radiotap header part */
|
||||||
if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
|
if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
|
||||||
|
@ -2048,6 +2031,32 @@ bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
|
||||||
if (unlikely(skb->len < ieee80211_get_radiotap_len(skb->data)))
|
if (unlikely(skb->len < ieee80211_get_radiotap_len(skb->data)))
|
||||||
return false; /* skb too short for claimed rt header extent */
|
return false; /* skb too short for claimed rt header extent */
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
|
||||||
|
struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||||
|
struct ieee80211_radiotap_iterator iterator;
|
||||||
|
struct ieee80211_radiotap_header *rthdr =
|
||||||
|
(struct ieee80211_radiotap_header *) skb->data;
|
||||||
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||||
|
int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
|
||||||
|
NULL);
|
||||||
|
u16 txflags;
|
||||||
|
u16 rate = 0;
|
||||||
|
bool rate_found = false;
|
||||||
|
u8 rate_retries = 0;
|
||||||
|
u16 rate_flags = 0;
|
||||||
|
u8 mcs_known, mcs_flags, mcs_bw;
|
||||||
|
u16 vht_known;
|
||||||
|
u8 vht_mcs = 0, vht_nss = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!ieee80211_validate_radiotap_len(skb))
|
||||||
|
return false;
|
||||||
|
|
||||||
info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
|
info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
|
||||||
IEEE80211_TX_CTL_DONTFRAG;
|
IEEE80211_TX_CTL_DONTFRAG;
|
||||||
|
|
||||||
|
@ -2186,6 +2195,9 @@ bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (rate_found) {
|
if (rate_found) {
|
||||||
|
struct ieee80211_supported_band *sband =
|
||||||
|
local->hw.wiphy->bands[info->band];
|
||||||
|
|
||||||
info->control.flags |= IEEE80211_TX_CTRL_RATE_INJECT;
|
info->control.flags |= IEEE80211_TX_CTRL_RATE_INJECT;
|
||||||
|
|
||||||
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
|
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
|
||||||
|
@ -2199,7 +2211,7 @@ bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
|
||||||
} else if (rate_flags & IEEE80211_TX_RC_VHT_MCS) {
|
} else if (rate_flags & IEEE80211_TX_RC_VHT_MCS) {
|
||||||
ieee80211_rate_set_vht(info->control.rates, vht_mcs,
|
ieee80211_rate_set_vht(info->control.rates, vht_mcs,
|
||||||
vht_nss);
|
vht_nss);
|
||||||
} else {
|
} else if (sband) {
|
||||||
for (i = 0; i < sband->n_bitrates; i++) {
|
for (i = 0; i < sband->n_bitrates; i++) {
|
||||||
if (rate * 5 != sband->bitrates[i].bitrate)
|
if (rate * 5 != sband->bitrates[i].bitrate)
|
||||||
continue;
|
continue;
|
||||||
|
@ -2236,8 +2248,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
|
||||||
info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
|
info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
|
||||||
IEEE80211_TX_CTL_INJECTED;
|
IEEE80211_TX_CTL_INJECTED;
|
||||||
|
|
||||||
/* Sanity-check and process the injection radiotap header */
|
/* Sanity-check the length of the radiotap header */
|
||||||
if (!ieee80211_parse_tx_radiotap(skb, dev))
|
if (!ieee80211_validate_radiotap_len(skb))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* we now know there is a radiotap header with a length we can use */
|
/* we now know there is a radiotap header with a length we can use */
|
||||||
|
@ -2351,6 +2363,14 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
|
||||||
ieee80211_select_queue_80211(sdata, skb, hdr);
|
ieee80211_select_queue_80211(sdata, skb, hdr);
|
||||||
skb_set_queue_mapping(skb, ieee80211_ac_from_tid(skb->priority));
|
skb_set_queue_mapping(skb, ieee80211_ac_from_tid(skb->priority));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process the radiotap header. This will now take into account the
|
||||||
|
* selected chandef above to accurately set injection rates and
|
||||||
|
* retransmissions.
|
||||||
|
*/
|
||||||
|
if (!ieee80211_parse_tx_radiotap(skb, dev))
|
||||||
|
goto fail_rcu;
|
||||||
|
|
||||||
/* remove the injection radiotap header */
|
/* remove the injection radiotap header */
|
||||||
skb_pull(skb, len_rthdr);
|
skb_pull(skb, len_rthdr);
|
||||||
|
|
||||||
|
|
|
@ -2178,8 +2178,6 @@ static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local)
|
||||||
list_for_each_entry(ctx, &local->chanctx_list, list)
|
list_for_each_entry(ctx, &local->chanctx_list, list)
|
||||||
ctx->driver_present = false;
|
ctx->driver_present = false;
|
||||||
mutex_unlock(&local->chanctx_mtx);
|
mutex_unlock(&local->chanctx_mtx);
|
||||||
|
|
||||||
cfg80211_shutdown_all_interfaces(local->hw.wiphy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ieee80211_assign_chanctx(struct ieee80211_local *local,
|
static void ieee80211_assign_chanctx(struct ieee80211_local *local,
|
||||||
|
|
|
@ -1340,6 +1340,11 @@ void cfg80211_register_wdev(struct cfg80211_registered_device *rdev,
|
||||||
rdev->devlist_generation++;
|
rdev->devlist_generation++;
|
||||||
wdev->registered = true;
|
wdev->registered = true;
|
||||||
|
|
||||||
|
if (wdev->netdev &&
|
||||||
|
sysfs_create_link(&wdev->netdev->dev.kobj, &rdev->wiphy.dev.kobj,
|
||||||
|
"phy80211"))
|
||||||
|
pr_err("failed to add phy80211 symlink to netdev!\n");
|
||||||
|
|
||||||
nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
|
nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1365,14 +1370,6 @@ int cfg80211_register_netdevice(struct net_device *dev)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj,
|
|
||||||
"phy80211")) {
|
|
||||||
pr_err("failed to add phy80211 symlink to netdev!\n");
|
|
||||||
unregister_netdevice(dev);
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg80211_register_wdev(rdev, wdev);
|
cfg80211_register_wdev(rdev, wdev);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
out:
|
out:
|
||||||
|
|
|
@ -133,6 +133,10 @@ static int wiphy_resume(struct device *dev)
|
||||||
if (rdev->wiphy.registered && rdev->ops->resume)
|
if (rdev->wiphy.registered && rdev->ops->resume)
|
||||||
ret = rdev_resume(rdev);
|
ret = rdev_resume(rdev);
|
||||||
wiphy_unlock(&rdev->wiphy);
|
wiphy_unlock(&rdev->wiphy);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
cfg80211_shutdown_all_interfaces(&rdev->wiphy);
|
||||||
|
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -1059,6 +1059,9 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
||||||
case NL80211_IFTYPE_MESH_POINT:
|
case NL80211_IFTYPE_MESH_POINT:
|
||||||
/* mesh should be handled? */
|
/* mesh should be handled? */
|
||||||
break;
|
break;
|
||||||
|
case NL80211_IFTYPE_OCB:
|
||||||
|
cfg80211_leave_ocb(rdev, dev);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче