Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
This commit is contained in:
commit
933faa43ab
|
@ -132,9 +132,7 @@
|
|||
!Finclude/net/cfg80211.h cfg80211_send_rx_assoc
|
||||
!Finclude/net/cfg80211.h cfg80211_send_assoc_timeout
|
||||
!Finclude/net/cfg80211.h cfg80211_send_deauth
|
||||
!Finclude/net/cfg80211.h __cfg80211_send_deauth
|
||||
!Finclude/net/cfg80211.h cfg80211_send_disassoc
|
||||
!Finclude/net/cfg80211.h __cfg80211_send_disassoc
|
||||
!Finclude/net/cfg80211.h cfg80211_ibss_joined
|
||||
!Finclude/net/cfg80211.h cfg80211_connect_result
|
||||
!Finclude/net/cfg80211.h cfg80211_roamed
|
||||
|
|
|
@ -1347,14 +1347,6 @@ struct il_rx_mpdu_res_start {
|
|||
#define TX_CMD_SEC_SHIFT 6
|
||||
#define TX_CMD_SEC_KEY128 0x08
|
||||
|
||||
/*
|
||||
* security overhead sizes
|
||||
*/
|
||||
#define WEP_IV_LEN 4
|
||||
#define WEP_ICV_LEN 4
|
||||
#define CCMP_MIC_LEN 8
|
||||
#define TKIP_ICV_LEN 4
|
||||
|
||||
/*
|
||||
* C_TX = 0x1c (command)
|
||||
*/
|
||||
|
|
|
@ -1220,14 +1220,6 @@ struct iwl_rx_mpdu_res_start {
|
|||
#define TX_CMD_SEC_SHIFT 6
|
||||
#define TX_CMD_SEC_KEY128 0x08
|
||||
|
||||
/*
|
||||
* security overhead sizes
|
||||
*/
|
||||
#define WEP_IV_LEN 4
|
||||
#define WEP_ICV_LEN 4
|
||||
#define CCMP_MIC_LEN 8
|
||||
#define TKIP_ICV_LEN 4
|
||||
|
||||
/*
|
||||
* REPLY_TX = 0x1c (command)
|
||||
*/
|
||||
|
|
|
@ -84,15 +84,6 @@ static const struct ieee80211_iface_limit iwl_mvm_limits[] = {
|
|||
.types = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_AP),
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO),
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_DEVICE),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_combination iwl_mvm_iface_combinations[] = {
|
||||
|
@ -173,10 +164,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
|||
hw->chanctx_data_size = sizeof(u16);
|
||||
|
||||
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO) |
|
||||
BIT(NL80211_IFTYPE_P2P_DEVICE);
|
||||
BIT(NL80211_IFTYPE_AP);
|
||||
|
||||
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
|
||||
WIPHY_FLAG_DISABLE_BEACON_HINTS |
|
||||
|
|
|
@ -224,13 +224,13 @@ static void iwl_pcie_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
|
|||
|
||||
switch (sec_ctl & TX_CMD_SEC_MSK) {
|
||||
case TX_CMD_SEC_CCM:
|
||||
len += CCMP_MIC_LEN;
|
||||
len += IEEE80211_CCMP_MIC_LEN;
|
||||
break;
|
||||
case TX_CMD_SEC_TKIP:
|
||||
len += TKIP_ICV_LEN;
|
||||
len += IEEE80211_TKIP_ICV_LEN;
|
||||
break;
|
||||
case TX_CMD_SEC_WEP:
|
||||
len += WEP_IV_LEN + WEP_ICV_LEN;
|
||||
len += IEEE80211_WEP_IV_LEN + IEEE80211_WEP_ICV_LEN;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -1723,11 +1723,11 @@ static void mac80211_hwsim_free(void)
|
|||
class_destroy(hwsim_class);
|
||||
}
|
||||
|
||||
|
||||
static struct device_driver mac80211_hwsim_driver = {
|
||||
.name = "mac80211_hwsim",
|
||||
.bus = &platform_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
static struct platform_driver mac80211_hwsim_driver = {
|
||||
.driver = {
|
||||
.name = "mac80211_hwsim",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct net_device_ops hwsim_netdev_ops = {
|
||||
|
@ -2169,7 +2169,6 @@ static const struct ieee80211_iface_limit hwsim_if_limits[] = {
|
|||
#endif
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO) },
|
||||
{ .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) },
|
||||
};
|
||||
|
||||
static struct ieee80211_iface_combination hwsim_if_comb = {
|
||||
|
@ -2219,7 +2218,7 @@ static int __init init_mac80211_hwsim(void)
|
|||
spin_lock_init(&hwsim_radio_lock);
|
||||
INIT_LIST_HEAD(&hwsim_radios);
|
||||
|
||||
err = driver_register(&mac80211_hwsim_driver);
|
||||
err = platform_driver_register(&mac80211_hwsim_driver);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -2254,7 +2253,7 @@ static int __init init_mac80211_hwsim(void)
|
|||
err = -ENOMEM;
|
||||
goto failed_drvdata;
|
||||
}
|
||||
data->dev->driver = &mac80211_hwsim_driver;
|
||||
data->dev->driver = &mac80211_hwsim_driver.driver;
|
||||
err = device_bind_driver(data->dev);
|
||||
if (err != 0) {
|
||||
printk(KERN_DEBUG
|
||||
|
@ -2295,8 +2294,7 @@ static int __init init_mac80211_hwsim(void)
|
|||
BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO) |
|
||||
BIT(NL80211_IFTYPE_ADHOC) |
|
||||
BIT(NL80211_IFTYPE_MESH_POINT) |
|
||||
BIT(NL80211_IFTYPE_P2P_DEVICE);
|
||||
BIT(NL80211_IFTYPE_MESH_POINT);
|
||||
|
||||
hw->flags = IEEE80211_HW_MFP_CAPABLE |
|
||||
IEEE80211_HW_SIGNAL_DBM |
|
||||
|
@ -2564,7 +2562,7 @@ failed_drvdata:
|
|||
failed:
|
||||
mac80211_hwsim_free();
|
||||
failed_unregister_driver:
|
||||
driver_unregister(&mac80211_hwsim_driver);
|
||||
platform_driver_unregister(&mac80211_hwsim_driver);
|
||||
return err;
|
||||
}
|
||||
module_init(init_mac80211_hwsim);
|
||||
|
@ -2577,6 +2575,6 @@ static void __exit exit_mac80211_hwsim(void)
|
|||
|
||||
mac80211_hwsim_free();
|
||||
unregister_netdev(hwsim_mon);
|
||||
driver_unregister(&mac80211_hwsim_driver);
|
||||
platform_driver_unregister(&mac80211_hwsim_driver);
|
||||
}
|
||||
module_exit(exit_mac80211_hwsim);
|
||||
|
|
|
@ -1829,6 +1829,15 @@ enum ieee80211_key_len {
|
|||
WLAN_KEY_LEN_AES_CMAC = 16,
|
||||
};
|
||||
|
||||
#define IEEE80211_WEP_IV_LEN 4
|
||||
#define IEEE80211_WEP_ICV_LEN 4
|
||||
#define IEEE80211_CCMP_HDR_LEN 8
|
||||
#define IEEE80211_CCMP_MIC_LEN 8
|
||||
#define IEEE80211_CCMP_PN_LEN 6
|
||||
#define IEEE80211_TKIP_IV_LEN 8
|
||||
#define IEEE80211_TKIP_ICV_LEN 4
|
||||
#define IEEE80211_CMAC_PN_LEN 6
|
||||
|
||||
/* Public action codes */
|
||||
enum ieee80211_pub_actioncode {
|
||||
WLAN_PUB_ACTION_EXT_CHANSW_ANN = 4,
|
||||
|
|
|
@ -753,6 +753,8 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
|
|||
* @STATION_INFO_LOCAL_PM: @local_pm filled
|
||||
* @STATION_INFO_PEER_PM: @peer_pm filled
|
||||
* @STATION_INFO_NONPEER_PM: @nonpeer_pm filled
|
||||
* @STATION_INFO_CHAIN_SIGNAL: @chain_signal filled
|
||||
* @STATION_INFO_CHAIN_SIGNAL_AVG: @chain_signal_avg filled
|
||||
*/
|
||||
enum station_info_flags {
|
||||
STATION_INFO_INACTIVE_TIME = 1<<0,
|
||||
|
@ -781,6 +783,8 @@ enum station_info_flags {
|
|||
STATION_INFO_NONPEER_PM = 1<<23,
|
||||
STATION_INFO_RX_BYTES64 = 1<<24,
|
||||
STATION_INFO_TX_BYTES64 = 1<<25,
|
||||
STATION_INFO_CHAIN_SIGNAL = 1<<26,
|
||||
STATION_INFO_CHAIN_SIGNAL_AVG = 1<<27,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -857,6 +861,8 @@ struct sta_bss_parameters {
|
|||
u16 beacon_interval;
|
||||
};
|
||||
|
||||
#define IEEE80211_MAX_CHAINS 4
|
||||
|
||||
/**
|
||||
* struct station_info - station information
|
||||
*
|
||||
|
@ -874,6 +880,9 @@ struct sta_bss_parameters {
|
|||
* For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
|
||||
* @signal_avg: Average signal strength, type depends on the wiphy's signal_type.
|
||||
* For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
|
||||
* @chains: bitmask for filled values in @chain_signal, @chain_signal_avg
|
||||
* @chain_signal: per-chain signal strength of last received packet in dBm
|
||||
* @chain_signal_avg: per-chain signal strength average in dBm
|
||||
* @txrate: current unicast bitrate from this station
|
||||
* @rxrate: current unicast bitrate to this station
|
||||
* @rx_packets: packets received from this station
|
||||
|
@ -909,6 +918,11 @@ struct station_info {
|
|||
u8 plink_state;
|
||||
s8 signal;
|
||||
s8 signal_avg;
|
||||
|
||||
u8 chains;
|
||||
s8 chain_signal[IEEE80211_MAX_CHAINS];
|
||||
s8 chain_signal_avg[IEEE80211_MAX_CHAINS];
|
||||
|
||||
struct rate_info txrate;
|
||||
struct rate_info rxrate;
|
||||
u32 rx_packets;
|
||||
|
@ -1147,6 +1161,7 @@ struct mesh_config {
|
|||
* @sync_method: which synchronization method to use
|
||||
* @path_sel_proto: which path selection protocol to use
|
||||
* @path_metric: which metric to use
|
||||
* @auth_id: which authentication method this mesh is using
|
||||
* @ie: vendor information elements (optional)
|
||||
* @ie_len: length of vendor information elements
|
||||
* @is_authenticated: this mesh requires authentication
|
||||
|
@ -1165,6 +1180,7 @@ struct mesh_setup {
|
|||
u8 sync_method;
|
||||
u8 path_sel_proto;
|
||||
u8 path_metric;
|
||||
u8 auth_id;
|
||||
const u8 *ie;
|
||||
u8 ie_len;
|
||||
bool is_authenticated;
|
||||
|
@ -1241,6 +1257,7 @@ struct cfg80211_ssid {
|
|||
* @scan_start: time (in jiffies) when the scan started
|
||||
* @wdev: the wireless device to scan for
|
||||
* @aborted: (internal) scan request was notified as aborted
|
||||
* @notified: (internal) scan request was notified as done or aborted
|
||||
* @no_cck: used to send probe requests at non CCK rate in 2GHz band
|
||||
*/
|
||||
struct cfg80211_scan_request {
|
||||
|
@ -1258,7 +1275,7 @@ struct cfg80211_scan_request {
|
|||
/* internal */
|
||||
struct wiphy *wiphy;
|
||||
unsigned long scan_start;
|
||||
bool aborted;
|
||||
bool aborted, notified;
|
||||
bool no_cck;
|
||||
|
||||
/* keep last */
|
||||
|
@ -1850,7 +1867,9 @@ struct cfg80211_update_ft_ies_params {
|
|||
* @get_mpath: get a mesh path for the given parameters
|
||||
* @dump_mpath: dump mesh path callback -- resume dump at index @idx
|
||||
* @join_mesh: join the mesh network with the specified parameters
|
||||
* (invoked with the wireless_dev mutex held)
|
||||
* @leave_mesh: leave the current mesh network
|
||||
* (invoked with the wireless_dev mutex held)
|
||||
*
|
||||
* @get_mesh_config: Get the current mesh configuration
|
||||
*
|
||||
|
@ -1877,20 +1896,28 @@ struct cfg80211_update_ft_ies_params {
|
|||
* the scan/scan_done bracket too.
|
||||
*
|
||||
* @auth: Request to authenticate with the specified peer
|
||||
* (invoked with the wireless_dev mutex held)
|
||||
* @assoc: Request to (re)associate with the specified peer
|
||||
* (invoked with the wireless_dev mutex held)
|
||||
* @deauth: Request to deauthenticate from the specified peer
|
||||
* (invoked with the wireless_dev mutex held)
|
||||
* @disassoc: Request to disassociate from the specified peer
|
||||
* (invoked with the wireless_dev mutex held)
|
||||
*
|
||||
* @connect: Connect to the ESS with the specified parameters. When connected,
|
||||
* call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS.
|
||||
* If the connection fails for some reason, call cfg80211_connect_result()
|
||||
* with the status from the AP.
|
||||
* (invoked with the wireless_dev mutex held)
|
||||
* @disconnect: Disconnect from the BSS/ESS.
|
||||
* (invoked with the wireless_dev mutex held)
|
||||
*
|
||||
* @join_ibss: Join the specified IBSS (or create if necessary). Once done, call
|
||||
* cfg80211_ibss_joined(), also call that function when changing BSSID due
|
||||
* to a merge.
|
||||
* (invoked with the wireless_dev mutex held)
|
||||
* @leave_ibss: Leave the IBSS.
|
||||
* (invoked with the wireless_dev mutex held)
|
||||
*
|
||||
* @set_mcast_rate: Set the specified multicast rate (only if vif is in ADHOC or
|
||||
* MESH mode)
|
||||
|
@ -2556,6 +2583,9 @@ struct wiphy_wowlan_support {
|
|||
* may request, if implemented.
|
||||
*
|
||||
* @wowlan: WoWLAN support information
|
||||
* @wowlan_config: current WoWLAN configuration; this should usually not be
|
||||
* used since access to it is necessarily racy, use the parameter passed
|
||||
* to the suspend() operation instead.
|
||||
*
|
||||
* @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features.
|
||||
* @ht_capa_mod_mask: Specify what ht_cap values can be over-ridden.
|
||||
|
@ -2623,6 +2653,7 @@ struct wiphy {
|
|||
|
||||
#ifdef CONFIG_PM
|
||||
struct wiphy_wowlan_support wowlan;
|
||||
struct cfg80211_wowlan *wowlan_config;
|
||||
#endif
|
||||
|
||||
u16 max_remain_on_channel_duration;
|
||||
|
@ -2834,7 +2865,8 @@ struct cfg80211_cached_keys;
|
|||
* by cfg80211 on change_interface
|
||||
* @mgmt_registrations: list of registrations for management frames
|
||||
* @mgmt_registrations_lock: lock for the list
|
||||
* @mtx: mutex used to lock data in this struct
|
||||
* @mtx: mutex used to lock data in this struct, may be used by drivers
|
||||
* and some API functions require it held
|
||||
* @cleanup_work: work struct used for cleanup that can't be done directly
|
||||
* @beacon_interval: beacon interval used on this device for transmitting
|
||||
* beacons, 0 when not valid
|
||||
|
@ -2858,8 +2890,6 @@ struct wireless_dev {
|
|||
|
||||
struct mutex mtx;
|
||||
|
||||
struct work_struct cleanup_work;
|
||||
|
||||
bool use_4addr, p2p_started;
|
||||
|
||||
u8 address[ETH_ALEN] __aligned(sizeof(u16));
|
||||
|
@ -2989,6 +3019,15 @@ struct ieee80211_rate *
|
|||
ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
|
||||
u32 basic_rates, int bitrate);
|
||||
|
||||
/**
|
||||
* ieee80211_mandatory_rates - get mandatory rates for a given band
|
||||
* @sband: the band to look for rates in
|
||||
*
|
||||
* This function returns a bitmap of the mandatory rates for the given
|
||||
* band, bits are set according to the rate position in the bitrates array.
|
||||
*/
|
||||
u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband);
|
||||
|
||||
/*
|
||||
* Radiotap parsing functions -- for controlled injection support
|
||||
*
|
||||
|
@ -3400,7 +3439,8 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss);
|
|||
* This function is called whenever an authentication has been processed in
|
||||
* station mode. The driver is required to call either this function or
|
||||
* cfg80211_send_auth_timeout() to indicate the result of cfg80211_ops::auth()
|
||||
* call. This function may sleep.
|
||||
* call. This function may sleep. The caller must hold the corresponding wdev's
|
||||
* mutex.
|
||||
*/
|
||||
void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
|
||||
|
||||
|
@ -3409,7 +3449,8 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
|
|||
* @dev: network device
|
||||
* @addr: The MAC address of the device with which the authentication timed out
|
||||
*
|
||||
* This function may sleep.
|
||||
* This function may sleep. The caller must hold the corresponding wdev's
|
||||
* mutex.
|
||||
*/
|
||||
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr);
|
||||
|
||||
|
@ -3424,7 +3465,8 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr);
|
|||
* This function is called whenever a (re)association response has been
|
||||
* processed in station mode. The driver is required to call either this
|
||||
* function or cfg80211_send_assoc_timeout() to indicate the result of
|
||||
* cfg80211_ops::assoc() call. This function may sleep.
|
||||
* cfg80211_ops::assoc() call. This function may sleep. The caller must hold
|
||||
* the corresponding wdev's mutex.
|
||||
*/
|
||||
void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
|
||||
const u8 *buf, size_t len);
|
||||
|
@ -3434,7 +3476,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
|
|||
* @dev: network device
|
||||
* @addr: The MAC address of the device with which the association timed out
|
||||
*
|
||||
* This function may sleep.
|
||||
* This function may sleep. The caller must hold the corresponding wdev's mutex.
|
||||
*/
|
||||
void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr);
|
||||
|
||||
|
@ -3446,20 +3488,11 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr);
|
|||
*
|
||||
* This function is called whenever deauthentication has been processed in
|
||||
* station mode. This includes both received deauthentication frames and
|
||||
* locally generated ones. This function may sleep.
|
||||
* locally generated ones. This function may sleep. The caller must hold the
|
||||
* corresponding wdev's mutex.
|
||||
*/
|
||||
void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
|
||||
|
||||
/**
|
||||
* __cfg80211_send_deauth - notification of processed deauthentication
|
||||
* @dev: network device
|
||||
* @buf: deauthentication frame (header + body)
|
||||
* @len: length of the frame data
|
||||
*
|
||||
* Like cfg80211_send_deauth(), but doesn't take the wdev lock.
|
||||
*/
|
||||
void __cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
|
||||
|
||||
/**
|
||||
* cfg80211_send_disassoc - notification of processed disassociation
|
||||
* @dev: network device
|
||||
|
@ -3468,21 +3501,11 @@ void __cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
|
|||
*
|
||||
* This function is called whenever disassociation has been processed in
|
||||
* station mode. This includes both received disassociation frames and locally
|
||||
* generated ones. This function may sleep.
|
||||
* generated ones. This function may sleep. The caller must hold the
|
||||
* corresponding wdev's mutex.
|
||||
*/
|
||||
void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len);
|
||||
|
||||
/**
|
||||
* __cfg80211_send_disassoc - notification of processed disassociation
|
||||
* @dev: network device
|
||||
* @buf: disassociation response frame (header + body)
|
||||
* @len: length of the frame data
|
||||
*
|
||||
* Like cfg80211_send_disassoc(), but doesn't take the wdev lock.
|
||||
*/
|
||||
void __cfg80211_send_disassoc(struct net_device *dev, const u8 *buf,
|
||||
size_t len);
|
||||
|
||||
/**
|
||||
* cfg80211_send_unprot_deauth - notification of unprotected deauthentication
|
||||
* @dev: network device
|
||||
|
@ -4153,6 +4176,7 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
|
|||
* cfg80211_crit_proto_stopped() - indicate critical protocol stopped by driver.
|
||||
*
|
||||
* @wdev: the wireless device for which critical protocol is stopped.
|
||||
* @gfp: allocation flags
|
||||
*
|
||||
* This function can be called by the driver to indicate it has reverted
|
||||
* operation back to normal. One reason could be that the duration given
|
||||
|
|
|
@ -269,6 +269,7 @@ enum ieee80211_radiotap_type {
|
|||
#define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04
|
||||
#define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08
|
||||
#define IEEE80211_RADIOTAP_MCS_HAVE_FEC 0x10
|
||||
#define IEEE80211_RADIOTAP_MCS_HAVE_STBC 0x20
|
||||
|
||||
#define IEEE80211_RADIOTAP_MCS_BW_MASK 0x03
|
||||
#define IEEE80211_RADIOTAP_MCS_BW_20 0
|
||||
|
@ -278,6 +279,12 @@ enum ieee80211_radiotap_type {
|
|||
#define IEEE80211_RADIOTAP_MCS_SGI 0x04
|
||||
#define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08
|
||||
#define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10
|
||||
#define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60
|
||||
#define IEEE80211_RADIOTAP_MCS_STBC_1 1
|
||||
#define IEEE80211_RADIOTAP_MCS_STBC_2 2
|
||||
#define IEEE80211_RADIOTAP_MCS_STBC_3 3
|
||||
|
||||
#define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5
|
||||
|
||||
/* For IEEE80211_RADIOTAP_AMPDU_STATUS */
|
||||
#define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001
|
||||
|
|
|
@ -805,6 +805,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
|
|||
* on this subframe
|
||||
* @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC
|
||||
* is stored in the @ampdu_delimiter_crc field)
|
||||
* @RX_FLAG_STBC_MASK: STBC 2 bit bitmask. 1 - Nss=1, 2 - Nss=2, 3 - Nss=3
|
||||
*/
|
||||
enum mac80211_rx_flags {
|
||||
RX_FLAG_MMIC_ERROR = BIT(0),
|
||||
|
@ -832,8 +833,11 @@ enum mac80211_rx_flags {
|
|||
RX_FLAG_80MHZ = BIT(23),
|
||||
RX_FLAG_80P80MHZ = BIT(24),
|
||||
RX_FLAG_160MHZ = BIT(25),
|
||||
RX_FLAG_STBC_MASK = BIT(26) | BIT(27),
|
||||
};
|
||||
|
||||
#define RX_FLAG_STBC_SHIFT 26
|
||||
|
||||
/**
|
||||
* struct ieee80211_rx_status - receive status
|
||||
*
|
||||
|
@ -850,6 +854,10 @@ enum mac80211_rx_flags {
|
|||
* @signal: signal strength when receiving this frame, either in dBm, in dB or
|
||||
* unspecified depending on the hardware capabilities flags
|
||||
* @IEEE80211_HW_SIGNAL_*
|
||||
* @chains: bitmask of receive chains for which separate signal strength
|
||||
* values were filled.
|
||||
* @chain_signal: per-chain signal strength, in dBm (unlike @signal, doesn't
|
||||
* support dB or unspecified units)
|
||||
* @antenna: antenna used
|
||||
* @rate_idx: index of data rate into band's supported rates or MCS index if
|
||||
* HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT)
|
||||
|
@ -881,6 +889,8 @@ struct ieee80211_rx_status {
|
|||
u8 band;
|
||||
u8 antenna;
|
||||
s8 signal;
|
||||
u8 chains;
|
||||
s8 chain_signal[IEEE80211_MAX_CHAINS];
|
||||
u8 ampdu_delimiter_crc;
|
||||
u8 vendor_radiotap_align;
|
||||
u8 vendor_radiotap_oui[3];
|
||||
|
@ -1235,7 +1245,7 @@ enum ieee80211_sta_rx_bandwidth {
|
|||
* struct ieee80211_sta_rates - station rate selection table
|
||||
*
|
||||
* @rcu_head: RCU head used for freeing the table on update
|
||||
* @rates: transmit rates/flags to be used by default.
|
||||
* @rate: transmit rates/flags to be used by default.
|
||||
* Overriding entries per-packet is possible by using cb tx control.
|
||||
*/
|
||||
struct ieee80211_sta_rates {
|
||||
|
@ -1276,7 +1286,7 @@ struct ieee80211_sta_rates {
|
|||
* notifications and capabilities. The value is only valid after
|
||||
* the station moves to associated state.
|
||||
* @smps_mode: current SMPS mode (off, static or dynamic)
|
||||
* @tx_rates: rate control selection table
|
||||
* @rates: rate control selection table
|
||||
*/
|
||||
struct ieee80211_sta {
|
||||
u32 supp_rates[IEEE80211_NUM_BANDS];
|
||||
|
@ -3043,7 +3053,8 @@ void ieee80211_napi_complete(struct ieee80211_hw *hw);
|
|||
* This function may not be called in IRQ context. Calls to this function
|
||||
* for a single hardware must be synchronized against each other. Calls to
|
||||
* this function, ieee80211_rx_ni() and ieee80211_rx_irqsafe() may not be
|
||||
* mixed for a single hardware.
|
||||
* mixed for a single hardware. Must not run concurrently with
|
||||
* ieee80211_tx_status() or ieee80211_tx_status_ni().
|
||||
*
|
||||
* In process context use instead ieee80211_rx_ni().
|
||||
*
|
||||
|
@ -3059,7 +3070,8 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb);
|
|||
* (internally defers to a tasklet.)
|
||||
*
|
||||
* Calls to this function, ieee80211_rx() or ieee80211_rx_ni() may not
|
||||
* be mixed for a single hardware.
|
||||
* be mixed for a single hardware.Must not run concurrently with
|
||||
* ieee80211_tx_status() or ieee80211_tx_status_ni().
|
||||
*
|
||||
* @hw: the hardware this frame came in on
|
||||
* @skb: the buffer to receive, owned by mac80211 after this call
|
||||
|
@ -3073,7 +3085,8 @@ void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb);
|
|||
* (internally disables bottom halves).
|
||||
*
|
||||
* Calls to this function, ieee80211_rx() and ieee80211_rx_irqsafe() may
|
||||
* not be mixed for a single hardware.
|
||||
* not be mixed for a single hardware. Must not run concurrently with
|
||||
* ieee80211_tx_status() or ieee80211_tx_status_ni().
|
||||
*
|
||||
* @hw: the hardware this frame came in on
|
||||
* @skb: the buffer to receive, owned by mac80211 after this call
|
||||
|
@ -3196,7 +3209,8 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif,
|
|||
* This function may not be called in IRQ context. Calls to this function
|
||||
* for a single hardware must be synchronized against each other. Calls
|
||||
* to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe()
|
||||
* may not be mixed for a single hardware.
|
||||
* may not be mixed for a single hardware. Must not run concurrently with
|
||||
* ieee80211_rx() or ieee80211_rx_ni().
|
||||
*
|
||||
* @hw: the hardware the frame was transmitted by
|
||||
* @skb: the frame that was transmitted, owned by mac80211 after this call
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define NL80211_GENL_NAME "nl80211"
|
||||
|
||||
/**
|
||||
* DOC: Station handling
|
||||
*
|
||||
|
@ -1429,6 +1431,11 @@ enum nl80211_commands {
|
|||
* @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which
|
||||
* the connection should have increased reliability (u16).
|
||||
*
|
||||
* @NL80211_ATTR_PEER_AID: Association ID for the peer TDLS station (u16).
|
||||
* This is similar to @NL80211_ATTR_STA_AID but with a difference of being
|
||||
* allowed to be used with the first @NL80211_CMD_SET_STATION command to
|
||||
* update a TDLS peer STA entry.
|
||||
*
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
*/
|
||||
|
@ -1727,6 +1734,8 @@ enum nl80211_attrs {
|
|||
NL80211_ATTR_CRIT_PROT_ID,
|
||||
NL80211_ATTR_MAX_CRIT_PROT_DURATION,
|
||||
|
||||
NL80211_ATTR_PEER_AID,
|
||||
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
|
@ -1991,6 +2000,10 @@ enum nl80211_sta_bss_param {
|
|||
* @NL80211_STA_INFO_PEER_PM: peer mesh STA link-specific power mode
|
||||
* @NL80211_STA_INFO_NONPEER_PM: neighbor mesh STA power save mode towards
|
||||
* non-peer STA
|
||||
* @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU
|
||||
* Contains a nested array of signal strength attributes (u8, dBm)
|
||||
* @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average
|
||||
* Same format as NL80211_STA_INFO_CHAIN_SIGNAL.
|
||||
* @__NL80211_STA_INFO_AFTER_LAST: internal
|
||||
* @NL80211_STA_INFO_MAX: highest possible station info attribute
|
||||
*/
|
||||
|
@ -2020,6 +2033,8 @@ enum nl80211_sta_info {
|
|||
NL80211_STA_INFO_NONPEER_PM,
|
||||
NL80211_STA_INFO_RX_BYTES64,
|
||||
NL80211_STA_INFO_TX_BYTES64,
|
||||
NL80211_STA_INFO_CHAIN_SIGNAL,
|
||||
NL80211_STA_INFO_CHAIN_SIGNAL_AVG,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_STA_INFO_AFTER_LAST,
|
||||
|
@ -2637,6 +2652,10 @@ enum nl80211_meshconf_params {
|
|||
* @NL80211_MESH_SETUP_USERSPACE_MPM: Enable this option if userspace will
|
||||
* implement an MPM which handles peer allocation and state.
|
||||
*
|
||||
* @NL80211_MESH_SETUP_AUTH_PROTOCOL: Inform the kernel of the authentication
|
||||
* method (u8, as defined in IEEE 8.4.2.100.6, e.g. 0x1 for SAE).
|
||||
* Default is no authentication method required.
|
||||
*
|
||||
* @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number
|
||||
*
|
||||
* @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use
|
||||
|
@ -2650,6 +2669,7 @@ enum nl80211_mesh_setup_params {
|
|||
NL80211_MESH_SETUP_USERSPACE_AMPE,
|
||||
NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC,
|
||||
NL80211_MESH_SETUP_USERSPACE_MPM,
|
||||
NL80211_MESH_SETUP_AUTH_PROTOCOL,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_MESH_SETUP_ATTR_AFTER_LAST,
|
||||
|
|
|
@ -85,7 +85,7 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
|
|||
*cpos++ = *pos++ ^ e[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < CCMP_MIC_LEN; i++)
|
||||
for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++)
|
||||
mic[i] = b[i] ^ s_0[i];
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,7 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
|
|||
crypto_cipher_encrypt_one(tfm, a, a);
|
||||
}
|
||||
|
||||
for (i = 0; i < CCMP_MIC_LEN; i++) {
|
||||
for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++) {
|
||||
if ((mic[i] ^ s_0[i]) != a[i])
|
||||
return -1;
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[])
|
|||
|
||||
tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
|
||||
if (!IS_ERR(tfm))
|
||||
crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN);
|
||||
crypto_cipher_setkey(tfm, key, WLAN_KEY_LEN_CCMP);
|
||||
|
||||
return tfm;
|
||||
}
|
||||
|
|
|
@ -444,7 +444,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|||
struct ieee80211_local *local = sdata->local;
|
||||
struct timespec uptime;
|
||||
u64 packets = 0;
|
||||
int ac;
|
||||
int i, ac;
|
||||
|
||||
sinfo->generation = sdata->local->sta_generation;
|
||||
|
||||
|
@ -488,6 +488,17 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|||
sinfo->signal = (s8)sta->last_signal;
|
||||
sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
|
||||
}
|
||||
if (sta->chains) {
|
||||
sinfo->filled |= STATION_INFO_CHAIN_SIGNAL |
|
||||
STATION_INFO_CHAIN_SIGNAL_AVG;
|
||||
|
||||
sinfo->chains = sta->chains;
|
||||
for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
|
||||
sinfo->chain_signal[i] = sta->chain_signal_last[i];
|
||||
sinfo->chain_signal_avg[i] =
|
||||
(s8) -ewma_read(&sta->chain_signal_avg[i]);
|
||||
}
|
||||
}
|
||||
|
||||
sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
|
||||
sta_set_rate_info_rx(sta, &sinfo->rxrate);
|
||||
|
@ -728,7 +739,7 @@ static void ieee80211_get_et_strings(struct wiphy *wiphy,
|
|||
|
||||
if (sset == ETH_SS_STATS) {
|
||||
sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats);
|
||||
memcpy(data, *ieee80211_gstrings_sta_stats, sz_sta_stats);
|
||||
memcpy(data, ieee80211_gstrings_sta_stats, sz_sta_stats);
|
||||
}
|
||||
drv_get_et_strings(sdata, sset, &(data[sz_sta_stats]));
|
||||
}
|
||||
|
@ -1735,6 +1746,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
|
|||
ifmsh->mesh_pp_id = setup->path_sel_proto;
|
||||
ifmsh->mesh_pm_id = setup->path_metric;
|
||||
ifmsh->user_mpm = setup->user_mpm;
|
||||
ifmsh->mesh_auth_id = setup->auth_id;
|
||||
ifmsh->security = IEEE80211_MESH_SEC_NONE;
|
||||
if (setup->is_authenticated)
|
||||
ifmsh->security |= IEEE80211_MESH_SEC_AUTHED;
|
||||
|
@ -2306,7 +2318,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
|
|||
enum ieee80211_smps_mode old_req;
|
||||
int err;
|
||||
|
||||
lockdep_assert_held(&sdata->u.mgd.mtx);
|
||||
lockdep_assert_held(&sdata->wdev.mtx);
|
||||
|
||||
old_req = sdata->u.mgd.req_smps;
|
||||
sdata->u.mgd.req_smps = smps_mode;
|
||||
|
@ -2363,9 +2375,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
|
|||
local->dynamic_ps_forced_timeout = timeout;
|
||||
|
||||
/* no change, but if automatic follow powersave */
|
||||
mutex_lock(&sdata->u.mgd.mtx);
|
||||
__ieee80211_request_smps(sdata, sdata->u.mgd.req_smps);
|
||||
mutex_unlock(&sdata->u.mgd.mtx);
|
||||
|
||||
if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
|
||||
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
|
||||
|
|
|
@ -228,9 +228,9 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
|
|||
if (sdata->vif.type != NL80211_IFTYPE_STATION)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&sdata->u.mgd.mtx);
|
||||
sdata_lock(sdata);
|
||||
err = __ieee80211_request_smps(sdata, smps_mode);
|
||||
mutex_unlock(&sdata->u.mgd.mtx);
|
||||
sdata_unlock(sdata);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -313,16 +313,16 @@ static ssize_t ieee80211_if_parse_tkip_mic_test(
|
|||
case NL80211_IFTYPE_STATION:
|
||||
fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
|
||||
/* BSSID SA DA */
|
||||
mutex_lock(&sdata->u.mgd.mtx);
|
||||
sdata_lock(sdata);
|
||||
if (!sdata->u.mgd.associated) {
|
||||
mutex_unlock(&sdata->u.mgd.mtx);
|
||||
sdata_unlock(sdata);
|
||||
dev_kfree_skb(skb);
|
||||
return -ENOTCONN;
|
||||
}
|
||||
memcpy(hdr->addr1, sdata->u.mgd.associated->bssid, ETH_ALEN);
|
||||
memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
|
||||
memcpy(hdr->addr3, addr, ETH_ALEN);
|
||||
mutex_unlock(&sdata->u.mgd.mtx);
|
||||
sdata_unlock(sdata);
|
||||
break;
|
||||
default:
|
||||
dev_kfree_skb(skb);
|
||||
|
@ -471,6 +471,8 @@ __IEEE80211_IF_FILE_W(tsf);
|
|||
IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
|
||||
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
IEEE80211_IF_FILE(estab_plinks, u.mesh.estab_plinks, ATOMIC);
|
||||
|
||||
/* Mesh stats attributes */
|
||||
IEEE80211_IF_FILE(fwded_mcast, u.mesh.mshstats.fwded_mcast, DEC);
|
||||
IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC);
|
||||
|
@ -480,7 +482,6 @@ IEEE80211_IF_FILE(dropped_frames_congestion,
|
|||
u.mesh.mshstats.dropped_frames_congestion, DEC);
|
||||
IEEE80211_IF_FILE(dropped_frames_no_route,
|
||||
u.mesh.mshstats.dropped_frames_no_route, DEC);
|
||||
IEEE80211_IF_FILE(estab_plinks, u.mesh.estab_plinks, ATOMIC);
|
||||
|
||||
/* Mesh parameters */
|
||||
IEEE80211_IF_FILE(dot11MeshMaxRetries,
|
||||
|
@ -583,6 +584,7 @@ static void add_wds_files(struct ieee80211_sub_if_data *sdata)
|
|||
static void add_mesh_files(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
DEBUGFS_ADD_MODE(tsf, 0600);
|
||||
DEBUGFS_ADD_MODE(estab_plinks, 0400);
|
||||
}
|
||||
|
||||
static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
|
||||
|
@ -598,7 +600,6 @@ static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
|
|||
MESHSTATS_ADD(dropped_frames_ttl);
|
||||
MESHSTATS_ADD(dropped_frames_no_route);
|
||||
MESHSTATS_ADD(dropped_frames_congestion);
|
||||
MESHSTATS_ADD(estab_plinks);
|
||||
#undef MESHSTATS_ADD
|
||||
}
|
||||
|
||||
|
|
|
@ -429,9 +429,9 @@ void ieee80211_request_smps_work(struct work_struct *work)
|
|||
container_of(work, struct ieee80211_sub_if_data,
|
||||
u.mgd.request_smps_work);
|
||||
|
||||
mutex_lock(&sdata->u.mgd.mtx);
|
||||
sdata_lock(sdata);
|
||||
__ieee80211_request_smps(sdata, sdata->u.mgd.driver_smps_mode);
|
||||
mutex_unlock(&sdata->u.mgd.mtx);
|
||||
sdata_unlock(sdata);
|
||||
}
|
||||
|
||||
void ieee80211_request_smps(struct ieee80211_vif *vif,
|
||||
|
|
|
@ -54,7 +54,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
|||
struct beacon_data *presp;
|
||||
int frame_len;
|
||||
|
||||
lockdep_assert_held(&ifibss->mtx);
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
/* Reset own TSF to allow time synchronization work. */
|
||||
drv_reset_tsf(local, sdata);
|
||||
|
@ -74,7 +74,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
|||
}
|
||||
|
||||
presp = rcu_dereference_protected(ifibss->presp,
|
||||
lockdep_is_held(&ifibss->mtx));
|
||||
lockdep_is_held(&sdata->wdev.mtx));
|
||||
rcu_assign_pointer(ifibss->presp, NULL);
|
||||
if (presp)
|
||||
kfree_rcu(presp, rcu_head);
|
||||
|
@ -263,7 +263,7 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
|||
const struct cfg80211_bss_ies *ies;
|
||||
u64 tsf;
|
||||
|
||||
lockdep_assert_held(&sdata->u.ibss.mtx);
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
if (beacon_int < 10)
|
||||
beacon_int = 10;
|
||||
|
@ -341,6 +341,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
|
|||
struct ieee80211_local *local = sdata->local;
|
||||
struct sta_info *sta;
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
struct ieee80211_supported_band *sband;
|
||||
int band;
|
||||
|
||||
/*
|
||||
|
@ -380,8 +381,9 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
|
|||
sta->last_rx = jiffies;
|
||||
|
||||
/* make sure mandatory rates are always added */
|
||||
sband = local->hw.wiphy->bands[band];
|
||||
sta->sta.supp_rates[band] = supp_rates |
|
||||
ieee80211_mandatory_rates(local, band);
|
||||
ieee80211_mandatory_rates(sband);
|
||||
|
||||
return ieee80211_ibss_finish_sta(sta, auth);
|
||||
}
|
||||
|
@ -408,7 +410,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
|
|||
struct sta_info *sta;
|
||||
u8 deauth_frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
|
||||
|
||||
lockdep_assert_held(&sdata->u.ibss.mtx);
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
if (len < 24 + 6)
|
||||
return;
|
||||
|
@ -492,7 +494,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
|||
prev_rates = sta->sta.supp_rates[band];
|
||||
/* make sure mandatory rates are always added */
|
||||
sta->sta.supp_rates[band] = supp_rates |
|
||||
ieee80211_mandatory_rates(local, band);
|
||||
ieee80211_mandatory_rates(sband);
|
||||
|
||||
if (sta->sta.supp_rates[band] != prev_rates) {
|
||||
ibss_dbg(sdata,
|
||||
|
@ -624,6 +626,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
|
|||
struct ieee80211_local *local = sdata->local;
|
||||
struct sta_info *sta;
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
struct ieee80211_supported_band *sband;
|
||||
int band;
|
||||
|
||||
/*
|
||||
|
@ -658,8 +661,9 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
|
|||
sta->last_rx = jiffies;
|
||||
|
||||
/* make sure mandatory rates are always added */
|
||||
sband = local->hw.wiphy->bands[band];
|
||||
sta->sta.supp_rates[band] = supp_rates |
|
||||
ieee80211_mandatory_rates(local, band);
|
||||
ieee80211_mandatory_rates(sband);
|
||||
|
||||
spin_lock(&ifibss->incomplete_lock);
|
||||
list_add(&sta->list, &ifibss->incomplete_stations);
|
||||
|
@ -673,7 +677,7 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
|
|||
int active = 0;
|
||||
struct sta_info *sta;
|
||||
|
||||
lockdep_assert_held(&sdata->u.ibss.mtx);
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
|
@ -699,7 +703,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
|
|||
{
|
||||
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
|
||||
|
||||
lockdep_assert_held(&ifibss->mtx);
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
mod_timer(&ifibss->timer,
|
||||
round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
|
||||
|
@ -730,7 +734,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
|
|||
u16 capability;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&ifibss->mtx);
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
if (ifibss->fixed_bssid) {
|
||||
memcpy(bssid, ifibss->bssid, ETH_ALEN);
|
||||
|
@ -773,7 +777,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
|
|||
int active_ibss;
|
||||
u16 capability;
|
||||
|
||||
lockdep_assert_held(&ifibss->mtx);
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
active_ibss = ieee80211_sta_active_ibss(sdata);
|
||||
ibss_dbg(sdata, "sta_find_ibss (active_ibss=%d)\n", active_ibss);
|
||||
|
@ -843,10 +847,10 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
|
|||
struct beacon_data *presp;
|
||||
u8 *pos, *end;
|
||||
|
||||
lockdep_assert_held(&ifibss->mtx);
|
||||
sdata_assert_lock(sdata);
|
||||
|
||||
presp = rcu_dereference_protected(ifibss->presp,
|
||||
lockdep_is_held(&ifibss->mtx));
|
||||
lockdep_is_held(&sdata->wdev.mtx));
|
||||
|
||||
if (ifibss->state != IEEE80211_IBSS_MLME_JOINED ||
|
||||
len < 24 + 2 || !presp)
|
||||
|
@ -930,7 +934,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
|
|||
mgmt = (struct ieee80211_mgmt *) skb->data;
|
||||
fc = le16_to_cpu(mgmt->frame_control);
|
||||
|
||||
mutex_lock(&sdata->u.ibss.mtx);
|
||||
sdata_lock(sdata);
|
||||
|
||||
if (!sdata->u.ibss.ssid_len)
|
||||
goto mgmt_out; /* not ready to merge yet */
|
||||
|
@ -953,7 +957,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
|
|||
}
|
||||
|
||||
mgmt_out:
|
||||
mutex_unlock(&sdata->u.ibss.mtx);
|
||||
sdata_unlock(sdata);
|
||||
}
|
||||
|
||||
void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
|
||||
|
@ -961,7 +965,7 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
|
|||
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
|
||||
struct sta_info *sta;
|
||||
|
||||
mutex_lock(&ifibss->mtx);
|
||||
sdata_lock(sdata);
|
||||
|
||||
/*
|
||||
* Work could be scheduled after scan or similar
|
||||
|
@ -997,7 +1001,7 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
|
|||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&ifibss->mtx);
|
||||
sdata_unlock(sdata);
|
||||
}
|
||||
|
||||
static void ieee80211_ibss_timer(unsigned long data)
|
||||
|
@ -1014,7 +1018,6 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
|
|||
|
||||
setup_timer(&ifibss->timer, ieee80211_ibss_timer,
|
||||
(unsigned long) sdata);
|
||||
mutex_init(&ifibss->mtx);
|
||||
INIT_LIST_HEAD(&ifibss->incomplete_stations);
|
||||
spin_lock_init(&ifibss->incomplete_lock);
|
||||
}
|
||||
|
@ -1041,8 +1044,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
|
|||
{
|
||||
u32 changed = 0;
|
||||
|
||||
mutex_lock(&sdata->u.ibss.mtx);
|
||||
|
||||
if (params->bssid) {
|
||||
memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN);
|
||||
sdata->u.ibss.fixed_bssid = true;
|
||||
|
@ -1075,8 +1076,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
|
|||
memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len);
|
||||
sdata->u.ibss.ssid_len = params->ssid_len;
|
||||
|
||||
mutex_unlock(&sdata->u.ibss.mtx);
|
||||
|
||||
/*
|
||||
* 802.11n-2009 9.13.3.1: In an IBSS, the HT Protection field is
|
||||
* reserved, but an HT STA shall protect HT transmissions as though
|
||||
|
@ -1112,8 +1111,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
|
|||
struct sta_info *sta;
|
||||
struct beacon_data *presp;
|
||||
|
||||
mutex_lock(&sdata->u.ibss.mtx);
|
||||
|
||||
active_ibss = ieee80211_sta_active_ibss(sdata);
|
||||
|
||||
if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) {
|
||||
|
@ -1157,7 +1154,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
|
|||
/* remove beacon */
|
||||
kfree(sdata->u.ibss.ie);
|
||||
presp = rcu_dereference_protected(ifibss->presp,
|
||||
lockdep_is_held(&sdata->u.ibss.mtx));
|
||||
lockdep_is_held(&sdata->wdev.mtx));
|
||||
RCU_INIT_POINTER(sdata->u.ibss.presp, NULL);
|
||||
sdata->vif.bss_conf.ibss_joined = false;
|
||||
sdata->vif.bss_conf.ibss_creator = false;
|
||||
|
@ -1173,7 +1170,5 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
|
|||
|
||||
del_timer_sync(&sdata->u.ibss.timer);
|
||||
|
||||
mutex_unlock(&sdata->u.ibss.mtx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -394,7 +394,6 @@ struct ieee80211_if_managed {
|
|||
bool nullfunc_failed;
|
||||
bool connection_loss;
|
||||
|
||||
struct mutex mtx;
|
||||
struct cfg80211_bss *associated;
|
||||
struct ieee80211_mgd_auth_data *auth_data;
|
||||
struct ieee80211_mgd_assoc_data *assoc_data;
|
||||
|
@ -488,8 +487,6 @@ struct ieee80211_if_managed {
|
|||
struct ieee80211_if_ibss {
|
||||
struct timer_list timer;
|
||||
|
||||
struct mutex mtx;
|
||||
|
||||
unsigned long last_scan_completed;
|
||||
|
||||
u32 basic_rates;
|
||||
|
@ -580,8 +577,6 @@ struct ieee80211_if_mesh {
|
|||
bool accepting_plinks;
|
||||
int num_gates;
|
||||
struct beacon_data __rcu *beacon;
|
||||
/* just protects beacon updates for now */
|
||||
struct mutex mtx;
|
||||
const u8 *ie;
|
||||
u8 ie_len;
|
||||
enum {
|
||||
|
@ -778,6 +773,26 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p)
|
|||
return container_of(p, struct ieee80211_sub_if_data, vif);
|
||||
}
|
||||
|
||||
static inline void sdata_lock(struct ieee80211_sub_if_data *sdata)
|
||||
__acquires(&sdata->wdev.mtx)
|
||||
{
|
||||
mutex_lock(&sdata->wdev.mtx);
|
||||
__acquire(&sdata->wdev.mtx);
|
||||
}
|
||||
|
||||
static inline void sdata_unlock(struct ieee80211_sub_if_data *sdata)
|
||||
__releases(&sdata->wdev.mtx)
|
||||
{
|
||||
mutex_unlock(&sdata->wdev.mtx);
|
||||
__release(&sdata->wdev.mtx);
|
||||
}
|
||||
|
||||
static inline void
|
||||
sdata_assert_lock(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
lockdep_assert_held(&sdata->wdev.mtx);
|
||||
}
|
||||
|
||||
static inline enum ieee80211_band
|
||||
ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
|
@ -1267,6 +1282,7 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata);
|
|||
void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata);
|
||||
void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata,
|
||||
__le16 fc, bool acked);
|
||||
void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);
|
||||
|
||||
/* IBSS code */
|
||||
void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
|
||||
|
@ -1505,9 +1521,6 @@ static inline void ieee802_11_parse_elems(u8 *start, size_t len, bool action,
|
|||
ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0);
|
||||
}
|
||||
|
||||
u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
|
||||
enum ieee80211_band band);
|
||||
|
||||
void ieee80211_dynamic_ps_enable_work(struct work_struct *work);
|
||||
void ieee80211_dynamic_ps_disable_work(struct work_struct *work);
|
||||
void ieee80211_dynamic_ps_timer(unsigned long data);
|
||||
|
|
|
@ -474,6 +474,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
|
|||
master->control_port_protocol;
|
||||
sdata->control_port_no_encrypt =
|
||||
master->control_port_no_encrypt;
|
||||
sdata->vif.cab_queue = master->vif.cab_queue;
|
||||
memcpy(sdata->vif.hw_queue, master->vif.hw_queue,
|
||||
sizeof(sdata->vif.hw_queue));
|
||||
break;
|
||||
}
|
||||
case NL80211_IFTYPE_AP:
|
||||
|
@ -653,7 +656,11 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
|
|||
|
||||
ieee80211_recalc_ps(local, -1);
|
||||
|
||||
if (dev) {
|
||||
if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
|
||||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
|
||||
/* XXX: for AP_VLAN, actually track AP queues */
|
||||
netif_tx_start_all_queues(dev);
|
||||
} else if (dev) {
|
||||
unsigned long flags;
|
||||
int n_acs = IEEE80211_NUM_ACS;
|
||||
int ac;
|
||||
|
@ -1696,6 +1703,15 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)
|
|||
|
||||
ASSERT_RTNL();
|
||||
|
||||
/*
|
||||
* Close all AP_VLAN interfaces first, as otherwise they
|
||||
* might be closed while the AP interface they belong to
|
||||
* is closed, causing unregister_netdevice_many() to crash.
|
||||
*/
|
||||
list_for_each_entry(sdata, &local->interfaces, list)
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||
dev_close(sdata->dev);
|
||||
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
|
||||
list_del(&sdata->list);
|
||||
|
|
|
@ -335,12 +335,12 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
|
|||
switch (cipher) {
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
key->conf.iv_len = WEP_IV_LEN;
|
||||
key->conf.icv_len = WEP_ICV_LEN;
|
||||
key->conf.iv_len = IEEE80211_WEP_IV_LEN;
|
||||
key->conf.icv_len = IEEE80211_WEP_ICV_LEN;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
key->conf.iv_len = TKIP_IV_LEN;
|
||||
key->conf.icv_len = TKIP_ICV_LEN;
|
||||
key->conf.iv_len = IEEE80211_TKIP_IV_LEN;
|
||||
key->conf.icv_len = IEEE80211_TKIP_ICV_LEN;
|
||||
if (seq) {
|
||||
for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
|
||||
key->u.tkip.rx[i].iv32 =
|
||||
|
@ -352,13 +352,13 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
|
|||
spin_lock_init(&key->u.tkip.txlock);
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
key->conf.iv_len = CCMP_HDR_LEN;
|
||||
key->conf.icv_len = CCMP_MIC_LEN;
|
||||
key->conf.iv_len = IEEE80211_CCMP_HDR_LEN;
|
||||
key->conf.icv_len = IEEE80211_CCMP_MIC_LEN;
|
||||
if (seq) {
|
||||
for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
|
||||
for (j = 0; j < CCMP_PN_LEN; j++)
|
||||
for (j = 0; j < IEEE80211_CCMP_PN_LEN; j++)
|
||||
key->u.ccmp.rx_pn[i][j] =
|
||||
seq[CCMP_PN_LEN - j - 1];
|
||||
seq[IEEE80211_CCMP_PN_LEN - j - 1];
|
||||
}
|
||||
/*
|
||||
* Initialize AES key state here as an optimization so that
|
||||
|
@ -375,9 +375,9 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
|
|||
key->conf.iv_len = 0;
|
||||
key->conf.icv_len = sizeof(struct ieee80211_mmie);
|
||||
if (seq)
|
||||
for (j = 0; j < CMAC_PN_LEN; j++)
|
||||
for (j = 0; j < IEEE80211_CMAC_PN_LEN; j++)
|
||||
key->u.aes_cmac.rx_pn[j] =
|
||||
seq[CMAC_PN_LEN - j - 1];
|
||||
seq[IEEE80211_CMAC_PN_LEN - j - 1];
|
||||
/*
|
||||
* Initialize AES key state here as an optimization so that
|
||||
* it does not need to be initialized for every packet.
|
||||
|
@ -740,13 +740,13 @@ void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
|
|||
pn = key->u.ccmp.rx_pn[IEEE80211_NUM_TIDS];
|
||||
else
|
||||
pn = key->u.ccmp.rx_pn[tid];
|
||||
memcpy(seq->ccmp.pn, pn, CCMP_PN_LEN);
|
||||
memcpy(seq->ccmp.pn, pn, IEEE80211_CCMP_PN_LEN);
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
if (WARN_ON(tid != 0))
|
||||
return;
|
||||
pn = key->u.aes_cmac.rx_pn;
|
||||
memcpy(seq->aes_cmac.pn, pn, CMAC_PN_LEN);
|
||||
memcpy(seq->aes_cmac.pn, pn, IEEE80211_CMAC_PN_LEN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,17 +19,6 @@
|
|||
#define NUM_DEFAULT_KEYS 4
|
||||
#define NUM_DEFAULT_MGMT_KEYS 2
|
||||
|
||||
#define WEP_IV_LEN 4
|
||||
#define WEP_ICV_LEN 4
|
||||
#define ALG_CCMP_KEY_LEN 16
|
||||
#define CCMP_HDR_LEN 8
|
||||
#define CCMP_MIC_LEN 8
|
||||
#define CCMP_TK_LEN 16
|
||||
#define CCMP_PN_LEN 6
|
||||
#define TKIP_IV_LEN 8
|
||||
#define TKIP_ICV_LEN 4
|
||||
#define CMAC_PN_LEN 6
|
||||
|
||||
struct ieee80211_local;
|
||||
struct ieee80211_sub_if_data;
|
||||
struct sta_info;
|
||||
|
@ -93,13 +82,13 @@ struct ieee80211_key {
|
|||
* frames and the last counter is used with Robust
|
||||
* Management frames.
|
||||
*/
|
||||
u8 rx_pn[IEEE80211_NUM_TIDS + 1][CCMP_PN_LEN];
|
||||
u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN];
|
||||
struct crypto_cipher *tfm;
|
||||
u32 replays; /* dot11RSNAStatsCCMPReplays */
|
||||
} ccmp;
|
||||
struct {
|
||||
atomic64_t tx_pn;
|
||||
u8 rx_pn[CMAC_PN_LEN];
|
||||
u8 rx_pn[IEEE80211_CMAC_PN_LEN];
|
||||
struct crypto_cipher *tfm;
|
||||
u32 replays; /* dot11RSNAStatsCMACReplays */
|
||||
u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
|
||||
|
|
|
@ -331,7 +331,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
|
|||
return NOTIFY_DONE;
|
||||
|
||||
ifmgd = &sdata->u.mgd;
|
||||
mutex_lock(&ifmgd->mtx);
|
||||
sdata_lock(sdata);
|
||||
|
||||
/* Copy the addresses to the bss_conf list */
|
||||
ifa = idev->ifa_list;
|
||||
|
@ -349,7 +349,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
|
|||
ieee80211_bss_info_change_notify(sdata,
|
||||
BSS_CHANGED_ARP_FILTER);
|
||||
|
||||
mutex_unlock(&ifmgd->mtx);
|
||||
sdata_unlock(sdata);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
|
|
@ -161,8 +161,11 @@ void mesh_sta_cleanup(struct sta_info *sta)
|
|||
del_timer_sync(&sta->plink_timer);
|
||||
}
|
||||
|
||||
if (changed)
|
||||
if (changed) {
|
||||
sdata_lock(sdata);
|
||||
ieee80211_mbss_info_change_notify(sdata, changed);
|
||||
sdata_unlock(sdata);
|
||||
}
|
||||
}
|
||||
|
||||
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata)
|
||||
|
@ -577,7 +580,9 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata)
|
|||
mesh_path_expire(sdata);
|
||||
|
||||
changed = mesh_accept_plinks_update(sdata);
|
||||
sdata_lock(sdata);
|
||||
ieee80211_mbss_info_change_notify(sdata, changed);
|
||||
sdata_unlock(sdata);
|
||||
|
||||
mod_timer(&ifmsh->housekeeping_timer,
|
||||
round_jiffies(jiffies +
|
||||
|
@ -697,25 +702,21 @@ out_free:
|
|||
}
|
||||
|
||||
static int
|
||||
ieee80211_mesh_rebuild_beacon(struct ieee80211_if_mesh *ifmsh)
|
||||
ieee80211_mesh_rebuild_beacon(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct beacon_data *old_bcn;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ifmsh->mtx);
|
||||
|
||||
old_bcn = rcu_dereference_protected(ifmsh->beacon,
|
||||
lockdep_is_held(&ifmsh->mtx));
|
||||
ret = ieee80211_mesh_build_beacon(ifmsh);
|
||||
old_bcn = rcu_dereference_protected(sdata->u.mesh.beacon,
|
||||
lockdep_is_held(&sdata->wdev.mtx));
|
||||
ret = ieee80211_mesh_build_beacon(&sdata->u.mesh);
|
||||
if (ret)
|
||||
/* just reuse old beacon */
|
||||
goto out;
|
||||
return ret;
|
||||
|
||||
if (old_bcn)
|
||||
kfree_rcu(old_bcn, rcu_head);
|
||||
out:
|
||||
mutex_unlock(&ifmsh->mtx);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata,
|
||||
|
@ -726,7 +727,7 @@ void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata,
|
|||
BSS_CHANGED_HT |
|
||||
BSS_CHANGED_BASIC_RATES |
|
||||
BSS_CHANGED_BEACON_INT)))
|
||||
if (ieee80211_mesh_rebuild_beacon(&sdata->u.mesh))
|
||||
if (ieee80211_mesh_rebuild_beacon(sdata))
|
||||
return;
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
}
|
||||
|
@ -741,6 +742,8 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
|
|||
BSS_CHANGED_BASIC_RATES |
|
||||
BSS_CHANGED_BEACON_INT;
|
||||
enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
|
||||
struct ieee80211_supported_band *sband =
|
||||
sdata->local->hw.wiphy->bands[band];
|
||||
|
||||
local->fif_other_bss++;
|
||||
/* mesh ifaces must set allmulti to forward mcast traffic */
|
||||
|
@ -748,7 +751,6 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
|
|||
ieee80211_configure_filter(local);
|
||||
|
||||
ifmsh->mesh_cc_id = 0; /* Disabled */
|
||||
ifmsh->mesh_auth_id = 0; /* Disabled */
|
||||
/* register sync ops from extensible synchronization framework */
|
||||
ifmsh->sync_ops = ieee80211_mesh_sync_ops_get(ifmsh->mesh_sp_id);
|
||||
ifmsh->adjusting_tbtt = false;
|
||||
|
@ -759,8 +761,7 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
|
|||
sdata->vif.bss_conf.ht_operation_mode =
|
||||
ifmsh->mshcfg.ht_opmode;
|
||||
sdata->vif.bss_conf.enable_beacon = true;
|
||||
sdata->vif.bss_conf.basic_rates =
|
||||
ieee80211_mandatory_rates(local, band);
|
||||
sdata->vif.bss_conf.basic_rates = ieee80211_mandatory_rates(sband);
|
||||
|
||||
changed |= ieee80211_mps_local_status_update(sdata);
|
||||
|
||||
|
@ -788,12 +789,12 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
|
|||
sdata->vif.bss_conf.enable_beacon = false;
|
||||
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
|
||||
mutex_lock(&ifmsh->mtx);
|
||||
sdata_lock(sdata);
|
||||
bcn = rcu_dereference_protected(ifmsh->beacon,
|
||||
lockdep_is_held(&ifmsh->mtx));
|
||||
lockdep_is_held(&sdata->wdev.mtx));
|
||||
rcu_assign_pointer(ifmsh->beacon, NULL);
|
||||
kfree_rcu(bcn, rcu_head);
|
||||
mutex_unlock(&ifmsh->mtx);
|
||||
sdata_unlock(sdata);
|
||||
|
||||
/* flush STAs and mpaths on this iface */
|
||||
sta_info_flush(sdata);
|
||||
|
@ -1041,7 +1042,6 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
|
|||
spin_lock_init(&ifmsh->mesh_preq_queue_lock);
|
||||
spin_lock_init(&ifmsh->sync_offset_lock);
|
||||
RCU_INIT_POINTER(ifmsh->beacon, NULL);
|
||||
mutex_init(&ifmsh->mtx);
|
||||
|
||||
sdata->vif.bss_conf.bssid = zero_addr;
|
||||
}
|
||||
|
|
|
@ -517,7 +517,9 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
|
|||
ieee80211_mps_frame_release(sta, elems);
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
sdata_lock(sdata);
|
||||
ieee80211_mbss_info_change_notify(sdata, changed);
|
||||
sdata_unlock(sdata);
|
||||
}
|
||||
|
||||
static void mesh_plink_timer(unsigned long data)
|
||||
|
@ -1068,6 +1070,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
rcu_read_unlock();
|
||||
|
||||
if (changed)
|
||||
if (changed) {
|
||||
sdata_lock(sdata);
|
||||
ieee80211_mbss_info_change_notify(sdata, changed);
|
||||
sdata_unlock(sdata);
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -688,8 +688,15 @@ int rate_control_set_rates(struct ieee80211_hw *hw,
|
|||
struct ieee80211_sta *pubsta,
|
||||
struct ieee80211_sta_rates *rates)
|
||||
{
|
||||
struct ieee80211_sta_rates *old = rcu_dereference(pubsta->rates);
|
||||
struct ieee80211_sta_rates *old;
|
||||
|
||||
/*
|
||||
* mac80211 guarantees that this function will not be called
|
||||
* concurrently, so the following RCU access is safe, even without
|
||||
* extra locking. This can not be checked easily, so we just set
|
||||
* the condition to true.
|
||||
*/
|
||||
old = rcu_dereference_protected(pubsta->rates, true);
|
||||
rcu_assign_pointer(pubsta->rates, rates);
|
||||
if (old)
|
||||
kfree_rcu(old, rcu_head);
|
||||
|
|
|
@ -258,6 +258,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
|||
pos += 2;
|
||||
|
||||
if (status->flag & RX_FLAG_HT) {
|
||||
unsigned int stbc;
|
||||
|
||||
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);
|
||||
*pos++ = local->hw.radiotap_mcs_details;
|
||||
*pos = 0;
|
||||
|
@ -267,6 +269,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
|
|||
*pos |= IEEE80211_RADIOTAP_MCS_BW_40;
|
||||
if (status->flag & RX_FLAG_HT_GF)
|
||||
*pos |= IEEE80211_RADIOTAP_MCS_FMT_GF;
|
||||
stbc = (status->flag & RX_FLAG_STBC_MASK) >> RX_FLAG_STBC_SHIFT;
|
||||
*pos |= stbc << IEEE80211_RADIOTAP_MCS_STBC_SHIFT;
|
||||
pos++;
|
||||
*pos++ = status->rate_idx;
|
||||
}
|
||||
|
@ -1372,6 +1376,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
|||
struct sk_buff *skb = rx->skb;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
int i;
|
||||
|
||||
if (!sta)
|
||||
return RX_CONTINUE;
|
||||
|
@ -1422,6 +1427,19 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
|||
ewma_add(&sta->avg_signal, -status->signal);
|
||||
}
|
||||
|
||||
if (status->chains) {
|
||||
sta->chains = status->chains;
|
||||
for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) {
|
||||
int signal = status->chain_signal[i];
|
||||
|
||||
if (!(status->chains & BIT(i)))
|
||||
continue;
|
||||
|
||||
sta->chain_signal_last[i] = signal;
|
||||
ewma_add(&sta->chain_signal_avg[i], -signal);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Change STA power saving mode only at the end of a frame
|
||||
* exchange sequence.
|
||||
|
@ -1608,7 +1626,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
|||
entry->ccmp = 1;
|
||||
memcpy(entry->last_pn,
|
||||
rx->key->u.ccmp.rx_pn[queue],
|
||||
CCMP_PN_LEN);
|
||||
IEEE80211_CCMP_PN_LEN);
|
||||
}
|
||||
return RX_QUEUED;
|
||||
}
|
||||
|
@ -1627,21 +1645,21 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
|||
* (IEEE 802.11i, 8.3.3.4.5) */
|
||||
if (entry->ccmp) {
|
||||
int i;
|
||||
u8 pn[CCMP_PN_LEN], *rpn;
|
||||
u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
|
||||
int queue;
|
||||
if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP)
|
||||
return RX_DROP_UNUSABLE;
|
||||
memcpy(pn, entry->last_pn, CCMP_PN_LEN);
|
||||
for (i = CCMP_PN_LEN - 1; i >= 0; i--) {
|
||||
memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
|
||||
for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
|
||||
pn[i]++;
|
||||
if (pn[i])
|
||||
break;
|
||||
}
|
||||
queue = rx->security_idx;
|
||||
rpn = rx->key->u.ccmp.rx_pn[queue];
|
||||
if (memcmp(pn, rpn, CCMP_PN_LEN))
|
||||
if (memcmp(pn, rpn, IEEE80211_CCMP_PN_LEN))
|
||||
return RX_DROP_UNUSABLE;
|
||||
memcpy(entry->last_pn, pn, CCMP_PN_LEN);
|
||||
memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN);
|
||||
}
|
||||
|
||||
skb_pull(rx->skb, ieee80211_hdrlen(fc));
|
||||
|
@ -3036,6 +3054,9 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
|
|||
* and location updates. Note that mac80211
|
||||
* itself never looks at these frames.
|
||||
*/
|
||||
if (!multicast &&
|
||||
!ether_addr_equal(sdata->vif.addr, hdr->addr1))
|
||||
return 0;
|
||||
if (ieee80211_is_public_action(hdr, skb->len))
|
||||
return 1;
|
||||
if (!ieee80211_is_beacon(hdr->frame_control))
|
||||
|
|
|
@ -358,6 +358,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
|
|||
do_posix_clock_monotonic_gettime(&uptime);
|
||||
sta->last_connected = uptime.tv_sec;
|
||||
ewma_init(&sta->avg_signal, 1024, 8);
|
||||
for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++)
|
||||
ewma_init(&sta->chain_signal_avg[i], 1024, 8);
|
||||
|
||||
if (sta_prepare_rate_control(local, sta, gfp)) {
|
||||
kfree(sta);
|
||||
|
|
|
@ -344,6 +344,11 @@ struct sta_info {
|
|||
int last_signal;
|
||||
struct ewma avg_signal;
|
||||
int last_ack_signal;
|
||||
|
||||
u8 chains;
|
||||
s8 chain_signal_last[IEEE80211_MAX_CHAINS];
|
||||
struct ewma chain_signal_avg[IEEE80211_MAX_CHAINS];
|
||||
|
||||
/* Plus 1 for non-QoS frames */
|
||||
__le16 last_seq_ctrl[IEEE80211_NUM_TIDS + 1];
|
||||
|
||||
|
|
|
@ -208,10 +208,10 @@ void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf,
|
|||
u32 iv32 = get_unaligned_le32(&data[4]);
|
||||
u16 iv16 = data[2] | (data[0] << 8);
|
||||
|
||||
spin_lock_bh(&key->u.tkip.txlock);
|
||||
spin_lock(&key->u.tkip.txlock);
|
||||
ieee80211_compute_tkip_p1k(key, iv32);
|
||||
tkip_mixing_phase2(tk, ctx, iv16, p2k);
|
||||
spin_unlock_bh(&key->u.tkip.txlock);
|
||||
spin_unlock(&key->u.tkip.txlock);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_get_tkip_p2k);
|
||||
|
||||
|
|
|
@ -1072,32 +1072,6 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
|
|||
ieee80211_set_wmm_default(sdata, true);
|
||||
}
|
||||
|
||||
u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
|
||||
enum ieee80211_band band)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_rate *bitrates;
|
||||
u32 mandatory_rates;
|
||||
enum ieee80211_rate_flags mandatory_flag;
|
||||
int i;
|
||||
|
||||
sband = local->hw.wiphy->bands[band];
|
||||
if (WARN_ON(!sband))
|
||||
return 1;
|
||||
|
||||
if (band == IEEE80211_BAND_2GHZ)
|
||||
mandatory_flag = IEEE80211_RATE_MANDATORY_B;
|
||||
else
|
||||
mandatory_flag = IEEE80211_RATE_MANDATORY_A;
|
||||
|
||||
bitrates = sband->bitrates;
|
||||
mandatory_rates = 0;
|
||||
for (i = 0; i < sband->n_bitrates; i++)
|
||||
if (bitrates[i].flags & mandatory_flag)
|
||||
mandatory_rates |= BIT(i);
|
||||
return mandatory_rates;
|
||||
}
|
||||
|
||||
void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
|
||||
u16 transaction, u16 auth_alg, u16 status,
|
||||
const u8 *extra, size_t extra_len, const u8 *da,
|
||||
|
@ -1607,9 +1581,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
|||
if (sdata->u.mgd.dtim_period)
|
||||
changed |= BSS_CHANGED_DTIM_PERIOD;
|
||||
|
||||
mutex_lock(&sdata->u.mgd.mtx);
|
||||
sdata_lock(sdata);
|
||||
ieee80211_bss_info_change_notify(sdata, changed);
|
||||
mutex_unlock(&sdata->u.mgd.mtx);
|
||||
sdata_unlock(sdata);
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
changed |= BSS_CHANGED_IBSS;
|
||||
|
@ -1740,6 +1714,13 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
|||
mb();
|
||||
local->resuming = false;
|
||||
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
continue;
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION)
|
||||
ieee80211_sta_restart(sdata);
|
||||
}
|
||||
|
||||
mod_timer(&local->sta_cleanup, jiffies + 1);
|
||||
#else
|
||||
WARN_ON(1);
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
int ieee80211_wep_init(struct ieee80211_local *local)
|
||||
{
|
||||
/* start WEP IV from a random value */
|
||||
get_random_bytes(&local->wep_iv, WEP_IV_LEN);
|
||||
get_random_bytes(&local->wep_iv, IEEE80211_WEP_IV_LEN);
|
||||
|
||||
local->wep_tx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(local->wep_tx_tfm)) {
|
||||
|
@ -98,20 +98,21 @@ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local,
|
|||
|
||||
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
|
||||
|
||||
if (WARN_ON(skb_tailroom(skb) < WEP_ICV_LEN ||
|
||||
skb_headroom(skb) < WEP_IV_LEN))
|
||||
if (WARN_ON(skb_tailroom(skb) < IEEE80211_WEP_ICV_LEN ||
|
||||
skb_headroom(skb) < IEEE80211_WEP_IV_LEN))
|
||||
return NULL;
|
||||
|
||||
hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||
newhdr = skb_push(skb, WEP_IV_LEN);
|
||||
memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen);
|
||||
newhdr = skb_push(skb, IEEE80211_WEP_IV_LEN);
|
||||
memmove(newhdr, newhdr + IEEE80211_WEP_IV_LEN, hdrlen);
|
||||
|
||||
/* the HW only needs room for the IV, but not the actual IV */
|
||||
if (info->control.hw_key &&
|
||||
(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))
|
||||
return newhdr + hdrlen;
|
||||
|
||||
skb_set_network_header(skb, skb_network_offset(skb) + WEP_IV_LEN);
|
||||
skb_set_network_header(skb, skb_network_offset(skb) +
|
||||
IEEE80211_WEP_IV_LEN);
|
||||
ieee80211_wep_get_iv(local, keylen, keyidx, newhdr + hdrlen);
|
||||
return newhdr + hdrlen;
|
||||
}
|
||||
|
@ -125,8 +126,8 @@ static void ieee80211_wep_remove_iv(struct ieee80211_local *local,
|
|||
unsigned int hdrlen;
|
||||
|
||||
hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||
memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen);
|
||||
skb_pull(skb, WEP_IV_LEN);
|
||||
memmove(skb->data + IEEE80211_WEP_IV_LEN, skb->data, hdrlen);
|
||||
skb_pull(skb, IEEE80211_WEP_IV_LEN);
|
||||
}
|
||||
|
||||
|
||||
|
@ -146,7 +147,7 @@ int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
|
|||
put_unaligned(icv, (__le32 *)(data + data_len));
|
||||
|
||||
crypto_cipher_setkey(tfm, rc4key, klen);
|
||||
for (i = 0; i < data_len + WEP_ICV_LEN; i++)
|
||||
for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++)
|
||||
crypto_cipher_encrypt_one(tfm, data + i, data + i);
|
||||
|
||||
return 0;
|
||||
|
@ -172,7 +173,7 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local,
|
|||
if (!iv)
|
||||
return -1;
|
||||
|
||||
len = skb->len - (iv + WEP_IV_LEN - skb->data);
|
||||
len = skb->len - (iv + IEEE80211_WEP_IV_LEN - skb->data);
|
||||
|
||||
/* Prepend 24-bit IV to RC4 key */
|
||||
memcpy(rc4key, iv, 3);
|
||||
|
@ -181,10 +182,10 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local,
|
|||
memcpy(rc4key + 3, key, keylen);
|
||||
|
||||
/* Add room for ICV */
|
||||
skb_put(skb, WEP_ICV_LEN);
|
||||
skb_put(skb, IEEE80211_WEP_ICV_LEN);
|
||||
|
||||
return ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, keylen + 3,
|
||||
iv + WEP_IV_LEN, len);
|
||||
iv + IEEE80211_WEP_IV_LEN, len);
|
||||
}
|
||||
|
||||
|
||||
|
@ -201,11 +202,11 @@ int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
|
|||
return -1;
|
||||
|
||||
crypto_cipher_setkey(tfm, rc4key, klen);
|
||||
for (i = 0; i < data_len + WEP_ICV_LEN; i++)
|
||||
for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++)
|
||||
crypto_cipher_decrypt_one(tfm, data + i, data + i);
|
||||
|
||||
crc = cpu_to_le32(~crc32_le(~0, data, data_len));
|
||||
if (memcmp(&crc, data + data_len, WEP_ICV_LEN) != 0)
|
||||
if (memcmp(&crc, data + data_len, IEEE80211_WEP_ICV_LEN) != 0)
|
||||
/* ICV mismatch */
|
||||
return -1;
|
||||
|
||||
|
@ -237,10 +238,10 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local,
|
|||
return -1;
|
||||
|
||||
hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||
if (skb->len < hdrlen + WEP_IV_LEN + WEP_ICV_LEN)
|
||||
if (skb->len < hdrlen + IEEE80211_WEP_IV_LEN + IEEE80211_WEP_ICV_LEN)
|
||||
return -1;
|
||||
|
||||
len = skb->len - hdrlen - WEP_IV_LEN - WEP_ICV_LEN;
|
||||
len = skb->len - hdrlen - IEEE80211_WEP_IV_LEN - IEEE80211_WEP_ICV_LEN;
|
||||
|
||||
keyidx = skb->data[hdrlen + 3] >> 6;
|
||||
|
||||
|
@ -256,16 +257,16 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local,
|
|||
memcpy(rc4key + 3, key->conf.key, key->conf.keylen);
|
||||
|
||||
if (ieee80211_wep_decrypt_data(local->wep_rx_tfm, rc4key, klen,
|
||||
skb->data + hdrlen + WEP_IV_LEN,
|
||||
len))
|
||||
skb->data + hdrlen +
|
||||
IEEE80211_WEP_IV_LEN, len))
|
||||
ret = -1;
|
||||
|
||||
/* Trim ICV */
|
||||
skb_trim(skb, skb->len - WEP_ICV_LEN);
|
||||
skb_trim(skb, skb->len - IEEE80211_WEP_ICV_LEN);
|
||||
|
||||
/* Remove IV */
|
||||
memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen);
|
||||
skb_pull(skb, WEP_IV_LEN);
|
||||
memmove(skb->data + IEEE80211_WEP_IV_LEN, skb->data, hdrlen);
|
||||
skb_pull(skb, IEEE80211_WEP_IV_LEN);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -305,13 +306,14 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx)
|
|||
if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key))
|
||||
return RX_DROP_UNUSABLE;
|
||||
} else if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
|
||||
if (!pskb_may_pull(rx->skb, ieee80211_hdrlen(fc) + WEP_IV_LEN))
|
||||
if (!pskb_may_pull(rx->skb, ieee80211_hdrlen(fc) +
|
||||
IEEE80211_WEP_IV_LEN))
|
||||
return RX_DROP_UNUSABLE;
|
||||
if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key))
|
||||
rx->sta->wep_weak_iv_count++;
|
||||
ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key);
|
||||
/* remove ICV */
|
||||
if (pskb_trim(rx->skb, rx->skb->len - WEP_ICV_LEN))
|
||||
if (pskb_trim(rx->skb, rx->skb->len - IEEE80211_WEP_ICV_LEN))
|
||||
return RX_DROP_UNUSABLE;
|
||||
}
|
||||
|
||||
|
|
|
@ -62,10 +62,10 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
|
|||
|
||||
tail = MICHAEL_MIC_LEN;
|
||||
if (!info->control.hw_key)
|
||||
tail += TKIP_ICV_LEN;
|
||||
tail += IEEE80211_TKIP_ICV_LEN;
|
||||
|
||||
if (WARN_ON(skb_tailroom(skb) < tail ||
|
||||
skb_headroom(skb) < TKIP_IV_LEN))
|
||||
skb_headroom(skb) < IEEE80211_TKIP_IV_LEN))
|
||||
return TX_DROP;
|
||||
|
||||
key = &tx->key->conf.key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY];
|
||||
|
@ -198,15 +198,16 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
|
|||
if (info->control.hw_key)
|
||||
tail = 0;
|
||||
else
|
||||
tail = TKIP_ICV_LEN;
|
||||
tail = IEEE80211_TKIP_ICV_LEN;
|
||||
|
||||
if (WARN_ON(skb_tailroom(skb) < tail ||
|
||||
skb_headroom(skb) < TKIP_IV_LEN))
|
||||
skb_headroom(skb) < IEEE80211_TKIP_IV_LEN))
|
||||
return -1;
|
||||
|
||||
pos = skb_push(skb, TKIP_IV_LEN);
|
||||
memmove(pos, pos + TKIP_IV_LEN, hdrlen);
|
||||
skb_set_network_header(skb, skb_network_offset(skb) + TKIP_IV_LEN);
|
||||
pos = skb_push(skb, IEEE80211_TKIP_IV_LEN);
|
||||
memmove(pos, pos + IEEE80211_TKIP_IV_LEN, hdrlen);
|
||||
skb_set_network_header(skb, skb_network_offset(skb) +
|
||||
IEEE80211_TKIP_IV_LEN);
|
||||
pos += hdrlen;
|
||||
|
||||
/* the HW only needs room for the IV, but not the actual IV */
|
||||
|
@ -227,7 +228,7 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
|
|||
return 0;
|
||||
|
||||
/* Add room for ICV */
|
||||
skb_put(skb, TKIP_ICV_LEN);
|
||||
skb_put(skb, IEEE80211_TKIP_ICV_LEN);
|
||||
|
||||
return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm,
|
||||
key, skb, pos, len);
|
||||
|
@ -290,11 +291,11 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
|
|||
return RX_DROP_UNUSABLE;
|
||||
|
||||
/* Trim ICV */
|
||||
skb_trim(skb, skb->len - TKIP_ICV_LEN);
|
||||
skb_trim(skb, skb->len - IEEE80211_TKIP_ICV_LEN);
|
||||
|
||||
/* Remove IV */
|
||||
memmove(skb->data + TKIP_IV_LEN, skb->data, hdrlen);
|
||||
skb_pull(skb, TKIP_IV_LEN);
|
||||
memmove(skb->data + IEEE80211_TKIP_IV_LEN, skb->data, hdrlen);
|
||||
skb_pull(skb, IEEE80211_TKIP_IV_LEN);
|
||||
|
||||
return RX_CONTINUE;
|
||||
}
|
||||
|
@ -337,9 +338,9 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
|
|||
else
|
||||
qos_tid = 0;
|
||||
|
||||
data_len = skb->len - hdrlen - CCMP_HDR_LEN;
|
||||
data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN;
|
||||
if (encrypted)
|
||||
data_len -= CCMP_MIC_LEN;
|
||||
data_len -= IEEE80211_CCMP_MIC_LEN;
|
||||
|
||||
/* First block, b_0 */
|
||||
b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
|
||||
|
@ -348,7 +349,7 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
|
|||
*/
|
||||
b_0[1] = qos_tid | (mgmt << 4);
|
||||
memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
|
||||
memcpy(&b_0[8], pn, CCMP_PN_LEN);
|
||||
memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN);
|
||||
/* l(m) */
|
||||
put_unaligned_be16(data_len, &b_0[14]);
|
||||
|
||||
|
@ -424,15 +425,16 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
|
|||
if (info->control.hw_key)
|
||||
tail = 0;
|
||||
else
|
||||
tail = CCMP_MIC_LEN;
|
||||
tail = IEEE80211_CCMP_MIC_LEN;
|
||||
|
||||
if (WARN_ON(skb_tailroom(skb) < tail ||
|
||||
skb_headroom(skb) < CCMP_HDR_LEN))
|
||||
skb_headroom(skb) < IEEE80211_CCMP_HDR_LEN))
|
||||
return -1;
|
||||
|
||||
pos = skb_push(skb, CCMP_HDR_LEN);
|
||||
memmove(pos, pos + CCMP_HDR_LEN, hdrlen);
|
||||
skb_set_network_header(skb, skb_network_offset(skb) + CCMP_HDR_LEN);
|
||||
pos = skb_push(skb, IEEE80211_CCMP_HDR_LEN);
|
||||
memmove(pos, pos + IEEE80211_CCMP_HDR_LEN, hdrlen);
|
||||
skb_set_network_header(skb, skb_network_offset(skb) +
|
||||
IEEE80211_CCMP_HDR_LEN);
|
||||
|
||||
/* the HW only needs room for the IV, but not the actual IV */
|
||||
if (info->control.hw_key &&
|
||||
|
@ -457,10 +459,10 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
|
|||
if (info->control.hw_key)
|
||||
return 0;
|
||||
|
||||
pos += CCMP_HDR_LEN;
|
||||
pos += IEEE80211_CCMP_HDR_LEN;
|
||||
ccmp_special_blocks(skb, pn, scratch, 0);
|
||||
ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len,
|
||||
pos, skb_put(skb, CCMP_MIC_LEN));
|
||||
pos, skb_put(skb, IEEE80211_CCMP_MIC_LEN));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -490,7 +492,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
|
|||
struct ieee80211_key *key = rx->key;
|
||||
struct sk_buff *skb = rx->skb;
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
u8 pn[CCMP_PN_LEN];
|
||||
u8 pn[IEEE80211_CCMP_PN_LEN];
|
||||
int data_len;
|
||||
int queue;
|
||||
|
||||
|
@ -500,12 +502,13 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
|
|||
!ieee80211_is_robust_mgmt_frame(hdr))
|
||||
return RX_CONTINUE;
|
||||
|
||||
data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN;
|
||||
data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN -
|
||||
IEEE80211_CCMP_MIC_LEN;
|
||||
if (!rx->sta || data_len < 0)
|
||||
return RX_DROP_UNUSABLE;
|
||||
|
||||
if (status->flag & RX_FLAG_DECRYPTED) {
|
||||
if (!pskb_may_pull(rx->skb, hdrlen + CCMP_HDR_LEN))
|
||||
if (!pskb_may_pull(rx->skb, hdrlen + IEEE80211_CCMP_HDR_LEN))
|
||||
return RX_DROP_UNUSABLE;
|
||||
} else {
|
||||
if (skb_linearize(rx->skb))
|
||||
|
@ -516,7 +519,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
|
|||
|
||||
queue = rx->security_idx;
|
||||
|
||||
if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) {
|
||||
if (memcmp(pn, key->u.ccmp.rx_pn[queue], IEEE80211_CCMP_PN_LEN) <= 0) {
|
||||
key->u.ccmp.replays++;
|
||||
return RX_DROP_UNUSABLE;
|
||||
}
|
||||
|
@ -528,19 +531,20 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
|
|||
|
||||
if (ieee80211_aes_ccm_decrypt(
|
||||
key->u.ccmp.tfm, scratch,
|
||||
skb->data + hdrlen + CCMP_HDR_LEN, data_len,
|
||||
skb->data + skb->len - CCMP_MIC_LEN,
|
||||
skb->data + hdrlen + CCMP_HDR_LEN))
|
||||
skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
|
||||
data_len,
|
||||
skb->data + skb->len - IEEE80211_CCMP_MIC_LEN,
|
||||
skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN))
|
||||
return RX_DROP_UNUSABLE;
|
||||
}
|
||||
|
||||
memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN);
|
||||
memcpy(key->u.ccmp.rx_pn[queue], pn, IEEE80211_CCMP_PN_LEN);
|
||||
|
||||
/* Remove CCMP header and MIC */
|
||||
if (pskb_trim(skb, skb->len - CCMP_MIC_LEN))
|
||||
if (pskb_trim(skb, skb->len - IEEE80211_CCMP_MIC_LEN))
|
||||
return RX_DROP_UNUSABLE;
|
||||
memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen);
|
||||
skb_pull(skb, CCMP_HDR_LEN);
|
||||
memmove(skb->data + IEEE80211_CCMP_HDR_LEN, skb->data, hdrlen);
|
||||
skb_pull(skb, IEEE80211_CCMP_HDR_LEN);
|
||||
|
||||
return RX_CONTINUE;
|
||||
}
|
||||
|
|
|
@ -34,13 +34,12 @@
|
|||
MODULE_AUTHOR("Johannes Berg");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("wireless configuration support");
|
||||
MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME);
|
||||
|
||||
/* RCU-protected (and cfg80211_mutex for writers) */
|
||||
/* RCU-protected (and RTNL for writers) */
|
||||
LIST_HEAD(cfg80211_rdev_list);
|
||||
int cfg80211_rdev_list_generation;
|
||||
|
||||
DEFINE_MUTEX(cfg80211_mutex);
|
||||
|
||||
/* for debugfs */
|
||||
static struct dentry *ieee80211_debugfs_dir;
|
||||
|
||||
|
@ -52,12 +51,11 @@ module_param(cfg80211_disable_40mhz_24ghz, bool, 0644);
|
|||
MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz,
|
||||
"Disable 40MHz support in the 2.4GHz band");
|
||||
|
||||
/* requires cfg80211_mutex to be held! */
|
||||
struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx)
|
||||
{
|
||||
struct cfg80211_registered_device *result = NULL, *rdev;
|
||||
|
||||
assert_cfg80211_lock();
|
||||
ASSERT_RTNL();
|
||||
|
||||
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
|
||||
if (rdev->wiphy_idx == wiphy_idx) {
|
||||
|
@ -76,12 +74,11 @@ int get_wiphy_idx(struct wiphy *wiphy)
|
|||
return rdev->wiphy_idx;
|
||||
}
|
||||
|
||||
/* requires cfg80211_rdev_mutex to be held! */
|
||||
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
|
||||
assert_cfg80211_lock();
|
||||
ASSERT_RTNL();
|
||||
|
||||
rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx);
|
||||
if (!rdev)
|
||||
|
@ -89,35 +86,13 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
|
|||
return &rdev->wiphy;
|
||||
}
|
||||
|
||||
struct cfg80211_registered_device *
|
||||
cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV);
|
||||
struct net_device *dev;
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
dev = dev_get_by_index(net, ifindex);
|
||||
if (!dev)
|
||||
goto out;
|
||||
if (dev->ieee80211_ptr) {
|
||||
rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
|
||||
mutex_lock(&rdev->mtx);
|
||||
} else
|
||||
rdev = ERR_PTR(-ENODEV);
|
||||
dev_put(dev);
|
||||
out:
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
return rdev;
|
||||
}
|
||||
|
||||
/* requires cfg80211_mutex to be held */
|
||||
int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
|
||||
char *newname)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev2;
|
||||
int wiphy_idx, taken = -1, result, digits;
|
||||
|
||||
assert_cfg80211_lock();
|
||||
ASSERT_RTNL();
|
||||
|
||||
/* prohibit calling the thing phy%d when %d is not its number */
|
||||
sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);
|
||||
|
@ -215,8 +190,7 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
|
|||
void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev)
|
||||
{
|
||||
lockdep_assert_held(&rdev->devlist_mtx);
|
||||
lockdep_assert_held(&rdev->sched_scan_mtx);
|
||||
ASSERT_RTNL();
|
||||
|
||||
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))
|
||||
return;
|
||||
|
@ -230,18 +204,15 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
|
|||
rdev->opencount--;
|
||||
|
||||
if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
|
||||
bool busy = work_busy(&rdev->scan_done_wk);
|
||||
|
||||
/*
|
||||
* If the work isn't pending or running (in which case it would
|
||||
* be waiting for the lock we hold) the driver didn't properly
|
||||
* cancel the scan when the interface was removed. In this case
|
||||
* warn and leak the scan request object to not crash later.
|
||||
* If the scan request wasn't notified as done, set it
|
||||
* to aborted and leak it after a warning. The driver
|
||||
* should have notified us that it ended at the latest
|
||||
* during rdev_stop_p2p_device().
|
||||
*/
|
||||
WARN_ON(!busy);
|
||||
|
||||
rdev->scan_req->aborted = true;
|
||||
___cfg80211_scan_done(rdev, !busy);
|
||||
if (WARN_ON(!rdev->scan_req->notified))
|
||||
rdev->scan_req->aborted = true;
|
||||
___cfg80211_scan_done(rdev, !rdev->scan_req->notified);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,8 +226,6 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
|
|||
|
||||
rtnl_lock();
|
||||
|
||||
/* read-only iteration need not hold the devlist_mtx */
|
||||
|
||||
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
||||
if (wdev->netdev) {
|
||||
dev_close(wdev->netdev);
|
||||
|
@ -265,12 +234,7 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
|
|||
/* otherwise, check iftype */
|
||||
switch (wdev->iftype) {
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
/* but this requires it */
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
cfg80211_stop_p2p_device(rdev, wdev);
|
||||
mutex_unlock(&rdev->sched_scan_mtx);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -298,10 +262,7 @@ static void cfg80211_event_work(struct work_struct *work)
|
|||
event_work);
|
||||
|
||||
rtnl_lock();
|
||||
cfg80211_lock_rdev(rdev);
|
||||
|
||||
cfg80211_process_rdev_events(rdev);
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
|
@ -309,7 +270,7 @@ static void cfg80211_event_work(struct work_struct *work)
|
|||
|
||||
struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
|
||||
{
|
||||
static int wiphy_counter;
|
||||
static atomic_t wiphy_counter = ATOMIC_INIT(0);
|
||||
|
||||
struct cfg80211_registered_device *rdev;
|
||||
int alloc_size;
|
||||
|
@ -331,26 +292,18 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
|
|||
|
||||
rdev->ops = ops;
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
|
||||
rdev->wiphy_idx = wiphy_counter++;
|
||||
rdev->wiphy_idx = atomic_inc_return(&wiphy_counter);
|
||||
|
||||
if (unlikely(rdev->wiphy_idx < 0)) {
|
||||
wiphy_counter--;
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
/* ugh, wrapped! */
|
||||
atomic_dec(&wiphy_counter);
|
||||
kfree(rdev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
|
||||
/* give it a proper name */
|
||||
dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
|
||||
|
||||
mutex_init(&rdev->mtx);
|
||||
mutex_init(&rdev->devlist_mtx);
|
||||
mutex_init(&rdev->sched_scan_mtx);
|
||||
INIT_LIST_HEAD(&rdev->wdev_list);
|
||||
INIT_LIST_HEAD(&rdev->beacon_registrations);
|
||||
spin_lock_init(&rdev->beacon_registrations_lock);
|
||||
|
@ -598,11 +551,11 @@ int wiphy_register(struct wiphy *wiphy)
|
|||
/* check and set up bitrates */
|
||||
ieee80211_set_bitrate_flags(wiphy);
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
rtnl_lock();
|
||||
|
||||
res = device_add(&rdev->wiphy.dev);
|
||||
if (res) {
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
rtnl_unlock();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -631,24 +584,21 @@ int wiphy_register(struct wiphy *wiphy)
|
|||
}
|
||||
|
||||
cfg80211_debugfs_rdev_add(rdev);
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
|
||||
/*
|
||||
* due to a locking dependency this has to be outside of the
|
||||
* cfg80211_mutex lock
|
||||
*/
|
||||
res = rfkill_register(rdev->rfkill);
|
||||
if (res)
|
||||
goto out_rm_dev;
|
||||
if (res) {
|
||||
device_del(&rdev->wiphy.dev);
|
||||
|
||||
debugfs_remove_recursive(rdev->wiphy.debugfsdir);
|
||||
list_del_rcu(&rdev->list);
|
||||
wiphy_regulatory_deregister(wiphy);
|
||||
rtnl_unlock();
|
||||
return res;
|
||||
}
|
||||
|
||||
rtnl_lock();
|
||||
rdev->wiphy.registered = true;
|
||||
rtnl_unlock();
|
||||
return 0;
|
||||
|
||||
out_rm_dev:
|
||||
device_del(&rdev->wiphy.dev);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(wiphy_register);
|
||||
|
||||
|
@ -675,25 +625,19 @@ void wiphy_unregister(struct wiphy *wiphy)
|
|||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||
|
||||
wait_event(rdev->dev_wait, ({
|
||||
int __count;
|
||||
rtnl_lock();
|
||||
__count = rdev->opencount;
|
||||
rtnl_unlock();
|
||||
__count == 0; }));
|
||||
|
||||
rtnl_lock();
|
||||
rdev->wiphy.registered = false;
|
||||
rtnl_unlock();
|
||||
|
||||
rfkill_unregister(rdev->rfkill);
|
||||
|
||||
/* protect the device list */
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
|
||||
wait_event(rdev->dev_wait, ({
|
||||
int __count;
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
__count = rdev->opencount;
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
__count == 0; }));
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
BUG_ON(!list_empty(&rdev->wdev_list));
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
/*
|
||||
* First remove the hardware from everywhere, this makes
|
||||
|
@ -703,20 +647,6 @@ void wiphy_unregister(struct wiphy *wiphy)
|
|||
list_del_rcu(&rdev->list);
|
||||
synchronize_rcu();
|
||||
|
||||
/*
|
||||
* Try to grab rdev->mtx. If a command is still in progress,
|
||||
* hopefully the driver will refuse it since it's tearing
|
||||
* down the device already. We wait for this command to complete
|
||||
* before unlinking the item from the list.
|
||||
* Note: as codified by the BUG_ON above we cannot get here if
|
||||
* a virtual interface is still present. Hence, we can only get
|
||||
* to lock contention here if userspace issues a command that
|
||||
* identified the hardware by wiphy index.
|
||||
*/
|
||||
cfg80211_lock_rdev(rdev);
|
||||
/* nothing */
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
|
||||
/*
|
||||
* If this device got a regulatory hint tell core its
|
||||
* free to listen now to a new shiny device regulatory hint
|
||||
|
@ -726,15 +656,17 @@ void wiphy_unregister(struct wiphy *wiphy)
|
|||
cfg80211_rdev_list_generation++;
|
||||
device_del(&rdev->wiphy.dev);
|
||||
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
rtnl_unlock();
|
||||
|
||||
flush_work(&rdev->scan_done_wk);
|
||||
cancel_work_sync(&rdev->conn_work);
|
||||
flush_work(&rdev->event_work);
|
||||
cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);
|
||||
|
||||
if (rdev->wowlan && rdev->ops->set_wakeup)
|
||||
#ifdef CONFIG_PM
|
||||
if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup)
|
||||
rdev_set_wakeup(rdev, false);
|
||||
#endif
|
||||
cfg80211_rdev_free_wowlan(rdev);
|
||||
}
|
||||
EXPORT_SYMBOL(wiphy_unregister);
|
||||
|
@ -744,9 +676,6 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
|
|||
struct cfg80211_internal_bss *scan, *tmp;
|
||||
struct cfg80211_beacon_registration *reg, *treg;
|
||||
rfkill_destroy(rdev->rfkill);
|
||||
mutex_destroy(&rdev->mtx);
|
||||
mutex_destroy(&rdev->devlist_mtx);
|
||||
mutex_destroy(&rdev->sched_scan_mtx);
|
||||
list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) {
|
||||
list_del(®->list);
|
||||
kfree(reg);
|
||||
|
@ -771,36 +700,6 @@ void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
|
|||
}
|
||||
EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
|
||||
|
||||
static void wdev_cleanup_work(struct work_struct *work)
|
||||
{
|
||||
struct wireless_dev *wdev;
|
||||
struct cfg80211_registered_device *rdev;
|
||||
|
||||
wdev = container_of(work, struct wireless_dev, cleanup_work);
|
||||
rdev = wiphy_to_dev(wdev->wiphy);
|
||||
|
||||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
|
||||
if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
|
||||
rdev->scan_req->aborted = true;
|
||||
___cfg80211_scan_done(rdev, true);
|
||||
}
|
||||
|
||||
if (WARN_ON(rdev->sched_scan_req &&
|
||||
rdev->sched_scan_req->dev == wdev->netdev)) {
|
||||
__cfg80211_stop_sched_scan(rdev, false);
|
||||
}
|
||||
|
||||
mutex_unlock(&rdev->sched_scan_mtx);
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
rdev->opencount--;
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
wake_up(&rdev->dev_wait);
|
||||
|
||||
dev_put(wdev->netdev);
|
||||
}
|
||||
|
||||
void cfg80211_unregister_wdev(struct wireless_dev *wdev)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
|
||||
|
@ -810,8 +709,6 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
|
|||
if (WARN_ON(wdev->netdev))
|
||||
return;
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
list_del_rcu(&wdev->list);
|
||||
rdev->devlist_generation++;
|
||||
|
||||
|
@ -823,8 +720,6 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
|
|||
WARN_ON_ONCE(1);
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&rdev->sched_scan_mtx);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_unregister_wdev);
|
||||
|
||||
|
@ -843,7 +738,7 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
|
|||
}
|
||||
|
||||
void cfg80211_leave(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev)
|
||||
struct wireless_dev *wdev)
|
||||
{
|
||||
struct net_device *dev = wdev->netdev;
|
||||
|
||||
|
@ -853,9 +748,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
|
|||
break;
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
case NL80211_IFTYPE_STATION:
|
||||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
__cfg80211_stop_sched_scan(rdev, false);
|
||||
mutex_unlock(&rdev->sched_scan_mtx);
|
||||
|
||||
wdev_lock(wdev);
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
|
@ -864,9 +757,8 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
|
|||
wdev->wext.ie_len = 0;
|
||||
wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
|
||||
#endif
|
||||
__cfg80211_disconnect(rdev, dev,
|
||||
WLAN_REASON_DEAUTH_LEAVING, true);
|
||||
cfg80211_mlme_down(rdev, dev);
|
||||
cfg80211_disconnect(rdev, dev,
|
||||
WLAN_REASON_DEAUTH_LEAVING, true);
|
||||
wdev_unlock(wdev);
|
||||
break;
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
|
@ -909,13 +801,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
|||
* are added with nl80211.
|
||||
*/
|
||||
mutex_init(&wdev->mtx);
|
||||
INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work);
|
||||
INIT_LIST_HEAD(&wdev->event_list);
|
||||
spin_lock_init(&wdev->event_lock);
|
||||
INIT_LIST_HEAD(&wdev->mgmt_registrations);
|
||||
spin_lock_init(&wdev->mgmt_registrations_lock);
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
wdev->identifier = ++rdev->wdev_id;
|
||||
list_add_rcu(&wdev->list, &rdev->wdev_list);
|
||||
rdev->devlist_generation++;
|
||||
|
@ -928,7 +818,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
|||
}
|
||||
wdev->netdev = dev;
|
||||
wdev->sme_state = CFG80211_SME_IDLE;
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
wdev->wext.default_key = -1;
|
||||
wdev->wext.default_mgmt_key = -1;
|
||||
|
@ -954,26 +843,22 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
|||
break;
|
||||
case NETDEV_DOWN:
|
||||
cfg80211_update_iface_num(rdev, wdev->iftype, -1);
|
||||
dev_hold(dev);
|
||||
queue_work(cfg80211_wq, &wdev->cleanup_work);
|
||||
if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
|
||||
if (WARN_ON(!rdev->scan_req->notified))
|
||||
rdev->scan_req->aborted = true;
|
||||
___cfg80211_scan_done(rdev, true);
|
||||
}
|
||||
|
||||
if (WARN_ON(rdev->sched_scan_req &&
|
||||
rdev->sched_scan_req->dev == wdev->netdev)) {
|
||||
__cfg80211_stop_sched_scan(rdev, false);
|
||||
}
|
||||
|
||||
rdev->opencount--;
|
||||
wake_up(&rdev->dev_wait);
|
||||
break;
|
||||
case NETDEV_UP:
|
||||
/*
|
||||
* If we have a really quick DOWN/UP succession we may
|
||||
* have this work still pending ... cancel it and see
|
||||
* if it was pending, in which case we need to account
|
||||
* for some of the work it would have done.
|
||||
*/
|
||||
if (cancel_work_sync(&wdev->cleanup_work)) {
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
rdev->opencount--;
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
dev_put(dev);
|
||||
}
|
||||
cfg80211_update_iface_num(rdev, wdev->iftype, 1);
|
||||
cfg80211_lock_rdev(rdev);
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
wdev_lock(wdev);
|
||||
switch (wdev->iftype) {
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
|
@ -1005,10 +890,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
|||
break;
|
||||
}
|
||||
wdev_unlock(wdev);
|
||||
mutex_unlock(&rdev->sched_scan_mtx);
|
||||
rdev->opencount++;
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
|
||||
/*
|
||||
* Configure power management to the driver here so that its
|
||||
|
@ -1024,12 +906,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
|||
}
|
||||
break;
|
||||
case NETDEV_UNREGISTER:
|
||||
/*
|
||||
* NB: cannot take rdev->mtx here because this may be
|
||||
* called within code protected by it when interfaces
|
||||
* are removed with nl80211.
|
||||
*/
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
/*
|
||||
* It is possible to get NETDEV_UNREGISTER
|
||||
* multiple times. To detect that, check
|
||||
|
@ -1046,7 +922,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
|||
kfree(wdev->wext.keys);
|
||||
#endif
|
||||
}
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
/*
|
||||
* synchronise (so that we won't find this netdev
|
||||
* from other code any more) and then clear the list
|
||||
|
@ -1066,9 +941,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
|||
return notifier_from_errno(-EOPNOTSUPP);
|
||||
if (rfkill_blocked(rdev->rfkill))
|
||||
return notifier_from_errno(-ERFKILL);
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
ret = cfg80211_can_add_interface(rdev, wdev->iftype);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
if (ret)
|
||||
return notifier_from_errno(ret);
|
||||
break;
|
||||
|
@ -1086,12 +959,10 @@ static void __net_exit cfg80211_pernet_exit(struct net *net)
|
|||
struct cfg80211_registered_device *rdev;
|
||||
|
||||
rtnl_lock();
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
|
||||
if (net_eq(wiphy_net(&rdev->wiphy), net))
|
||||
WARN_ON(cfg80211_switch_netns(rdev, &init_net));
|
||||
}
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
#ifndef __NET_WIRELESS_CORE_H
|
||||
#define __NET_WIRELESS_CORE_H
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/rbtree.h>
|
||||
|
@ -23,11 +22,6 @@
|
|||
struct cfg80211_registered_device {
|
||||
const struct cfg80211_ops *ops;
|
||||
struct list_head list;
|
||||
/* we hold this mutex during any call so that
|
||||
* we cannot do multiple calls at once, and also
|
||||
* to avoid the deregister call to proceed while
|
||||
* any call is in progress */
|
||||
struct mutex mtx;
|
||||
|
||||
/* rfkill support */
|
||||
struct rfkill_ops rfkill_ops;
|
||||
|
@ -49,9 +43,7 @@ struct cfg80211_registered_device {
|
|||
/* wiphy index, internal only */
|
||||
int wiphy_idx;
|
||||
|
||||
/* associated wireless interfaces */
|
||||
struct mutex devlist_mtx;
|
||||
/* protected by devlist_mtx or RCU */
|
||||
/* associated wireless interfaces, protected by rtnl or RCU */
|
||||
struct list_head wdev_list;
|
||||
int devlist_generation, wdev_id;
|
||||
int opencount; /* also protected by devlist_mtx */
|
||||
|
@ -75,8 +67,6 @@ struct cfg80211_registered_device {
|
|||
struct work_struct scan_done_wk;
|
||||
struct work_struct sched_scan_results_wk;
|
||||
|
||||
struct mutex sched_scan_mtx;
|
||||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
struct genl_info *testmode_info;
|
||||
#endif
|
||||
|
@ -84,8 +74,6 @@ struct cfg80211_registered_device {
|
|||
struct work_struct conn_work;
|
||||
struct work_struct event_work;
|
||||
|
||||
struct cfg80211_wowlan *wowlan;
|
||||
|
||||
struct delayed_work dfs_update_channels_wk;
|
||||
|
||||
/* netlink port which started critical protocol (0 means not started) */
|
||||
|
@ -106,29 +94,26 @@ struct cfg80211_registered_device *wiphy_to_dev(struct wiphy *wiphy)
|
|||
static inline void
|
||||
cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev)
|
||||
{
|
||||
#ifdef CONFIG_PM
|
||||
int i;
|
||||
|
||||
if (!rdev->wowlan)
|
||||
if (!rdev->wiphy.wowlan_config)
|
||||
return;
|
||||
for (i = 0; i < rdev->wowlan->n_patterns; i++)
|
||||
kfree(rdev->wowlan->patterns[i].mask);
|
||||
kfree(rdev->wowlan->patterns);
|
||||
if (rdev->wowlan->tcp && rdev->wowlan->tcp->sock)
|
||||
sock_release(rdev->wowlan->tcp->sock);
|
||||
kfree(rdev->wowlan->tcp);
|
||||
kfree(rdev->wowlan);
|
||||
for (i = 0; i < rdev->wiphy.wowlan_config->n_patterns; i++)
|
||||
kfree(rdev->wiphy.wowlan_config->patterns[i].mask);
|
||||
kfree(rdev->wiphy.wowlan_config->patterns);
|
||||
if (rdev->wiphy.wowlan_config->tcp &&
|
||||
rdev->wiphy.wowlan_config->tcp->sock)
|
||||
sock_release(rdev->wiphy.wowlan_config->tcp->sock);
|
||||
kfree(rdev->wiphy.wowlan_config->tcp);
|
||||
kfree(rdev->wiphy.wowlan_config);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern struct workqueue_struct *cfg80211_wq;
|
||||
extern struct mutex cfg80211_mutex;
|
||||
extern struct list_head cfg80211_rdev_list;
|
||||
extern int cfg80211_rdev_list_generation;
|
||||
|
||||
static inline void assert_cfg80211_lock(void)
|
||||
{
|
||||
lockdep_assert_held(&cfg80211_mutex);
|
||||
}
|
||||
|
||||
struct cfg80211_internal_bss {
|
||||
struct list_head list;
|
||||
struct list_head hidden_list;
|
||||
|
@ -161,27 +146,11 @@ static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss)
|
|||
struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx);
|
||||
int get_wiphy_idx(struct wiphy *wiphy);
|
||||
|
||||
/* requires cfg80211_rdev_mutex to be held! */
|
||||
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx);
|
||||
|
||||
/* identical to cfg80211_get_dev_from_info but only operate on ifindex */
|
||||
extern struct cfg80211_registered_device *
|
||||
cfg80211_get_dev_from_ifindex(struct net *net, int ifindex);
|
||||
|
||||
int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
|
||||
struct net *net);
|
||||
|
||||
static inline void cfg80211_lock_rdev(struct cfg80211_registered_device *rdev)
|
||||
{
|
||||
mutex_lock(&rdev->mtx);
|
||||
}
|
||||
|
||||
static inline void cfg80211_unlock_rdev(struct cfg80211_registered_device *rdev)
|
||||
{
|
||||
BUG_ON(IS_ERR(rdev) || !rdev);
|
||||
mutex_unlock(&rdev->mtx);
|
||||
}
|
||||
|
||||
static inline void wdev_lock(struct wireless_dev *wdev)
|
||||
__acquires(wdev)
|
||||
{
|
||||
|
@ -196,7 +165,7 @@ static inline void wdev_unlock(struct wireless_dev *wdev)
|
|||
mutex_unlock(&wdev->mtx);
|
||||
}
|
||||
|
||||
#define ASSERT_RDEV_LOCK(rdev) lockdep_assert_held(&(rdev)->mtx)
|
||||
#define ASSERT_RDEV_LOCK(rdev) ASSERT_RTNL()
|
||||
#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx)
|
||||
|
||||
static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev)
|
||||
|
@ -314,38 +283,21 @@ int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
|
|||
struct net_device *dev);
|
||||
|
||||
/* MLME */
|
||||
int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_auth_type auth_type,
|
||||
const u8 *bssid,
|
||||
const u8 *ssid, int ssid_len,
|
||||
const u8 *ie, int ie_len,
|
||||
const u8 *key, int key_len, int key_idx,
|
||||
const u8 *sae_data, int sae_data_len);
|
||||
int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, struct ieee80211_channel *chan,
|
||||
enum nl80211_auth_type auth_type, const u8 *bssid,
|
||||
struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_auth_type auth_type,
|
||||
const u8 *bssid,
|
||||
const u8 *ssid, int ssid_len,
|
||||
const u8 *ie, int ie_len,
|
||||
const u8 *key, int key_len, int key_idx,
|
||||
const u8 *sae_data, int sae_data_len);
|
||||
int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
const u8 *bssid,
|
||||
const u8 *ssid, int ssid_len,
|
||||
struct cfg80211_assoc_request *req);
|
||||
int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
const u8 *bssid,
|
||||
const u8 *ssid, int ssid_len,
|
||||
struct cfg80211_assoc_request *req);
|
||||
int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, const u8 *bssid,
|
||||
const u8 *ie, int ie_len, u16 reason,
|
||||
bool local_state_change);
|
||||
int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, const u8 *bssid,
|
||||
const u8 *ie, int ie_len, u16 reason,
|
||||
|
@ -377,18 +329,11 @@ void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa,
|
|||
const struct ieee80211_vht_cap *vht_capa_mask);
|
||||
|
||||
/* SME */
|
||||
int __cfg80211_connect(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct cfg80211_connect_params *connect,
|
||||
struct cfg80211_cached_keys *connkeys,
|
||||
const u8 *prev_bssid);
|
||||
int cfg80211_connect(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct cfg80211_connect_params *connect,
|
||||
struct cfg80211_cached_keys *connkeys);
|
||||
int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, u16 reason,
|
||||
bool wextev);
|
||||
struct cfg80211_cached_keys *connkeys,
|
||||
const u8 *prev_bssid);
|
||||
int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, u16 reason,
|
||||
bool wextev);
|
||||
|
|
|
@ -74,7 +74,7 @@ static ssize_t ht40allow_map_read(struct file *file,
|
|||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
rtnl_lock();
|
||||
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
||||
sband = wiphy->bands[band];
|
||||
|
@ -85,7 +85,7 @@ static ssize_t ht40allow_map_read(struct file *file,
|
|||
buf, buf_size, offset);
|
||||
}
|
||||
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
rtnl_unlock();
|
||||
|
||||
r = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
|
||||
|
||||
|
|
|
@ -152,11 +152,11 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
|
|||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
int err;
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
ASSERT_RTNL();
|
||||
|
||||
wdev_lock(wdev);
|
||||
err = __cfg80211_join_ibss(rdev, dev, params, connkeys);
|
||||
wdev_unlock(wdev);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -359,11 +359,9 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
|
|||
wdev->wext.ibss.channel_fixed = false;
|
||||
}
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
wdev_lock(wdev);
|
||||
err = cfg80211_ibss_wext_join(rdev, wdev);
|
||||
wdev_unlock(wdev);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -429,11 +427,9 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
|
|||
memcpy(wdev->wext.ibss.ssid, ssid, len);
|
||||
wdev->wext.ibss.ssid_len = len;
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
wdev_lock(wdev);
|
||||
err = cfg80211_ibss_wext_join(rdev, wdev);
|
||||
wdev_unlock(wdev);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -512,11 +508,9 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
|
|||
} else
|
||||
wdev->wext.ibss.bssid = NULL;
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
wdev_lock(wdev);
|
||||
err = cfg80211_ibss_wext_join(rdev, wdev);
|
||||
wdev_unlock(wdev);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -82,6 +82,7 @@ const struct mesh_setup default_mesh_setup = {
|
|||
.sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET,
|
||||
.path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP,
|
||||
.path_metric = IEEE80211_PATH_METRIC_AIRTIME,
|
||||
.auth_id = 0, /* open */
|
||||
.ie = NULL,
|
||||
.ie_len = 0,
|
||||
.is_secure = false,
|
||||
|
@ -185,11 +186,9 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
|
|||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
int err;
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
wdev_lock(wdev);
|
||||
err = __cfg80211_join_mesh(rdev, dev, setup, conf);
|
||||
wdev_unlock(wdev);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -25,12 +25,9 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
|
|||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||
|
||||
trace_cfg80211_send_rx_auth(dev);
|
||||
wdev_lock(wdev);
|
||||
|
||||
nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL);
|
||||
cfg80211_sme_rx_auth(dev, buf, len);
|
||||
|
||||
wdev_unlock(wdev);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_send_rx_auth);
|
||||
|
||||
|
@ -46,7 +43,6 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
|
|||
int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
|
||||
|
||||
trace_cfg80211_send_rx_assoc(dev, bss);
|
||||
wdev_lock(wdev);
|
||||
|
||||
status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
|
||||
|
||||
|
@ -59,7 +55,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
|
|||
if (status_code != WLAN_STATUS_SUCCESS && wdev->conn &&
|
||||
cfg80211_sme_failed_reassoc(wdev)) {
|
||||
cfg80211_put_bss(wiphy, bss);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL);
|
||||
|
@ -71,7 +67,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
|
|||
* sme will schedule work that does it later.
|
||||
*/
|
||||
cfg80211_put_bss(wiphy, bss);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) {
|
||||
|
@ -87,13 +83,11 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
|
|||
__cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
|
||||
status_code,
|
||||
status_code == WLAN_STATUS_SUCCESS, bss);
|
||||
out:
|
||||
wdev_unlock(wdev);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_send_rx_assoc);
|
||||
|
||||
void __cfg80211_send_deauth(struct net_device *dev,
|
||||
const u8 *buf, size_t len)
|
||||
void cfg80211_send_deauth(struct net_device *dev,
|
||||
const u8 *buf, size_t len)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct wiphy *wiphy = wdev->wiphy;
|
||||
|
@ -102,7 +96,7 @@ void __cfg80211_send_deauth(struct net_device *dev,
|
|||
const u8 *bssid = mgmt->bssid;
|
||||
bool was_current = false;
|
||||
|
||||
trace___cfg80211_send_deauth(dev);
|
||||
trace_cfg80211_send_deauth(dev);
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
||||
if (wdev->current_bss &&
|
||||
|
@ -129,20 +123,10 @@ void __cfg80211_send_deauth(struct net_device *dev,
|
|||
false, NULL);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(__cfg80211_send_deauth);
|
||||
|
||||
void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
|
||||
wdev_lock(wdev);
|
||||
__cfg80211_send_deauth(dev, buf, len);
|
||||
wdev_unlock(wdev);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_send_deauth);
|
||||
|
||||
void __cfg80211_send_disassoc(struct net_device *dev,
|
||||
const u8 *buf, size_t len)
|
||||
void cfg80211_send_disassoc(struct net_device *dev,
|
||||
const u8 *buf, size_t len)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct wiphy *wiphy = wdev->wiphy;
|
||||
|
@ -152,7 +136,7 @@ void __cfg80211_send_disassoc(struct net_device *dev,
|
|||
u16 reason_code;
|
||||
bool from_ap;
|
||||
|
||||
trace___cfg80211_send_disassoc(dev);
|
||||
trace_cfg80211_send_disassoc(dev);
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
||||
nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL);
|
||||
|
@ -175,16 +159,6 @@ void __cfg80211_send_disassoc(struct net_device *dev,
|
|||
from_ap = !ether_addr_equal(mgmt->sa, dev->dev_addr);
|
||||
__cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
|
||||
}
|
||||
EXPORT_SYMBOL(__cfg80211_send_disassoc);
|
||||
|
||||
void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
|
||||
wdev_lock(wdev);
|
||||
__cfg80211_send_disassoc(dev, buf, len);
|
||||
wdev_unlock(wdev);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_send_disassoc);
|
||||
|
||||
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
|
||||
|
@ -194,15 +168,12 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
|
|||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||
|
||||
trace_cfg80211_send_auth_timeout(dev, addr);
|
||||
wdev_lock(wdev);
|
||||
|
||||
nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
|
||||
if (wdev->sme_state == CFG80211_SME_CONNECTING)
|
||||
__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
|
||||
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
||||
false, NULL);
|
||||
|
||||
wdev_unlock(wdev);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_send_auth_timeout);
|
||||
|
||||
|
@ -213,15 +184,12 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
|
|||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
|
||||
|
||||
trace_cfg80211_send_assoc_timeout(dev, addr);
|
||||
wdev_lock(wdev);
|
||||
|
||||
nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL);
|
||||
if (wdev->sme_state == CFG80211_SME_CONNECTING)
|
||||
__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
|
||||
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
||||
false, NULL);
|
||||
|
||||
wdev_unlock(wdev);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
|
||||
|
||||
|
@ -253,18 +221,27 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
|
|||
EXPORT_SYMBOL(cfg80211_michael_mic_failure);
|
||||
|
||||
/* some MLME handling for userspace SME */
|
||||
int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_auth_type auth_type,
|
||||
const u8 *bssid,
|
||||
const u8 *ssid, int ssid_len,
|
||||
const u8 *ie, int ie_len,
|
||||
const u8 *key, int key_len, int key_idx,
|
||||
const u8 *sae_data, int sae_data_len)
|
||||
int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_auth_type auth_type,
|
||||
const u8 *bssid,
|
||||
const u8 *ssid, int ssid_len,
|
||||
const u8 *ie, int ie_len,
|
||||
const u8 *key, int key_len, int key_idx,
|
||||
const u8 *sae_data, int sae_data_len)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_auth_request req;
|
||||
struct cfg80211_auth_request req = {
|
||||
.ie = ie,
|
||||
.ie_len = ie_len,
|
||||
.sae_data = sae_data,
|
||||
.sae_data_len = sae_data_len,
|
||||
.auth_type = auth_type,
|
||||
.key = key,
|
||||
.key_len = key_len,
|
||||
.key_idx = key_idx,
|
||||
};
|
||||
int err;
|
||||
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
@ -277,18 +254,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
|
|||
ether_addr_equal(bssid, wdev->current_bss->pub.bssid))
|
||||
return -EALREADY;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
|
||||
req.ie = ie;
|
||||
req.ie_len = ie_len;
|
||||
req.sae_data = sae_data;
|
||||
req.sae_data_len = sae_data_len;
|
||||
req.auth_type = auth_type;
|
||||
req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
|
||||
WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
|
||||
req.key = key;
|
||||
req.key_len = key_len;
|
||||
req.key_idx = key_idx;
|
||||
if (!req.bss)
|
||||
return -ENOENT;
|
||||
|
||||
|
@ -304,28 +271,6 @@ out:
|
|||
return err;
|
||||
}
|
||||
|
||||
int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, struct ieee80211_channel *chan,
|
||||
enum nl80211_auth_type auth_type, const u8 *bssid,
|
||||
const u8 *ssid, int ssid_len,
|
||||
const u8 *ie, int ie_len,
|
||||
const u8 *key, int key_len, int key_idx,
|
||||
const u8 *sae_data, int sae_data_len)
|
||||
{
|
||||
int err;
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
wdev_lock(dev->ieee80211_ptr);
|
||||
err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
|
||||
ssid, ssid_len, ie, ie_len,
|
||||
key, key_len, key_idx,
|
||||
sae_data, sae_data_len);
|
||||
wdev_unlock(dev->ieee80211_ptr);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Do a logical ht_capa &= ht_capa_mask. */
|
||||
void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
|
||||
const struct ieee80211_ht_cap *ht_capa_mask)
|
||||
|
@ -360,12 +305,12 @@ void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa,
|
|||
p1[i] &= p2[i];
|
||||
}
|
||||
|
||||
int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
const u8 *bssid,
|
||||
const u8 *ssid, int ssid_len,
|
||||
struct cfg80211_assoc_request *req)
|
||||
int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
const u8 *bssid,
|
||||
const u8 *ssid, int ssid_len,
|
||||
struct cfg80211_assoc_request *req)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
int err;
|
||||
|
@ -415,30 +360,10 @@ out:
|
|||
return err;
|
||||
}
|
||||
|
||||
int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
const u8 *bssid,
|
||||
const u8 *ssid, int ssid_len,
|
||||
struct cfg80211_assoc_request *req)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
int err;
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
wdev_lock(wdev);
|
||||
err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid,
|
||||
ssid, ssid_len, req);
|
||||
wdev_unlock(wdev);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, const u8 *bssid,
|
||||
const u8 *ie, int ie_len, u16 reason,
|
||||
bool local_state_change)
|
||||
int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, const u8 *bssid,
|
||||
const u8 *ie, int ie_len, u16 reason,
|
||||
bool local_state_change)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_deauth_request req = {
|
||||
|
@ -458,29 +383,18 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
|
|||
return rdev_deauth(rdev, dev, &req);
|
||||
}
|
||||
|
||||
int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, const u8 *bssid,
|
||||
const u8 *ie, int ie_len, u16 reason,
|
||||
bool local_state_change)
|
||||
int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, const u8 *bssid,
|
||||
const u8 *ie, int ie_len, u16 reason,
|
||||
bool local_state_change)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
int err;
|
||||
|
||||
wdev_lock(wdev);
|
||||
err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason,
|
||||
local_state_change);
|
||||
wdev_unlock(wdev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, const u8 *bssid,
|
||||
const u8 *ie, int ie_len, u16 reason,
|
||||
bool local_state_change)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_disassoc_request req;
|
||||
struct cfg80211_disassoc_request req = {
|
||||
.reason_code = reason,
|
||||
.local_state_change = local_state_change,
|
||||
.ie = ie,
|
||||
.ie_len = ie_len,
|
||||
};
|
||||
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
||||
|
@ -490,11 +404,6 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
|
|||
if (WARN(!wdev->current_bss, "sme_state=%d\n", wdev->sme_state))
|
||||
return -ENOTCONN;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.reason_code = reason;
|
||||
req.local_state_change = local_state_change;
|
||||
req.ie = ie;
|
||||
req.ie_len = ie_len;
|
||||
if (ether_addr_equal(wdev->current_bss->pub.bssid, bssid))
|
||||
req.bss = &wdev->current_bss->pub;
|
||||
else
|
||||
|
@ -503,44 +412,25 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
|
|||
return rdev_disassoc(rdev, dev, &req);
|
||||
}
|
||||
|
||||
int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, const u8 *bssid,
|
||||
const u8 *ie, int ie_len, u16 reason,
|
||||
bool local_state_change)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
int err;
|
||||
|
||||
wdev_lock(wdev);
|
||||
err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason,
|
||||
local_state_change);
|
||||
wdev_unlock(wdev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_deauth_request req;
|
||||
u8 bssid[ETH_ALEN];
|
||||
struct cfg80211_deauth_request req = {
|
||||
.reason_code = WLAN_REASON_DEAUTH_LEAVING,
|
||||
.bssid = bssid,
|
||||
};
|
||||
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
||||
if (!rdev->ops->deauth)
|
||||
return;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.reason_code = WLAN_REASON_DEAUTH_LEAVING;
|
||||
req.ie = NULL;
|
||||
req.ie_len = 0;
|
||||
|
||||
if (!wdev->current_bss)
|
||||
return;
|
||||
|
||||
memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN);
|
||||
req.bssid = bssid;
|
||||
rdev_deauth(rdev, dev, &req);
|
||||
|
||||
if (wdev->current_bss) {
|
||||
|
@ -848,7 +738,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
|
|||
dfs_update_channels_wk);
|
||||
wiphy = &rdev->wiphy;
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
rtnl_lock();
|
||||
for (bandid = 0; bandid < IEEE80211_NUM_BANDS; bandid++) {
|
||||
sband = wiphy->bands[bandid];
|
||||
if (!sband)
|
||||
|
@ -881,7 +771,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
|
|||
check_again = true;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
rtnl_unlock();
|
||||
|
||||
/* reschedule if there are other channels waiting to be cleared again */
|
||||
if (check_again)
|
||||
|
|
|
@ -37,10 +37,10 @@ static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
|
|||
|
||||
/* the netlink family */
|
||||
static struct genl_family nl80211_fam = {
|
||||
.id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
|
||||
.name = "nl80211", /* have users key off the name instead */
|
||||
.hdrsize = 0, /* no private header */
|
||||
.version = 1, /* no particular meaning now */
|
||||
.id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
|
||||
.name = NL80211_GENL_NAME, /* have users key off the name instead */
|
||||
.hdrsize = 0, /* no private header */
|
||||
.version = 1, /* no particular meaning now */
|
||||
.maxattr = NL80211_ATTR_MAX,
|
||||
.netnsok = true,
|
||||
.pre_doit = nl80211_pre_doit,
|
||||
|
@ -59,7 +59,7 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
|
|||
int wiphy_idx = -1;
|
||||
int ifidx = -1;
|
||||
|
||||
assert_cfg80211_lock();
|
||||
ASSERT_RTNL();
|
||||
|
||||
if (!have_ifidx && !have_wdev_id)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
@ -80,7 +80,6 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
|
|||
if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
|
||||
continue;
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
||||
if (have_ifidx && wdev->netdev &&
|
||||
wdev->netdev->ifindex == ifidx) {
|
||||
|
@ -92,7 +91,6 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
|
|||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
if (result)
|
||||
break;
|
||||
|
@ -109,7 +107,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
|
|||
struct cfg80211_registered_device *rdev = NULL, *tmp;
|
||||
struct net_device *netdev;
|
||||
|
||||
assert_cfg80211_lock();
|
||||
ASSERT_RTNL();
|
||||
|
||||
if (!attrs[NL80211_ATTR_WIPHY] &&
|
||||
!attrs[NL80211_ATTR_IFINDEX] &&
|
||||
|
@ -128,14 +126,12 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
|
|||
tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);
|
||||
if (tmp) {
|
||||
/* make sure wdev exists */
|
||||
mutex_lock(&tmp->devlist_mtx);
|
||||
list_for_each_entry(wdev, &tmp->wdev_list, list) {
|
||||
if (wdev->identifier != (u32)wdev_id)
|
||||
continue;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&tmp->devlist_mtx);
|
||||
|
||||
if (!found)
|
||||
tmp = NULL;
|
||||
|
@ -182,19 +178,6 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
|
|||
/*
|
||||
* This function returns a pointer to the driver
|
||||
* that the genl_info item that is passed refers to.
|
||||
* If successful, it returns non-NULL and also locks
|
||||
* the driver's mutex!
|
||||
*
|
||||
* This means that you need to call cfg80211_unlock_rdev()
|
||||
* before being allowed to acquire &cfg80211_mutex!
|
||||
*
|
||||
* This is necessary because we need to lock the global
|
||||
* mutex to get an item off the list safely, and then
|
||||
* we lock the rdev mutex so it doesn't go away under us.
|
||||
*
|
||||
* We don't want to keep cfg80211_mutex locked
|
||||
* for all the time in order to allow requests on
|
||||
* other interfaces to go through at the same time.
|
||||
*
|
||||
* The result of this can be a PTR_ERR and hence must
|
||||
* be checked with IS_ERR() for errors.
|
||||
|
@ -202,20 +185,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
|
|||
static struct cfg80211_registered_device *
|
||||
cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
rdev = __cfg80211_rdev_from_attrs(netns, info->attrs);
|
||||
|
||||
/* if it is not an error we grab the lock on
|
||||
* it to assure it won't be going away while
|
||||
* we operate on it */
|
||||
if (!IS_ERR(rdev))
|
||||
mutex_lock(&rdev->mtx);
|
||||
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
|
||||
return rdev;
|
||||
return __cfg80211_rdev_from_attrs(netns, info->attrs);
|
||||
}
|
||||
|
||||
/* policy for the attributes */
|
||||
|
@ -378,6 +348,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
|
|||
[NL80211_ATTR_MDID] = { .type = NLA_U16 },
|
||||
[NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
|
||||
.len = IEEE80211_MAX_DATA_LEN },
|
||||
[NL80211_ATTR_PEER_AID] = { .type = NLA_U16 },
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
|
@ -455,7 +426,6 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
|
|||
int err;
|
||||
|
||||
rtnl_lock();
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
|
||||
if (!cb->args[0]) {
|
||||
err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
|
||||
|
@ -484,14 +454,12 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
|
|||
*rdev = wiphy_to_dev(wiphy);
|
||||
*wdev = NULL;
|
||||
|
||||
mutex_lock(&(*rdev)->devlist_mtx);
|
||||
list_for_each_entry(tmp, &(*rdev)->wdev_list, list) {
|
||||
if (tmp->identifier == cb->args[1]) {
|
||||
*wdev = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&(*rdev)->devlist_mtx);
|
||||
|
||||
if (!*wdev) {
|
||||
err = -ENODEV;
|
||||
|
@ -499,19 +467,14 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
|
|||
}
|
||||
}
|
||||
|
||||
cfg80211_lock_rdev(*rdev);
|
||||
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
return 0;
|
||||
out_unlock:
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
rtnl_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev)
|
||||
{
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
|
@ -1567,7 +1530,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
struct nlattr **tb = nl80211_fam.attrbuf;
|
||||
int res;
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
rtnl_lock();
|
||||
res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
|
||||
tb, nl80211_fam.maxattr, nl80211_policy);
|
||||
if (res == 0) {
|
||||
|
@ -1581,10 +1544,8 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
|
||||
|
||||
netdev = dev_get_by_index(sock_net(skb->sk), ifidx);
|
||||
if (!netdev) {
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
if (!netdev)
|
||||
return -ENODEV;
|
||||
}
|
||||
if (netdev->ieee80211_ptr) {
|
||||
dev = wiphy_to_dev(
|
||||
netdev->ieee80211_ptr->wiphy);
|
||||
|
@ -1628,7 +1589,6 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
!skb->len &&
|
||||
cb->min_dump_alloc < 4096) {
|
||||
cb->min_dump_alloc = 4096;
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
return 1;
|
||||
}
|
||||
idx--;
|
||||
|
@ -1637,7 +1597,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
} while (cb->args[1] > 0);
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
rtnl_unlock();
|
||||
|
||||
cb->args[0] = idx;
|
||||
|
||||
|
@ -1792,7 +1752,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
|
|||
if (result)
|
||||
return result;
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
switch (iftype) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
|
@ -1816,7 +1775,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
|
|||
default:
|
||||
result = -EINVAL;
|
||||
}
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -1865,6 +1823,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
|
|||
u32 frag_threshold = 0, rts_threshold = 0;
|
||||
u8 coverage_class = 0;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
/*
|
||||
* Try to find the wiphy and netdev. Normally this
|
||||
* function shouldn't need the netdev, but this is
|
||||
|
@ -1874,31 +1834,25 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
|
|||
* also passed a netdev to set_wiphy, so that it is
|
||||
* possible to let that go to the right netdev!
|
||||
*/
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
|
||||
if (info->attrs[NL80211_ATTR_IFINDEX]) {
|
||||
int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
|
||||
|
||||
netdev = dev_get_by_index(genl_info_net(info), ifindex);
|
||||
if (netdev && netdev->ieee80211_ptr) {
|
||||
if (netdev && netdev->ieee80211_ptr)
|
||||
rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy);
|
||||
mutex_lock(&rdev->mtx);
|
||||
} else
|
||||
else
|
||||
netdev = NULL;
|
||||
}
|
||||
|
||||
if (!netdev) {
|
||||
rdev = __cfg80211_rdev_from_attrs(genl_info_net(info),
|
||||
info->attrs);
|
||||
if (IS_ERR(rdev)) {
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
if (IS_ERR(rdev))
|
||||
return PTR_ERR(rdev);
|
||||
}
|
||||
wdev = NULL;
|
||||
netdev = NULL;
|
||||
result = 0;
|
||||
|
||||
mutex_lock(&rdev->mtx);
|
||||
} else
|
||||
wdev = netdev->ieee80211_ptr;
|
||||
|
||||
|
@ -1911,8 +1865,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
|
|||
result = cfg80211_dev_rename(
|
||||
rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
|
||||
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
|
||||
if (result)
|
||||
goto bad_res;
|
||||
|
||||
|
@ -2119,7 +2071,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
|
|||
}
|
||||
|
||||
bad_res:
|
||||
mutex_unlock(&rdev->mtx);
|
||||
if (netdev)
|
||||
dev_put(netdev);
|
||||
return result;
|
||||
|
@ -2217,7 +2168,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
|
|||
struct cfg80211_registered_device *rdev;
|
||||
struct wireless_dev *wdev;
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
rtnl_lock();
|
||||
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
|
||||
if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
|
||||
continue;
|
||||
|
@ -2227,7 +2178,6 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
|
|||
}
|
||||
if_idx = 0;
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
||||
if (if_idx < if_start) {
|
||||
if_idx++;
|
||||
|
@ -2236,17 +2186,15 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
|
|||
if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq, NLM_F_MULTI,
|
||||
rdev, wdev) < 0) {
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
goto out;
|
||||
}
|
||||
if_idx++;
|
||||
}
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
wp_idx++;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
rtnl_unlock();
|
||||
|
||||
cb->args[0] = wp_idx;
|
||||
cb->args[1] = if_idx;
|
||||
|
@ -2479,11 +2427,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
|
|||
INIT_LIST_HEAD(&wdev->mgmt_registrations);
|
||||
spin_lock_init(&wdev->mgmt_registrations_lock);
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
wdev->identifier = ++rdev->wdev_id;
|
||||
list_add_rcu(&wdev->list, &rdev->wdev_list);
|
||||
rdev->devlist_generation++;
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -2992,8 +2938,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
|
|||
struct wireless_dev *wdev;
|
||||
bool ret = false;
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
|
||||
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
||||
if (wdev->iftype != NL80211_IFTYPE_AP &&
|
||||
wdev->iftype != NL80211_IFTYPE_P2P_GO)
|
||||
|
@ -3007,8 +2951,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
|
|||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -3170,13 +3112,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
|||
params.radar_required = true;
|
||||
}
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
|
||||
params.chandef.chan,
|
||||
CHAN_MODE_SHARED,
|
||||
radar_detect_width);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -3376,6 +3315,32 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,
|
||||
int id)
|
||||
{
|
||||
void *attr;
|
||||
int i = 0;
|
||||
|
||||
if (!mask)
|
||||
return true;
|
||||
|
||||
attr = nla_nest_start(msg, id);
|
||||
if (!attr)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < IEEE80211_MAX_CHAINS; i++) {
|
||||
if (!(mask & BIT(i)))
|
||||
continue;
|
||||
|
||||
if (nla_put_u8(msg, i, signal[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
nla_nest_end(msg, attr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
|
||||
int flags,
|
||||
struct cfg80211_registered_device *rdev,
|
||||
|
@ -3411,7 +3376,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
|
|||
(u32)sinfo->rx_bytes))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & (STATION_INFO_TX_BYTES |
|
||||
NL80211_STA_INFO_TX_BYTES64)) &&
|
||||
STATION_INFO_TX_BYTES64)) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
|
||||
(u32)sinfo->tx_bytes))
|
||||
goto nla_put_failure;
|
||||
|
@ -3447,6 +3412,18 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL) {
|
||||
if (!nl80211_put_signal(msg, sinfo->chains,
|
||||
sinfo->chain_signal,
|
||||
NL80211_STA_INFO_CHAIN_SIGNAL))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL_AVG) {
|
||||
if (!nl80211_put_signal(msg, sinfo->chains,
|
||||
sinfo->chain_signal_avg,
|
||||
NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
if (sinfo->filled & STATION_INFO_TX_BITRATE) {
|
||||
if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
|
||||
NL80211_STA_INFO_TX_BITRATE))
|
||||
|
@ -3834,6 +3811,8 @@ static int nl80211_set_station_tdls(struct genl_info *info,
|
|||
struct station_parameters *params)
|
||||
{
|
||||
/* Dummy STA entry gets updated once the peer capabilities are known */
|
||||
if (info->attrs[NL80211_ATTR_PEER_AID])
|
||||
params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
|
||||
if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
|
||||
params->ht_capa =
|
||||
nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
|
||||
|
@ -3974,7 +3953,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
|
|||
if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
|
||||
return -EINVAL;
|
||||
|
||||
if (!info->attrs[NL80211_ATTR_STA_AID])
|
||||
if (!info->attrs[NL80211_ATTR_STA_AID] &&
|
||||
!info->attrs[NL80211_ATTR_PEER_AID])
|
||||
return -EINVAL;
|
||||
|
||||
mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
|
||||
|
@ -3985,7 +3965,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
|
|||
params.listen_interval =
|
||||
nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
|
||||
|
||||
params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
|
||||
if (info->attrs[NL80211_ATTR_STA_AID])
|
||||
params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
|
||||
else
|
||||
params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
|
||||
if (!params.aid || params.aid > IEEE80211_MAX_AID)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -4634,6 +4617,7 @@ static const struct nla_policy
|
|||
[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 },
|
||||
[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 },
|
||||
[NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
|
||||
[NL80211_MESH_SETUP_AUTH_PROTOCOL] = { .type = NLA_U8 },
|
||||
[NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG },
|
||||
[NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY,
|
||||
.len = IEEE80211_MAX_DATA_LEN },
|
||||
|
@ -4819,6 +4803,13 @@ static int nl80211_parse_mesh_setup(struct genl_info *info,
|
|||
if (setup->is_secure)
|
||||
setup->user_mpm = true;
|
||||
|
||||
if (tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]) {
|
||||
if (!setup->user_mpm)
|
||||
return -EINVAL;
|
||||
setup->auth_id =
|
||||
nla_get_u8(tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4861,18 +4852,13 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
|
|||
void *hdr = NULL;
|
||||
struct nlattr *nl_reg_rules;
|
||||
unsigned int i;
|
||||
int err = -EINVAL;
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
|
||||
if (!cfg80211_regdomain)
|
||||
goto out;
|
||||
return -EINVAL;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg) {
|
||||
err = -ENOBUFS;
|
||||
goto out;
|
||||
}
|
||||
if (!msg)
|
||||
return -ENOBUFS;
|
||||
|
||||
hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
|
||||
NL80211_CMD_GET_REG);
|
||||
|
@ -4931,8 +4917,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
|
|||
nla_nest_end(msg, nl_reg_rules);
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
err = genlmsg_reply(msg, info);
|
||||
goto out;
|
||||
return genlmsg_reply(msg, info);
|
||||
|
||||
nla_put_failure_rcu:
|
||||
rcu_read_unlock();
|
||||
|
@ -4940,10 +4925,7 @@ nla_put_failure:
|
|||
genlmsg_cancel(msg, hdr);
|
||||
put_failure:
|
||||
nlmsg_free(msg);
|
||||
err = -EMSGSIZE;
|
||||
out:
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
return err;
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
|
||||
|
@ -5009,12 +4991,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
|
|||
}
|
||||
}
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
|
||||
r = set_regdom(rd);
|
||||
/* set_regdom took ownership */
|
||||
rd = NULL;
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
|
||||
bad_reg:
|
||||
kfree(rd);
|
||||
|
@ -5064,7 +5043,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
|||
if (!rdev->ops->scan)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
if (rdev->scan_req) {
|
||||
err = -EBUSY;
|
||||
goto unlock;
|
||||
|
@ -5250,7 +5228,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
|||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&rdev->sched_scan_mtx);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -5322,8 +5299,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
|||
if (ie_len > wiphy->max_sched_scan_ie_len)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
|
||||
if (rdev->sched_scan_req) {
|
||||
err = -EINPROGRESS;
|
||||
goto out;
|
||||
|
@ -5491,7 +5466,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
|||
out_free:
|
||||
kfree(request);
|
||||
out:
|
||||
mutex_unlock(&rdev->sched_scan_mtx);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -5499,17 +5473,12 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb,
|
|||
struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
int err;
|
||||
|
||||
if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
|
||||
!rdev->ops->sched_scan_stop)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
err = __cfg80211_stop_sched_scan(rdev, false);
|
||||
mutex_unlock(&rdev->sched_scan_mtx);
|
||||
|
||||
return err;
|
||||
return __cfg80211_stop_sched_scan(rdev, false);
|
||||
}
|
||||
|
||||
static int nl80211_start_radar_detection(struct sk_buff *skb,
|
||||
|
@ -5541,12 +5510,11 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
|
|||
if (!rdev->ops->start_radar_detection)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
|
||||
chandef.chan, CHAN_MODE_SHARED,
|
||||
BIT(chandef.width));
|
||||
if (err)
|
||||
goto err_locked;
|
||||
return err;
|
||||
|
||||
err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
|
||||
if (!err) {
|
||||
|
@ -5554,9 +5522,6 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
|
|||
wdev->cac_started = true;
|
||||
wdev->cac_start_time = jiffies;
|
||||
}
|
||||
err_locked:
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -5939,10 +5904,13 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
|
|||
if (local_state_change)
|
||||
return 0;
|
||||
|
||||
return cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
|
||||
ssid, ssid_len, ie, ie_len,
|
||||
key.p.key, key.p.key_len, key.idx,
|
||||
sae_data, sae_data_len);
|
||||
wdev_lock(dev->ieee80211_ptr);
|
||||
err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
|
||||
ssid, ssid_len, ie, ie_len,
|
||||
key.p.key, key.p.key_len, key.idx,
|
||||
sae_data, sae_data_len);
|
||||
wdev_unlock(dev->ieee80211_ptr);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
|
||||
|
@ -6109,9 +6077,12 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
|
|||
}
|
||||
|
||||
err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
|
||||
if (!err)
|
||||
if (!err) {
|
||||
wdev_lock(dev->ieee80211_ptr);
|
||||
err = cfg80211_mlme_assoc(rdev, dev, chan, bssid,
|
||||
ssid, ssid_len, &req);
|
||||
wdev_unlock(dev->ieee80211_ptr);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -6121,7 +6092,7 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
|
|||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
const u8 *ie = NULL, *bssid;
|
||||
int ie_len = 0;
|
||||
int ie_len = 0, err;
|
||||
u16 reason_code;
|
||||
bool local_state_change;
|
||||
|
||||
|
@ -6156,8 +6127,11 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
|
||||
|
||||
return cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
|
||||
local_state_change);
|
||||
wdev_lock(dev->ieee80211_ptr);
|
||||
err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,
|
||||
local_state_change);
|
||||
wdev_unlock(dev->ieee80211_ptr);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
|
||||
|
@ -6165,7 +6139,7 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
|
|||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
const u8 *ie = NULL, *bssid;
|
||||
int ie_len = 0;
|
||||
int ie_len = 0, err;
|
||||
u16 reason_code;
|
||||
bool local_state_change;
|
||||
|
||||
|
@ -6200,8 +6174,11 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];
|
||||
|
||||
return cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
|
||||
local_state_change);
|
||||
wdev_lock(dev->ieee80211_ptr);
|
||||
err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,
|
||||
local_state_change);
|
||||
wdev_unlock(dev->ieee80211_ptr);
|
||||
return err;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -6419,6 +6396,8 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
|
|||
void *data = NULL;
|
||||
int data_len = 0;
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
if (cb->args[0]) {
|
||||
/*
|
||||
* 0 is a valid index, but not valid for args[0],
|
||||
|
@ -6430,18 +6409,16 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
|
|||
nl80211_fam.attrbuf, nl80211_fam.maxattr,
|
||||
nl80211_policy);
|
||||
if (err)
|
||||
return err;
|
||||
goto out_err;
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),
|
||||
nl80211_fam.attrbuf);
|
||||
if (IS_ERR(rdev)) {
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
return PTR_ERR(rdev);
|
||||
err = PTR_ERR(rdev);
|
||||
goto out_err;
|
||||
}
|
||||
phy_idx = rdev->wiphy_idx;
|
||||
rdev = NULL;
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
|
||||
if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
|
||||
cb->args[1] =
|
||||
|
@ -6453,14 +6430,11 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
|
|||
data_len = nla_len((void *)cb->args[1]);
|
||||
}
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
|
||||
if (!rdev) {
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
return -ENOENT;
|
||||
err = -ENOENT;
|
||||
goto out_err;
|
||||
}
|
||||
cfg80211_lock_rdev(rdev);
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
|
||||
if (!rdev->ops->testmode_dump) {
|
||||
err = -EOPNOTSUPP;
|
||||
|
@ -6501,7 +6475,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
|
|||
/* see above */
|
||||
cb->args[0] = phy_idx + 1;
|
||||
out_err:
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
rtnl_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -6709,7 +6683,9 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
|
|||
sizeof(connect.vht_capa));
|
||||
}
|
||||
|
||||
err = cfg80211_connect(rdev, dev, &connect, connkeys);
|
||||
wdev_lock(dev->ieee80211_ptr);
|
||||
err = cfg80211_connect(rdev, dev, &connect, connkeys, NULL);
|
||||
wdev_unlock(dev->ieee80211_ptr);
|
||||
if (err)
|
||||
kfree(connkeys);
|
||||
return err;
|
||||
|
@ -6720,6 +6696,7 @@ static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
|
|||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
u16 reason;
|
||||
int ret;
|
||||
|
||||
if (!info->attrs[NL80211_ATTR_REASON_CODE])
|
||||
reason = WLAN_REASON_DEAUTH_LEAVING;
|
||||
|
@ -6733,7 +6710,10 @@ static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
|
|||
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return cfg80211_disconnect(rdev, dev, reason, true);
|
||||
wdev_lock(dev->ieee80211_ptr);
|
||||
ret = cfg80211_disconnect(rdev, dev, reason, true);
|
||||
wdev_unlock(dev->ieee80211_ptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
|
||||
|
@ -7509,28 +7489,29 @@ static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)
|
|||
static int nl80211_send_wowlan_patterns(struct sk_buff *msg,
|
||||
struct cfg80211_registered_device *rdev)
|
||||
{
|
||||
struct cfg80211_wowlan *wowlan = rdev->wiphy.wowlan_config;
|
||||
struct nlattr *nl_pats, *nl_pat;
|
||||
int i, pat_len;
|
||||
|
||||
if (!rdev->wowlan->n_patterns)
|
||||
if (!wowlan->n_patterns)
|
||||
return 0;
|
||||
|
||||
nl_pats = nla_nest_start(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN);
|
||||
if (!nl_pats)
|
||||
return -ENOBUFS;
|
||||
|
||||
for (i = 0; i < rdev->wowlan->n_patterns; i++) {
|
||||
for (i = 0; i < wowlan->n_patterns; i++) {
|
||||
nl_pat = nla_nest_start(msg, i + 1);
|
||||
if (!nl_pat)
|
||||
return -ENOBUFS;
|
||||
pat_len = rdev->wowlan->patterns[i].pattern_len;
|
||||
pat_len = wowlan->patterns[i].pattern_len;
|
||||
if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK,
|
||||
DIV_ROUND_UP(pat_len, 8),
|
||||
rdev->wowlan->patterns[i].mask) ||
|
||||
wowlan->patterns[i].mask) ||
|
||||
nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN,
|
||||
pat_len, rdev->wowlan->patterns[i].pattern) ||
|
||||
pat_len, wowlan->patterns[i].pattern) ||
|
||||
nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET,
|
||||
rdev->wowlan->patterns[i].pkt_offset))
|
||||
wowlan->patterns[i].pkt_offset))
|
||||
return -ENOBUFS;
|
||||
nla_nest_end(msg, nl_pat);
|
||||
}
|
||||
|
@ -7577,6 +7558,8 @@ static int nl80211_send_wowlan_tcp(struct sk_buff *msg,
|
|||
&tcp->payload_tok))
|
||||
return -ENOBUFS;
|
||||
|
||||
nla_nest_end(msg, nl_tcp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -7591,12 +7574,12 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
|
|||
!rdev->wiphy.wowlan.tcp)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (rdev->wowlan && rdev->wowlan->tcp) {
|
||||
if (rdev->wiphy.wowlan_config && rdev->wiphy.wowlan_config->tcp) {
|
||||
/* adjust size to have room for all the data */
|
||||
size += rdev->wowlan->tcp->tokens_size +
|
||||
rdev->wowlan->tcp->payload_len +
|
||||
rdev->wowlan->tcp->wake_len +
|
||||
rdev->wowlan->tcp->wake_len / 8;
|
||||
size += rdev->wiphy.wowlan_config->tcp->tokens_size +
|
||||
rdev->wiphy.wowlan_config->tcp->payload_len +
|
||||
rdev->wiphy.wowlan_config->tcp->wake_len +
|
||||
rdev->wiphy.wowlan_config->tcp->wake_len / 8;
|
||||
}
|
||||
|
||||
msg = nlmsg_new(size, GFP_KERNEL);
|
||||
|
@ -7608,33 +7591,34 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
|
|||
if (!hdr)
|
||||
goto nla_put_failure;
|
||||
|
||||
if (rdev->wowlan) {
|
||||
if (rdev->wiphy.wowlan_config) {
|
||||
struct nlattr *nl_wowlan;
|
||||
|
||||
nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);
|
||||
if (!nl_wowlan)
|
||||
goto nla_put_failure;
|
||||
|
||||
if ((rdev->wowlan->any &&
|
||||
if ((rdev->wiphy.wowlan_config->any &&
|
||||
nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
|
||||
(rdev->wowlan->disconnect &&
|
||||
(rdev->wiphy.wowlan_config->disconnect &&
|
||||
nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
|
||||
(rdev->wowlan->magic_pkt &&
|
||||
(rdev->wiphy.wowlan_config->magic_pkt &&
|
||||
nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
|
||||
(rdev->wowlan->gtk_rekey_failure &&
|
||||
(rdev->wiphy.wowlan_config->gtk_rekey_failure &&
|
||||
nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
|
||||
(rdev->wowlan->eap_identity_req &&
|
||||
(rdev->wiphy.wowlan_config->eap_identity_req &&
|
||||
nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
|
||||
(rdev->wowlan->four_way_handshake &&
|
||||
(rdev->wiphy.wowlan_config->four_way_handshake &&
|
||||
nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
|
||||
(rdev->wowlan->rfkill_release &&
|
||||
(rdev->wiphy.wowlan_config->rfkill_release &&
|
||||
nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (nl80211_send_wowlan_patterns(msg, rdev))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (nl80211_send_wowlan_tcp(msg, rdev->wowlan->tcp))
|
||||
if (nl80211_send_wowlan_tcp(msg,
|
||||
rdev->wiphy.wowlan_config->tcp))
|
||||
goto nla_put_failure;
|
||||
|
||||
nla_nest_end(msg, nl_wowlan);
|
||||
|
@ -7801,7 +7785,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
|
|||
struct cfg80211_wowlan *ntrig;
|
||||
struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan;
|
||||
int err, i;
|
||||
bool prev_enabled = rdev->wowlan;
|
||||
bool prev_enabled = rdev->wiphy.wowlan_config;
|
||||
|
||||
if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns &&
|
||||
!rdev->wiphy.wowlan.tcp)
|
||||
|
@ -7809,7 +7793,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) {
|
||||
cfg80211_rdev_free_wowlan(rdev);
|
||||
rdev->wowlan = NULL;
|
||||
rdev->wiphy.wowlan_config = NULL;
|
||||
goto set_wakeup;
|
||||
}
|
||||
|
||||
|
@ -7945,11 +7929,12 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
|
|||
goto error;
|
||||
}
|
||||
cfg80211_rdev_free_wowlan(rdev);
|
||||
rdev->wowlan = ntrig;
|
||||
rdev->wiphy.wowlan_config = ntrig;
|
||||
|
||||
set_wakeup:
|
||||
if (rdev->ops->set_wakeup && prev_enabled != !!rdev->wowlan)
|
||||
rdev_set_wakeup(rdev, rdev->wowlan);
|
||||
if (rdev->ops->set_wakeup &&
|
||||
prev_enabled != !!rdev->wiphy.wowlan_config)
|
||||
rdev_set_wakeup(rdev, rdev->wiphy.wowlan_config);
|
||||
|
||||
return 0;
|
||||
error:
|
||||
|
@ -8134,9 +8119,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
|
|||
if (wdev->p2p_started)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
err = cfg80211_can_add_interface(rdev, wdev->iftype);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -8145,9 +8128,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
|
|||
return err;
|
||||
|
||||
wdev->p2p_started = true;
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
rdev->opencount++;
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -8163,11 +8144,7 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
|
|||
if (!rdev->ops->stop_p2p_device)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
cfg80211_stop_p2p_device(rdev, wdev);
|
||||
mutex_unlock(&rdev->sched_scan_mtx);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -8310,11 +8287,11 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
|
|||
info->user_ptr[0] = rdev;
|
||||
} else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV ||
|
||||
ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
ASSERT_RTNL();
|
||||
|
||||
wdev = __cfg80211_wdev_from_attrs(genl_info_net(info),
|
||||
info->attrs);
|
||||
if (IS_ERR(wdev)) {
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
if (rtnl)
|
||||
rtnl_unlock();
|
||||
return PTR_ERR(wdev);
|
||||
|
@ -8325,7 +8302,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
|
|||
|
||||
if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
|
||||
if (!dev) {
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
if (rtnl)
|
||||
rtnl_unlock();
|
||||
return -EINVAL;
|
||||
|
@ -8339,7 +8315,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
|
|||
if (dev) {
|
||||
if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
|
||||
!netif_running(dev)) {
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
if (rtnl)
|
||||
rtnl_unlock();
|
||||
return -ENETDOWN;
|
||||
|
@ -8348,17 +8323,12 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
|
|||
dev_hold(dev);
|
||||
} else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) {
|
||||
if (!wdev->p2p_started) {
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
if (rtnl)
|
||||
rtnl_unlock();
|
||||
return -ENETDOWN;
|
||||
}
|
||||
}
|
||||
|
||||
cfg80211_lock_rdev(rdev);
|
||||
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
|
||||
info->user_ptr[0] = rdev;
|
||||
}
|
||||
|
||||
|
@ -8368,8 +8338,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
|
|||
static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
|
||||
struct genl_info *info)
|
||||
{
|
||||
if (info->user_ptr[0])
|
||||
cfg80211_unlock_rdev(info->user_ptr[0]);
|
||||
if (info->user_ptr[1]) {
|
||||
if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
|
||||
struct wireless_dev *wdev = info->user_ptr[1];
|
||||
|
@ -8391,7 +8359,8 @@ static struct genl_ops nl80211_ops[] = {
|
|||
.dumpit = nl80211_dump_wiphy,
|
||||
.policy = nl80211_policy,
|
||||
/* can be retrieved by unprivileged users */
|
||||
.internal_flags = NL80211_FLAG_NEED_WIPHY,
|
||||
.internal_flags = NL80211_FLAG_NEED_WIPHY |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
{
|
||||
.cmd = NL80211_CMD_SET_WIPHY,
|
||||
|
@ -8406,7 +8375,8 @@ static struct genl_ops nl80211_ops[] = {
|
|||
.dumpit = nl80211_dump_interface,
|
||||
.policy = nl80211_policy,
|
||||
/* can be retrieved by unprivileged users */
|
||||
.internal_flags = NL80211_FLAG_NEED_WDEV,
|
||||
.internal_flags = NL80211_FLAG_NEED_WDEV |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
{
|
||||
.cmd = NL80211_CMD_SET_INTERFACE,
|
||||
|
@ -8565,6 +8535,7 @@ static struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_GET_REG,
|
||||
.doit = nl80211_get_reg,
|
||||
.policy = nl80211_policy,
|
||||
.internal_flags = NL80211_FLAG_NEED_RTNL,
|
||||
/* can be retrieved by unprivileged users */
|
||||
},
|
||||
{
|
||||
|
@ -8572,6 +8543,7 @@ static struct genl_ops nl80211_ops[] = {
|
|||
.doit = nl80211_set_reg,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
{
|
||||
.cmd = NL80211_CMD_REQ_SET_REG,
|
||||
|
@ -9027,8 +8999,6 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
|
|||
struct nlattr *nest;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&rdev->sched_scan_mtx);
|
||||
|
||||
if (WARN_ON(!req))
|
||||
return 0;
|
||||
|
||||
|
@ -9970,6 +9940,7 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
|
|||
if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
|
||||
(netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
|
||||
netdev->ifindex)) ||
|
||||
nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) ||
|
||||
(sig_dbm &&
|
||||
nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
|
||||
|
@ -10010,6 +9981,7 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
|
|||
if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
|
||||
(netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
|
||||
netdev->ifindex)) ||
|
||||
nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||
|
||||
nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
|
||||
nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) ||
|
||||
(ack && nla_put_flag(msg, NL80211_ATTR_ACK)))
|
||||
|
|
|
@ -81,7 +81,10 @@ static struct regulatory_request core_request_world = {
|
|||
.country_ie_env = ENVIRON_ANY,
|
||||
};
|
||||
|
||||
/* Receipt of information from last regulatory request */
|
||||
/*
|
||||
* Receipt of information from last regulatory request,
|
||||
* protected by RTNL (and can be accessed with RCU protection)
|
||||
*/
|
||||
static struct regulatory_request __rcu *last_request =
|
||||
(void __rcu *)&core_request_world;
|
||||
|
||||
|
@ -96,39 +99,25 @@ static struct device_type reg_device_type = {
|
|||
* Central wireless core regulatory domains, we only need two,
|
||||
* the current one and a world regulatory domain in case we have no
|
||||
* information to give us an alpha2.
|
||||
* (protected by RTNL, can be read under RCU)
|
||||
*/
|
||||
const struct ieee80211_regdomain __rcu *cfg80211_regdomain;
|
||||
|
||||
/*
|
||||
* Protects static reg.c components:
|
||||
* - cfg80211_regdomain (if not used with RCU)
|
||||
* - cfg80211_world_regdom
|
||||
* - last_request (if not used with RCU)
|
||||
* - reg_num_devs_support_basehint
|
||||
*/
|
||||
static DEFINE_MUTEX(reg_mutex);
|
||||
|
||||
/*
|
||||
* Number of devices that registered to the core
|
||||
* that support cellular base station regulatory hints
|
||||
* (protected by RTNL)
|
||||
*/
|
||||
static int reg_num_devs_support_basehint;
|
||||
|
||||
static inline void assert_reg_lock(void)
|
||||
{
|
||||
lockdep_assert_held(®_mutex);
|
||||
}
|
||||
|
||||
static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
|
||||
{
|
||||
return rcu_dereference_protected(cfg80211_regdomain,
|
||||
lockdep_is_held(®_mutex));
|
||||
return rtnl_dereference(cfg80211_regdomain);
|
||||
}
|
||||
|
||||
static const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy)
|
||||
{
|
||||
return rcu_dereference_protected(wiphy->regd,
|
||||
lockdep_is_held(®_mutex));
|
||||
return rtnl_dereference(wiphy->regd);
|
||||
}
|
||||
|
||||
static void rcu_free_regdom(const struct ieee80211_regdomain *r)
|
||||
|
@ -140,8 +129,7 @@ static void rcu_free_regdom(const struct ieee80211_regdomain *r)
|
|||
|
||||
static struct regulatory_request *get_last_request(void)
|
||||
{
|
||||
return rcu_dereference_check(last_request,
|
||||
lockdep_is_held(®_mutex));
|
||||
return rcu_dereference_rtnl(last_request);
|
||||
}
|
||||
|
||||
/* Used to queue up regulatory hints */
|
||||
|
@ -200,6 +188,7 @@ static const struct ieee80211_regdomain world_regdom = {
|
|||
}
|
||||
};
|
||||
|
||||
/* protected by RTNL */
|
||||
static const struct ieee80211_regdomain *cfg80211_world_regdom =
|
||||
&world_regdom;
|
||||
|
||||
|
@ -215,7 +204,7 @@ static void reset_regdomains(bool full_reset,
|
|||
const struct ieee80211_regdomain *r;
|
||||
struct regulatory_request *lr;
|
||||
|
||||
assert_reg_lock();
|
||||
ASSERT_RTNL();
|
||||
|
||||
r = get_cfg80211_regdom();
|
||||
|
||||
|
@ -377,7 +366,7 @@ static void reg_regdb_search(struct work_struct *work)
|
|||
const struct ieee80211_regdomain *curdom, *regdom = NULL;
|
||||
int i;
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
rtnl_lock();
|
||||
|
||||
mutex_lock(®_regdb_search_mutex);
|
||||
while (!list_empty(®_regdb_search_list)) {
|
||||
|
@ -402,7 +391,7 @@ static void reg_regdb_search(struct work_struct *work)
|
|||
if (!IS_ERR_OR_NULL(regdom))
|
||||
set_regdom(regdom);
|
||||
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
static DECLARE_WORK(reg_regdb_work, reg_regdb_search);
|
||||
|
@ -936,13 +925,7 @@ static bool reg_request_cell_base(struct regulatory_request *request)
|
|||
|
||||
bool reg_last_request_cell_base(void)
|
||||
{
|
||||
bool val;
|
||||
|
||||
mutex_lock(®_mutex);
|
||||
val = reg_request_cell_base(get_last_request());
|
||||
mutex_unlock(®_mutex);
|
||||
|
||||
return val;
|
||||
return reg_request_cell_base(get_last_request());
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CFG80211_CERTIFICATION_ONUS
|
||||
|
@ -1225,7 +1208,7 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
|
|||
struct cfg80211_registered_device *rdev;
|
||||
struct wiphy *wiphy;
|
||||
|
||||
assert_cfg80211_lock();
|
||||
ASSERT_RTNL();
|
||||
|
||||
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
|
||||
wiphy = &rdev->wiphy;
|
||||
|
@ -1444,8 +1427,6 @@ static void reg_set_request_processed(void)
|
|||
* what it believes should be the current regulatory domain.
|
||||
*
|
||||
* Returns one of the different reg request treatment values.
|
||||
*
|
||||
* Caller must hold ®_mutex
|
||||
*/
|
||||
static enum reg_request_treatment
|
||||
__regulatory_hint(struct wiphy *wiphy,
|
||||
|
@ -1570,21 +1551,19 @@ static void reg_process_pending_hints(void)
|
|||
{
|
||||
struct regulatory_request *reg_request, *lr;
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
mutex_lock(®_mutex);
|
||||
lr = get_last_request();
|
||||
|
||||
/* When last_request->processed becomes true this will be rescheduled */
|
||||
if (lr && !lr->processed) {
|
||||
REG_DBG_PRINT("Pending regulatory request, waiting for it to be processed...\n");
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock(®_requests_lock);
|
||||
|
||||
if (list_empty(®_requests_list)) {
|
||||
spin_unlock(®_requests_lock);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
reg_request = list_first_entry(®_requests_list,
|
||||
|
@ -1595,10 +1574,6 @@ static void reg_process_pending_hints(void)
|
|||
spin_unlock(®_requests_lock);
|
||||
|
||||
reg_process_hint(reg_request, reg_request->initiator);
|
||||
|
||||
out:
|
||||
mutex_unlock(®_mutex);
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
}
|
||||
|
||||
/* Processes beacon hints -- this has nothing to do with country IEs */
|
||||
|
@ -1607,9 +1582,6 @@ static void reg_process_pending_beacon_hints(void)
|
|||
struct cfg80211_registered_device *rdev;
|
||||
struct reg_beacon *pending_beacon, *tmp;
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
mutex_lock(®_mutex);
|
||||
|
||||
/* This goes through the _pending_ beacon list */
|
||||
spin_lock_bh(®_pending_beacons_lock);
|
||||
|
||||
|
@ -1626,14 +1598,14 @@ static void reg_process_pending_beacon_hints(void)
|
|||
}
|
||||
|
||||
spin_unlock_bh(®_pending_beacons_lock);
|
||||
mutex_unlock(®_mutex);
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
}
|
||||
|
||||
static void reg_todo(struct work_struct *work)
|
||||
{
|
||||
rtnl_lock();
|
||||
reg_process_pending_hints();
|
||||
reg_process_pending_beacon_hints();
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
static void queue_regulatory_request(struct regulatory_request *request)
|
||||
|
@ -1717,29 +1689,23 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
|
|||
}
|
||||
EXPORT_SYMBOL(regulatory_hint);
|
||||
|
||||
/*
|
||||
* We hold wdev_lock() here so we cannot hold cfg80211_mutex() and
|
||||
* therefore cannot iterate over the rdev list here.
|
||||
*/
|
||||
void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
|
||||
const u8 *country_ie, u8 country_ie_len)
|
||||
{
|
||||
char alpha2[2];
|
||||
enum environment_cap env = ENVIRON_ANY;
|
||||
struct regulatory_request *request, *lr;
|
||||
|
||||
mutex_lock(®_mutex);
|
||||
lr = get_last_request();
|
||||
|
||||
if (unlikely(!lr))
|
||||
goto out;
|
||||
struct regulatory_request *request = NULL, *lr;
|
||||
|
||||
/* IE len must be evenly divisible by 2 */
|
||||
if (country_ie_len & 0x01)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
request = kzalloc(sizeof(*request), GFP_KERNEL);
|
||||
if (!request)
|
||||
return;
|
||||
|
||||
alpha2[0] = country_ie[0];
|
||||
alpha2[1] = country_ie[1];
|
||||
|
@ -1749,19 +1715,21 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
|
|||
else if (country_ie[2] == 'O')
|
||||
env = ENVIRON_OUTDOOR;
|
||||
|
||||
rcu_read_lock();
|
||||
lr = get_last_request();
|
||||
|
||||
if (unlikely(!lr))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* We will run this only upon a successful connection on cfg80211.
|
||||
* We leave conflict resolution to the workqueue, where can hold
|
||||
* cfg80211_mutex.
|
||||
* the RTNL.
|
||||
*/
|
||||
if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
|
||||
lr->wiphy_idx != WIPHY_IDX_INVALID)
|
||||
goto out;
|
||||
|
||||
request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);
|
||||
if (!request)
|
||||
goto out;
|
||||
|
||||
request->wiphy_idx = get_wiphy_idx(wiphy);
|
||||
request->alpha2[0] = alpha2[0];
|
||||
request->alpha2[1] = alpha2[1];
|
||||
|
@ -1769,8 +1737,10 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
|
|||
request->country_ie_env = env;
|
||||
|
||||
queue_regulatory_request(request);
|
||||
request = NULL;
|
||||
out:
|
||||
mutex_unlock(®_mutex);
|
||||
kfree(request);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void restore_alpha2(char *alpha2, bool reset_user)
|
||||
|
@ -1858,8 +1828,7 @@ static void restore_regulatory_settings(bool reset_user)
|
|||
LIST_HEAD(tmp_reg_req_list);
|
||||
struct cfg80211_registered_device *rdev;
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
mutex_lock(®_mutex);
|
||||
ASSERT_RTNL();
|
||||
|
||||
reset_regdomains(true, &world_regdom);
|
||||
restore_alpha2(alpha2, reset_user);
|
||||
|
@ -1914,9 +1883,6 @@ static void restore_regulatory_settings(bool reset_user)
|
|||
list_splice_tail_init(&tmp_reg_req_list, ®_requests_list);
|
||||
spin_unlock(®_requests_lock);
|
||||
|
||||
mutex_unlock(®_mutex);
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
|
||||
REG_DBG_PRINT("Kicking the queue\n");
|
||||
|
||||
schedule_work(®_work);
|
||||
|
@ -2231,7 +2197,6 @@ int set_regdom(const struct ieee80211_regdomain *rd)
|
|||
struct regulatory_request *lr;
|
||||
int r;
|
||||
|
||||
mutex_lock(®_mutex);
|
||||
lr = get_last_request();
|
||||
|
||||
/* Note that this doesn't update the wiphys, this is done below */
|
||||
|
@ -2241,14 +2206,12 @@ int set_regdom(const struct ieee80211_regdomain *rd)
|
|||
reg_set_request_processed();
|
||||
|
||||
kfree(rd);
|
||||
goto out;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* This would make this whole thing pointless */
|
||||
if (WARN_ON(!lr->intersect && rd != get_cfg80211_regdom())) {
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (WARN_ON(!lr->intersect && rd != get_cfg80211_regdom()))
|
||||
return -EINVAL;
|
||||
|
||||
/* update all wiphys now with the new established regulatory domain */
|
||||
update_all_wiphy_regulatory(lr->initiator);
|
||||
|
@ -2259,10 +2222,7 @@ int set_regdom(const struct ieee80211_regdomain *rd)
|
|||
|
||||
reg_set_request_processed();
|
||||
|
||||
out:
|
||||
mutex_unlock(®_mutex);
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
|
@ -2287,23 +2247,17 @@ int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env)
|
|||
|
||||
void wiphy_regulatory_register(struct wiphy *wiphy)
|
||||
{
|
||||
mutex_lock(®_mutex);
|
||||
|
||||
if (!reg_dev_ignore_cell_hint(wiphy))
|
||||
reg_num_devs_support_basehint++;
|
||||
|
||||
wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
|
||||
|
||||
mutex_unlock(®_mutex);
|
||||
}
|
||||
|
||||
/* Caller must hold cfg80211_mutex */
|
||||
void wiphy_regulatory_deregister(struct wiphy *wiphy)
|
||||
{
|
||||
struct wiphy *request_wiphy = NULL;
|
||||
struct regulatory_request *lr;
|
||||
|
||||
mutex_lock(®_mutex);
|
||||
lr = get_last_request();
|
||||
|
||||
if (!reg_dev_ignore_cell_hint(wiphy))
|
||||
|
@ -2316,12 +2270,10 @@ void wiphy_regulatory_deregister(struct wiphy *wiphy)
|
|||
request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx);
|
||||
|
||||
if (!request_wiphy || request_wiphy != wiphy)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
lr->wiphy_idx = WIPHY_IDX_INVALID;
|
||||
lr->country_ie_env = ENVIRON_ANY;
|
||||
out:
|
||||
mutex_unlock(®_mutex);
|
||||
}
|
||||
|
||||
static void reg_timeout_work(struct work_struct *work)
|
||||
|
@ -2385,9 +2337,9 @@ void regulatory_exit(void)
|
|||
cancel_delayed_work_sync(®_timeout);
|
||||
|
||||
/* Lock to suppress warnings */
|
||||
mutex_lock(®_mutex);
|
||||
rtnl_lock();
|
||||
reset_regdomains(true, NULL);
|
||||
mutex_unlock(®_mutex);
|
||||
rtnl_unlock();
|
||||
|
||||
dev_set_uevent_suppress(®_pdev->dev, true);
|
||||
|
||||
|
|
|
@ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
|
|||
union iwreq_data wrqu;
|
||||
#endif
|
||||
|
||||
lockdep_assert_held(&rdev->sched_scan_mtx);
|
||||
ASSERT_RTNL();
|
||||
|
||||
request = rdev->scan_req;
|
||||
|
||||
|
@ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk)
|
|||
rdev = container_of(wk, struct cfg80211_registered_device,
|
||||
scan_done_wk);
|
||||
|
||||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
rtnl_lock();
|
||||
___cfg80211_scan_done(rdev, false);
|
||||
mutex_unlock(&rdev->sched_scan_mtx);
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
|
||||
|
@ -241,6 +241,7 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
|
|||
WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
|
||||
|
||||
request->aborted = aborted;
|
||||
request->notified = true;
|
||||
queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_scan_done);
|
||||
|
@ -255,7 +256,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
|
|||
|
||||
request = rdev->sched_scan_req;
|
||||
|
||||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
rtnl_lock();
|
||||
|
||||
/* we don't have sched_scan_req anymore if the scan is stopping */
|
||||
if (request) {
|
||||
|
@ -270,7 +271,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
|
|||
nl80211_send_sched_scan_results(rdev, request->dev);
|
||||
}
|
||||
|
||||
mutex_unlock(&rdev->sched_scan_mtx);
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
void cfg80211_sched_scan_results(struct wiphy *wiphy)
|
||||
|
@ -289,9 +290,9 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
|
|||
|
||||
trace_cfg80211_sched_scan_stopped(wiphy);
|
||||
|
||||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
rtnl_lock();
|
||||
__cfg80211_stop_sched_scan(rdev, true);
|
||||
mutex_unlock(&rdev->sched_scan_mtx);
|
||||
rtnl_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
|
||||
|
||||
|
@ -300,7 +301,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
|
|||
{
|
||||
struct net_device *dev;
|
||||
|
||||
lockdep_assert_held(&rdev->sched_scan_mtx);
|
||||
ASSERT_RTNL();
|
||||
|
||||
if (!rdev->sched_scan_req)
|
||||
return -ENOENT;
|
||||
|
@ -1040,6 +1041,25 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
|
|||
EXPORT_SYMBOL(cfg80211_unlink_bss);
|
||||
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
static struct cfg80211_registered_device *
|
||||
cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct net_device *dev;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
dev = dev_get_by_index(net, ifindex);
|
||||
if (!dev)
|
||||
return ERR_PTR(-ENODEV);
|
||||
if (dev->ieee80211_ptr)
|
||||
rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
|
||||
else
|
||||
rdev = ERR_PTR(-ENODEV);
|
||||
dev_put(dev);
|
||||
return rdev;
|
||||
}
|
||||
|
||||
int cfg80211_wext_siwscan(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
|
@ -1062,7 +1082,6 @@ int cfg80211_wext_siwscan(struct net_device *dev,
|
|||
if (IS_ERR(rdev))
|
||||
return PTR_ERR(rdev);
|
||||
|
||||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
if (rdev->scan_req) {
|
||||
err = -EBUSY;
|
||||
goto out;
|
||||
|
@ -1169,9 +1188,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
|
|||
dev_hold(dev);
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&rdev->sched_scan_mtx);
|
||||
kfree(creq);
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan);
|
||||
|
@ -1470,10 +1487,8 @@ int cfg80211_wext_giwscan(struct net_device *dev,
|
|||
if (IS_ERR(rdev))
|
||||
return PTR_ERR(rdev);
|
||||
|
||||
if (rdev->scan_req) {
|
||||
res = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
if (rdev->scan_req)
|
||||
return -EAGAIN;
|
||||
|
||||
res = ieee80211_scan_results(rdev, info, extra, data->length);
|
||||
data->length = 0;
|
||||
|
@ -1482,8 +1497,6 @@ int cfg80211_wext_giwscan(struct net_device *dev,
|
|||
res = 0;
|
||||
}
|
||||
|
||||
out:
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan);
|
||||
|
|
|
@ -43,35 +43,29 @@ static bool cfg80211_is_all_idle(void)
|
|||
struct wireless_dev *wdev;
|
||||
bool is_all_idle = true;
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
|
||||
/*
|
||||
* All devices must be idle as otherwise if you are actively
|
||||
* scanning some new beacon hints could be learned and would
|
||||
* count as new regulatory hints.
|
||||
*/
|
||||
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
|
||||
cfg80211_lock_rdev(rdev);
|
||||
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
||||
wdev_lock(wdev);
|
||||
if (wdev->sme_state != CFG80211_SME_IDLE)
|
||||
is_all_idle = false;
|
||||
wdev_unlock(wdev);
|
||||
}
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
}
|
||||
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
|
||||
return is_all_idle;
|
||||
}
|
||||
|
||||
static void disconnect_work(struct work_struct *work)
|
||||
{
|
||||
if (!cfg80211_is_all_idle())
|
||||
return;
|
||||
|
||||
regulatory_hint_disconnect();
|
||||
rtnl_lock();
|
||||
if (cfg80211_is_all_idle())
|
||||
regulatory_hint_disconnect();
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
|
||||
|
@ -85,7 +79,6 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
|
|||
ASSERT_RTNL();
|
||||
ASSERT_RDEV_LOCK(rdev);
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
lockdep_assert_held(&rdev->sched_scan_mtx);
|
||||
|
||||
if (rdev->scan_req)
|
||||
return -EBUSY;
|
||||
|
@ -176,13 +169,13 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
|
|||
case CFG80211_CONN_AUTHENTICATE_NEXT:
|
||||
BUG_ON(!rdev->ops->auth);
|
||||
wdev->conn->state = CFG80211_CONN_AUTHENTICATING;
|
||||
return __cfg80211_mlme_auth(rdev, wdev->netdev,
|
||||
params->channel, params->auth_type,
|
||||
params->bssid,
|
||||
params->ssid, params->ssid_len,
|
||||
NULL, 0,
|
||||
params->key, params->key_len,
|
||||
params->key_idx, NULL, 0);
|
||||
return cfg80211_mlme_auth(rdev, wdev->netdev,
|
||||
params->channel, params->auth_type,
|
||||
params->bssid,
|
||||
params->ssid, params->ssid_len,
|
||||
NULL, 0,
|
||||
params->key, params->key_len,
|
||||
params->key_idx, NULL, 0);
|
||||
case CFG80211_CONN_ASSOCIATE_NEXT:
|
||||
BUG_ON(!rdev->ops->assoc);
|
||||
wdev->conn->state = CFG80211_CONN_ASSOCIATING;
|
||||
|
@ -198,19 +191,19 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
|
|||
req.vht_capa = params->vht_capa;
|
||||
req.vht_capa_mask = params->vht_capa_mask;
|
||||
|
||||
err = __cfg80211_mlme_assoc(rdev, wdev->netdev, params->channel,
|
||||
params->bssid, params->ssid,
|
||||
params->ssid_len, &req);
|
||||
err = cfg80211_mlme_assoc(rdev, wdev->netdev, params->channel,
|
||||
params->bssid, params->ssid,
|
||||
params->ssid_len, &req);
|
||||
if (err)
|
||||
__cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
|
||||
NULL, 0,
|
||||
WLAN_REASON_DEAUTH_LEAVING,
|
||||
false);
|
||||
cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
|
||||
NULL, 0,
|
||||
WLAN_REASON_DEAUTH_LEAVING,
|
||||
false);
|
||||
return err;
|
||||
case CFG80211_CONN_DEAUTH_ASSOC_FAIL:
|
||||
__cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
|
||||
NULL, 0,
|
||||
WLAN_REASON_DEAUTH_LEAVING, false);
|
||||
cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
|
||||
NULL, 0,
|
||||
WLAN_REASON_DEAUTH_LEAVING, false);
|
||||
/* return an error so that we call __cfg80211_connect_result() */
|
||||
return -EINVAL;
|
||||
default:
|
||||
|
@ -226,11 +219,11 @@ void cfg80211_conn_work(struct work_struct *work)
|
|||
u8 bssid_buf[ETH_ALEN], *bssid = NULL;
|
||||
|
||||
rtnl_lock();
|
||||
cfg80211_lock_rdev(rdev);
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
|
||||
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
||||
if (!wdev->netdev)
|
||||
continue;
|
||||
|
||||
wdev_lock(wdev);
|
||||
if (!netif_running(wdev->netdev)) {
|
||||
wdev_unlock(wdev);
|
||||
|
@ -253,9 +246,6 @@ void cfg80211_conn_work(struct work_struct *work)
|
|||
wdev_unlock(wdev);
|
||||
}
|
||||
|
||||
mutex_unlock(&rdev->sched_scan_mtx);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
|
@ -770,11 +760,11 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason,
|
|||
}
|
||||
EXPORT_SYMBOL(cfg80211_disconnected);
|
||||
|
||||
int __cfg80211_connect(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct cfg80211_connect_params *connect,
|
||||
struct cfg80211_cached_keys *connkeys,
|
||||
const u8 *prev_bssid)
|
||||
int cfg80211_connect(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct cfg80211_connect_params *connect,
|
||||
struct cfg80211_cached_keys *connkeys,
|
||||
const u8 *prev_bssid)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_bss *bss = NULL;
|
||||
|
@ -921,27 +911,8 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
|
|||
}
|
||||
}
|
||||
|
||||
int cfg80211_connect(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct cfg80211_connect_params *connect,
|
||||
struct cfg80211_cached_keys *connkeys)
|
||||
{
|
||||
int err;
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
/* might request scan - scan_mtx -> wdev_mtx dependency */
|
||||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
wdev_lock(dev->ieee80211_ptr);
|
||||
err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
|
||||
wdev_unlock(dev->ieee80211_ptr);
|
||||
mutex_unlock(&rdev->sched_scan_mtx);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, u16 reason, bool wextev)
|
||||
int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, u16 reason, bool wextev)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
int err;
|
||||
|
@ -961,7 +932,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
|
|||
/* was it connected by userspace SME? */
|
||||
if (!wdev->conn) {
|
||||
cfg80211_mlme_down(rdev, dev);
|
||||
return 0;
|
||||
goto disconnect;
|
||||
}
|
||||
|
||||
if (wdev->sme_state == CFG80211_SME_CONNECTING &&
|
||||
|
@ -976,7 +947,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
|
|||
}
|
||||
|
||||
/* wdev->conn->params.bssid must be set if > SCANNING */
|
||||
err = __cfg80211_mlme_deauth(rdev, dev,
|
||||
err = cfg80211_mlme_deauth(rdev, dev,
|
||||
wdev->conn->params.bssid,
|
||||
NULL, 0, reason, false);
|
||||
if (err)
|
||||
|
@ -987,6 +958,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
|
|||
return err;
|
||||
}
|
||||
|
||||
disconnect:
|
||||
if (wdev->sme_state == CFG80211_SME_CONNECTED)
|
||||
__cfg80211_disconnected(dev, NULL, 0, 0, false);
|
||||
else if (wdev->sme_state == CFG80211_SME_CONNECTING)
|
||||
|
@ -997,19 +969,6 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
u16 reason, bool wextev)
|
||||
{
|
||||
int err;
|
||||
|
||||
wdev_lock(dev->ieee80211_ptr);
|
||||
err = __cfg80211_disconnect(rdev, dev, reason, wextev);
|
||||
wdev_unlock(dev->ieee80211_ptr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void cfg80211_sme_disassoc(struct net_device *dev,
|
||||
struct cfg80211_internal_bss *bss)
|
||||
{
|
||||
|
@ -1032,6 +991,6 @@ void cfg80211_sme_disassoc(struct net_device *dev,
|
|||
|
||||
memcpy(bssid, bss->pub.bssid, ETH_ALEN);
|
||||
|
||||
__cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0,
|
||||
WLAN_REASON_DEAUTH_LEAVING, false);
|
||||
cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0,
|
||||
WLAN_REASON_DEAUTH_LEAVING, false);
|
||||
}
|
||||
|
|
|
@ -91,6 +91,7 @@ static void cfg80211_leave_all(struct cfg80211_registered_device *rdev)
|
|||
cfg80211_leave(rdev, wdev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wiphy_suspend(struct device *dev, pm_message_t state)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = dev_to_rdev(dev);
|
||||
|
@ -100,10 +101,10 @@ static int wiphy_suspend(struct device *dev, pm_message_t state)
|
|||
|
||||
rtnl_lock();
|
||||
if (rdev->wiphy.registered) {
|
||||
if (!rdev->wowlan)
|
||||
if (!rdev->wiphy.wowlan_config)
|
||||
cfg80211_leave_all(rdev);
|
||||
if (rdev->ops->suspend)
|
||||
ret = rdev_suspend(rdev, rdev->wowlan);
|
||||
ret = rdev_suspend(rdev, rdev->wiphy.wowlan_config);
|
||||
if (ret == 1) {
|
||||
/* Driver refuse to configure wowlan */
|
||||
cfg80211_leave_all(rdev);
|
||||
|
@ -132,6 +133,7 @@ static int wiphy_resume(struct device *dev)
|
|||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const void *wiphy_namespace(struct device *d)
|
||||
{
|
||||
|
@ -146,8 +148,10 @@ struct class ieee80211_class = {
|
|||
.dev_release = wiphy_dev_release,
|
||||
.dev_attrs = ieee80211_dev_attrs,
|
||||
.dev_uevent = wiphy_uevent,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = wiphy_suspend,
|
||||
.resume = wiphy_resume,
|
||||
#endif
|
||||
.ns_type = &net_ns_type_operations,
|
||||
.namespace = wiphy_namespace,
|
||||
};
|
||||
|
|
|
@ -1911,12 +1911,12 @@ TRACE_EVENT(cfg80211_send_rx_assoc,
|
|||
NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(netdev_evt_only, __cfg80211_send_deauth,
|
||||
DEFINE_EVENT(netdev_evt_only, cfg80211_send_deauth,
|
||||
TP_PROTO(struct net_device *netdev),
|
||||
TP_ARGS(netdev)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(netdev_evt_only, __cfg80211_send_disassoc,
|
||||
DEFINE_EVENT(netdev_evt_only, cfg80211_send_disassoc,
|
||||
TP_PROTO(struct net_device *netdev),
|
||||
TP_ARGS(netdev)
|
||||
);
|
||||
|
@ -2441,6 +2441,7 @@ TRACE_EVENT(cfg80211_report_wowlan_wakeup,
|
|||
TP_STRUCT__entry(
|
||||
WIPHY_ENTRY
|
||||
WDEV_ENTRY
|
||||
__field(bool, non_wireless)
|
||||
__field(bool, disconnect)
|
||||
__field(bool, magic_pkt)
|
||||
__field(bool, gtk_rekey_failure)
|
||||
|
@ -2449,20 +2450,22 @@ TRACE_EVENT(cfg80211_report_wowlan_wakeup,
|
|||
__field(bool, rfkill_release)
|
||||
__field(s32, pattern_idx)
|
||||
__field(u32, packet_len)
|
||||
__dynamic_array(u8, packet, wakeup->packet_present_len)
|
||||
__dynamic_array(u8, packet,
|
||||
wakeup ? wakeup->packet_present_len : 0)
|
||||
),
|
||||
TP_fast_assign(
|
||||
WIPHY_ASSIGN;
|
||||
WDEV_ASSIGN;
|
||||
__entry->disconnect = wakeup->disconnect;
|
||||
__entry->magic_pkt = wakeup->magic_pkt;
|
||||
__entry->gtk_rekey_failure = wakeup->gtk_rekey_failure;
|
||||
__entry->eap_identity_req = wakeup->eap_identity_req;
|
||||
__entry->four_way_handshake = wakeup->four_way_handshake;
|
||||
__entry->rfkill_release = wakeup->rfkill_release;
|
||||
__entry->pattern_idx = wakeup->pattern_idx;
|
||||
__entry->packet_len = wakeup->packet_len;
|
||||
if (wakeup->packet && wakeup->packet_present_len)
|
||||
__entry->non_wireless = !wakeup;
|
||||
__entry->disconnect = wakeup ? wakeup->disconnect : false;
|
||||
__entry->magic_pkt = wakeup ? wakeup->magic_pkt : false;
|
||||
__entry->gtk_rekey_failure = wakeup ? wakeup->gtk_rekey_failure : false;
|
||||
__entry->eap_identity_req = wakeup ? wakeup->eap_identity_req : false;
|
||||
__entry->four_way_handshake = wakeup ? wakeup->four_way_handshake : false;
|
||||
__entry->rfkill_release = wakeup ? wakeup->rfkill_release : false;
|
||||
__entry->pattern_idx = wakeup ? wakeup->pattern_idx : false;
|
||||
__entry->packet_len = wakeup ? wakeup->packet_len : false;
|
||||
if (wakeup && wakeup->packet && wakeup->packet_present_len)
|
||||
memcpy(__get_dynamic_array(packet), wakeup->packet,
|
||||
wakeup->packet_present_len);
|
||||
),
|
||||
|
|
|
@ -33,6 +33,29 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
|
|||
}
|
||||
EXPORT_SYMBOL(ieee80211_get_response_rate);
|
||||
|
||||
u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband)
|
||||
{
|
||||
struct ieee80211_rate *bitrates;
|
||||
u32 mandatory_rates = 0;
|
||||
enum ieee80211_rate_flags mandatory_flag;
|
||||
int i;
|
||||
|
||||
if (WARN_ON(!sband))
|
||||
return 1;
|
||||
|
||||
if (sband->band == IEEE80211_BAND_2GHZ)
|
||||
mandatory_flag = IEEE80211_RATE_MANDATORY_B;
|
||||
else
|
||||
mandatory_flag = IEEE80211_RATE_MANDATORY_A;
|
||||
|
||||
bitrates = sband->bitrates;
|
||||
for (i = 0; i < sband->n_bitrates; i++)
|
||||
if (bitrates[i].flags & mandatory_flag)
|
||||
mandatory_rates |= BIT(i);
|
||||
return mandatory_rates;
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_mandatory_rates);
|
||||
|
||||
int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band)
|
||||
{
|
||||
/* see 802.11 17.3.8.3.2 and Annex J
|
||||
|
@ -785,12 +808,8 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev)
|
|||
ASSERT_RTNL();
|
||||
ASSERT_RDEV_LOCK(rdev);
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
|
||||
list_for_each_entry(wdev, &rdev->wdev_list, list)
|
||||
cfg80211_process_wdev_events(wdev);
|
||||
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
}
|
||||
|
||||
int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
||||
|
@ -822,10 +841,8 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
|||
return -EBUSY;
|
||||
|
||||
if (ntype != otype && netif_running(dev)) {
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr,
|
||||
ntype);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -841,8 +858,10 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
|||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
wdev_lock(dev->ieee80211_ptr);
|
||||
cfg80211_disconnect(rdev, dev,
|
||||
WLAN_REASON_DEAUTH_LEAVING, true);
|
||||
wdev_unlock(dev->ieee80211_ptr);
|
||||
break;
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
/* mesh should be handled? */
|
||||
|
@ -1169,6 +1188,9 @@ bool ieee80211_operating_class_to_band(u8 operating_class,
|
|||
case 84:
|
||||
*band = IEEE80211_BAND_2GHZ;
|
||||
return true;
|
||||
case 180:
|
||||
*band = IEEE80211_BAND_60GHZ;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -1184,8 +1206,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
|
|||
if (!beacon_int)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
|
||||
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
||||
if (!wdev->beacon_interval)
|
||||
continue;
|
||||
|
@ -1195,8 +1215,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
|
|||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1220,7 +1238,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
|
|||
int i, j;
|
||||
|
||||
ASSERT_RTNL();
|
||||
lockdep_assert_held(&rdev->devlist_mtx);
|
||||
|
||||
if (WARN_ON(hweight32(radar_detect) > 1))
|
||||
return -EINVAL;
|
||||
|
|
|
@ -72,7 +72,6 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
|
|||
struct cfg80211_registered_device *rdev;
|
||||
struct vif_params vifparams;
|
||||
enum nl80211_iftype type;
|
||||
int ret;
|
||||
|
||||
rdev = wiphy_to_dev(wdev->wiphy);
|
||||
|
||||
|
@ -98,11 +97,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
|
|||
|
||||
memset(&vifparams, 0, sizeof(vifparams));
|
||||
|
||||
cfg80211_lock_rdev(rdev);
|
||||
ret = cfg80211_change_iface(rdev, dev, type, NULL, &vifparams);
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
|
||||
return ret;
|
||||
return cfg80211_change_iface(rdev, dev, type, NULL, &vifparams);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode);
|
||||
|
||||
|
@ -579,13 +574,10 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
|
|||
{
|
||||
int err;
|
||||
|
||||
/* devlist mutex needed for possible IBSS re-join */
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
wdev_lock(dev->ieee80211_ptr);
|
||||
err = __cfg80211_set_encryption(rdev, dev, pairwise, addr,
|
||||
remove, tx_key, idx, params);
|
||||
wdev_unlock(dev->ieee80211_ptr);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -787,7 +779,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
|
|||
struct cfg80211_chan_def chandef = {
|
||||
.width = NL80211_CHAN_WIDTH_20_NOHT,
|
||||
};
|
||||
int freq, err;
|
||||
int freq;
|
||||
|
||||
switch (wdev->iftype) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
|
@ -804,10 +796,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
|
|||
chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
|
||||
if (!chandef.chan)
|
||||
return -EINVAL;
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
err = cfg80211_set_monitor_channel(rdev, &chandef);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
return err;
|
||||
return cfg80211_set_monitor_channel(rdev, &chandef);
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
|
||||
if (freq < 0)
|
||||
|
@ -818,10 +807,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
|
|||
chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
|
||||
if (!chandef.chan)
|
||||
return -EINVAL;
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
err = cfg80211_set_mesh_channel(rdev, wdev, &chandef);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
return err;
|
||||
return cfg80211_set_mesh_channel(rdev, wdev, &chandef);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
|
|
@ -54,8 +54,8 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
|
|||
if (wdev->wext.prev_bssid_valid)
|
||||
prev_bssid = wdev->wext.prev_bssid;
|
||||
|
||||
err = __cfg80211_connect(rdev, wdev->netdev,
|
||||
&wdev->wext.connect, ck, prev_bssid);
|
||||
err = cfg80211_connect(rdev, wdev->netdev,
|
||||
&wdev->wext.connect, ck, prev_bssid);
|
||||
if (err)
|
||||
kfree(ck);
|
||||
|
||||
|
@ -87,9 +87,6 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
cfg80211_lock_rdev(rdev);
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
wdev_lock(wdev);
|
||||
|
||||
if (wdev->sme_state != CFG80211_SME_IDLE) {
|
||||
|
@ -103,8 +100,8 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
|
|||
/* if SSID set, we'll try right again, avoid event */
|
||||
if (wdev->wext.connect.ssid_len)
|
||||
event = false;
|
||||
err = __cfg80211_disconnect(rdev, dev,
|
||||
WLAN_REASON_DEAUTH_LEAVING, event);
|
||||
err = cfg80211_disconnect(rdev, dev,
|
||||
WLAN_REASON_DEAUTH_LEAVING, event);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
@ -136,9 +133,6 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
|
|||
err = cfg80211_mgd_wext_connect(rdev, wdev);
|
||||
out:
|
||||
wdev_unlock(wdev);
|
||||
mutex_unlock(&rdev->sched_scan_mtx);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -190,9 +184,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
|
|||
if (len > 0 && ssid[len - 1] == '\0')
|
||||
len--;
|
||||
|
||||
cfg80211_lock_rdev(rdev);
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
wdev_lock(wdev);
|
||||
|
||||
err = 0;
|
||||
|
@ -208,8 +199,8 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
|
|||
/* if SSID set now, we'll try to connect, avoid event */
|
||||
if (len)
|
||||
event = false;
|
||||
err = __cfg80211_disconnect(rdev, dev,
|
||||
WLAN_REASON_DEAUTH_LEAVING, event);
|
||||
err = cfg80211_disconnect(rdev, dev,
|
||||
WLAN_REASON_DEAUTH_LEAVING, event);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
@ -226,9 +217,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
|
|||
err = cfg80211_mgd_wext_connect(rdev, wdev);
|
||||
out:
|
||||
wdev_unlock(wdev);
|
||||
mutex_unlock(&rdev->sched_scan_mtx);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -287,9 +275,6 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
|
|||
if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))
|
||||
bssid = NULL;
|
||||
|
||||
cfg80211_lock_rdev(rdev);
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
mutex_lock(&rdev->sched_scan_mtx);
|
||||
wdev_lock(wdev);
|
||||
|
||||
if (wdev->sme_state != CFG80211_SME_IDLE) {
|
||||
|
@ -303,8 +288,8 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
|
|||
ether_addr_equal(bssid, wdev->wext.connect.bssid))
|
||||
goto out;
|
||||
|
||||
err = __cfg80211_disconnect(rdev, dev,
|
||||
WLAN_REASON_DEAUTH_LEAVING, false);
|
||||
err = cfg80211_disconnect(rdev, dev,
|
||||
WLAN_REASON_DEAUTH_LEAVING, false);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
@ -318,9 +303,6 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
|
|||
err = cfg80211_mgd_wext_connect(rdev, wdev);
|
||||
out:
|
||||
wdev_unlock(wdev);
|
||||
mutex_unlock(&rdev->sched_scan_mtx);
|
||||
mutex_unlock(&rdev->devlist_mtx);
|
||||
cfg80211_unlock_rdev(rdev);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -383,8 +365,8 @@ int cfg80211_wext_siwgenie(struct net_device *dev,
|
|||
wdev->wext.ie_len = ie_len;
|
||||
|
||||
if (wdev->sme_state != CFG80211_SME_IDLE) {
|
||||
err = __cfg80211_disconnect(rdev, dev,
|
||||
WLAN_REASON_DEAUTH_LEAVING, false);
|
||||
err = cfg80211_disconnect(rdev, dev,
|
||||
WLAN_REASON_DEAUTH_LEAVING, false);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
@ -420,8 +402,7 @@ int cfg80211_wext_siwmlme(struct net_device *dev,
|
|||
switch (mlme->cmd) {
|
||||
case IW_MLME_DEAUTH:
|
||||
case IW_MLME_DISASSOC:
|
||||
err = __cfg80211_disconnect(rdev, dev, mlme->reason_code,
|
||||
true);
|
||||
err = cfg80211_disconnect(rdev, dev, mlme->reason_code, true);
|
||||
break;
|
||||
default:
|
||||
err = -EOPNOTSUPP;
|
||||
|
|
Loading…
Reference in New Issue