Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
9b4e9e75
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
9b4e9e75
编写于
9月 24, 2012
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-john' of
git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
上级
7a5f799b
9385d04f
变更
22
隐藏空白更改
内联
并排
Showing
22 changed file
with
429 addition
and
334 deletion
+429
-334
drivers/net/wireless/ath/ath5k/mac80211-ops.c
drivers/net/wireless/ath/ath5k/mac80211-ops.c
+1
-1
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
+1
-1
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/main.c
+1
-1
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mac80211_hwsim.c
+1
-4
include/linux/ieee80211.h
include/linux/ieee80211.h
+0
-80
include/net/mac80211.h
include/net/mac80211.h
+10
-2
net/mac80211/cfg.c
net/mac80211/cfg.c
+32
-2
net/mac80211/chan.c
net/mac80211/chan.c
+48
-19
net/mac80211/ibss.c
net/mac80211/ibss.c
+32
-1
net/mac80211/ieee80211_i.h
net/mac80211/ieee80211_i.h
+7
-16
net/mac80211/iface.c
net/mac80211/iface.c
+12
-3
net/mac80211/key.c
net/mac80211/key.c
+1
-1
net/mac80211/main.c
net/mac80211/main.c
+3
-7
net/mac80211/mesh_plink.c
net/mac80211/mesh_plink.c
+2
-1
net/mac80211/mlme.c
net/mac80211/mlme.c
+115
-90
net/mac80211/offchannel.c
net/mac80211/offchannel.c
+1
-2
net/mac80211/scan.c
net/mac80211/scan.c
+15
-26
net/mac80211/sta_info.c
net/mac80211/sta_info.c
+67
-54
net/mac80211/sta_info.h
net/mac80211/sta_info.h
+2
-0
net/mac80211/status.c
net/mac80211/status.c
+30
-18
net/mac80211/tx.c
net/mac80211/tx.c
+1
-1
net/mac80211/util.c
net/mac80211/util.c
+47
-4
未找到文件。
drivers/net/wireless/ath/ath5k/mac80211-ops.c
浏览文件 @
9b4e9e75
...
...
@@ -523,7 +523,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if
(
key
->
cipher
==
WLAN_CIPHER_SUITE_TKIP
)
key
->
flags
|=
IEEE80211_KEY_FLAG_GENERATE_MMIC
;
if
(
key
->
cipher
==
WLAN_CIPHER_SUITE_CCMP
)
key
->
flags
|=
IEEE80211_KEY_FLAG_SW_MGMT
;
key
->
flags
|=
IEEE80211_KEY_FLAG_SW_MGMT
_TX
;
ret
=
0
;
}
break
;
...
...
drivers/net/wireless/ath/ath9k/htc_drv_main.c
浏览文件 @
9b4e9e75
...
...
@@ -1445,7 +1445,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw,
key
->
flags
|=
IEEE80211_KEY_FLAG_GENERATE_MMIC
;
if
(
priv
->
ah
->
sw_mgmt_crypto
&&
key
->
cipher
==
WLAN_CIPHER_SUITE_CCMP
)
key
->
flags
|=
IEEE80211_KEY_FLAG_SW_MGMT
;
key
->
flags
|=
IEEE80211_KEY_FLAG_SW_MGMT
_TX
;
ret
=
0
;
}
break
;
...
...
drivers/net/wireless/ath/ath9k/main.c
浏览文件 @
9b4e9e75
...
...
@@ -1406,7 +1406,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
key
->
flags
|=
IEEE80211_KEY_FLAG_GENERATE_MMIC
;
if
(
sc
->
sc_ah
->
sw_mgmt_crypto
&&
key
->
cipher
==
WLAN_CIPHER_SUITE_CCMP
)
key
->
flags
|=
IEEE80211_KEY_FLAG_SW_MGMT
;
key
->
flags
|=
IEEE80211_KEY_FLAG_SW_MGMT
_TX
;
ret
=
0
;
}
break
;
...
...
drivers/net/wireless/mac80211_hwsim.c
浏览文件 @
9b4e9e75
...
...
@@ -2056,7 +2056,7 @@ static int __init init_mac80211_hwsim(void)
mac80211_hwsim_free
();
return
err
;
}
module_init
(
init_mac80211_hwsim
);
static
void
__exit
exit_mac80211_hwsim
(
void
)
{
...
...
@@ -2067,7 +2067,4 @@ static void __exit exit_mac80211_hwsim(void)
mac80211_hwsim_free
();
unregister_netdev
(
hwsim_mon
);
}
module_init
(
init_mac80211_hwsim
);
module_exit
(
exit_mac80211_hwsim
);
include/linux/ieee80211.h
浏览文件 @
9b4e9e75
...
...
@@ -1934,36 +1934,6 @@ static inline bool ieee80211_is_public_action(struct ieee80211_hdr *hdr,
return
mgmt
->
u
.
action
.
category
==
WLAN_CATEGORY_PUBLIC
;
}
/**
* ieee80211_fhss_chan_to_freq - get channel frequency
* @channel: the FHSS channel
*
* Convert IEEE802.11 FHSS channel to frequency (MHz)
* Ref IEEE 802.11-2007 section 14.6
*/
static
inline
int
ieee80211_fhss_chan_to_freq
(
int
channel
)
{
if
((
channel
>
1
)
&&
(
channel
<
96
))
return
channel
+
2400
;
else
return
-
1
;
}
/**
* ieee80211_freq_to_fhss_chan - get channel
* @freq: the channels frequency
*
* Convert frequency (MHz) to IEEE802.11 FHSS channel
* Ref IEEE 802.11-2007 section 14.6
*/
static
inline
int
ieee80211_freq_to_fhss_chan
(
int
freq
)
{
if
((
freq
>
2401
)
&&
(
freq
<
2496
))
return
freq
-
2400
;
else
return
-
1
;
}
/**
* ieee80211_dsss_chan_to_freq - get channel center frequency
* @channel: the DSSS channel
...
...
@@ -2000,56 +1970,6 @@ static inline int ieee80211_freq_to_dsss_chan(int freq)
return
-
1
;
}
/* Convert IEEE802.11 HR DSSS channel to frequency (MHz) and back
* Ref IEEE 802.11-2007 section 18.4.6.2
*
* The channels and frequencies are the same as those defined for DSSS
*/
#define ieee80211_hr_chan_to_freq(chan) ieee80211_dsss_chan_to_freq(chan)
#define ieee80211_freq_to_hr_chan(freq) ieee80211_freq_to_dsss_chan(freq)
/* Convert IEEE802.11 ERP channel to frequency (MHz) and back
* Ref IEEE 802.11-2007 section 19.4.2
*/
#define ieee80211_erp_chan_to_freq(chan) ieee80211_hr_chan_to_freq(chan)
#define ieee80211_freq_to_erp_chan(freq) ieee80211_freq_to_hr_chan(freq)
/**
* ieee80211_ofdm_chan_to_freq - get channel center frequency
* @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz
* @channel: the OFDM channel
*
* Convert IEEE802.11 OFDM channel to center frequency (MHz)
* Ref IEEE 802.11-2007 section 17.3.8.3.2
*/
static
inline
int
ieee80211_ofdm_chan_to_freq
(
int
s_freq
,
int
channel
)
{
if
((
channel
>
0
)
&&
(
channel
<=
200
)
&&
(
s_freq
>=
4000
))
return
s_freq
+
(
channel
*
5
);
else
return
-
1
;
}
/**
* ieee80211_freq_to_ofdm_channel - get channel
* @s_freq: starting frequency == (dotChannelStartingFactor/2) MHz
* @freq: the frequency
*
* Convert frequency (MHz) to IEEE802.11 OFDM channel
* Ref IEEE 802.11-2007 section 17.3.8.3.2
*
* This routine selects the channel with the closest center frequency.
*/
static
inline
int
ieee80211_freq_to_ofdm_chan
(
int
s_freq
,
int
freq
)
{
if
((
freq
>
(
s_freq
+
2
))
&&
(
freq
<=
(
s_freq
+
1202
))
&&
(
s_freq
>=
4000
))
return
(
freq
+
2
-
s_freq
)
/
5
;
else
return
-
1
;
}
/**
* ieee80211_tu_to_usec - convert time units (TU) to microseconds
* @tu: the TUs
...
...
include/net/mac80211.h
浏览文件 @
9b4e9e75
...
...
@@ -973,21 +973,29 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
* generation in software.
* @IEEE80211_KEY_FLAG_PAIRWISE: Set by mac80211, this flag indicates
* that the key is pairwise rather then a shared key.
* @IEEE80211_KEY_FLAG_SW_MGMT: This flag should be set by the driver for a
* @IEEE80211_KEY_FLAG_SW_MGMT
_TX
: This flag should be set by the driver for a
* CCMP key if it requires CCMP encryption of management frames (MFP) to
* be done in software.
* @IEEE80211_KEY_FLAG_PUT_IV_SPACE: This flag should be set by the driver
* if space should be prepared for the IV, but the IV
* itself should not be generated. Do not set together with
* @IEEE80211_KEY_FLAG_GENERATE_IV on the same key.
* @IEEE80211_KEY_FLAG_RX_MGMT: This key will be used to decrypt received
* management frames. The flag can help drivers that have a hardware
* crypto implementation that doesn't deal with management frames
* properly by allowing them to not upload the keys to hardware and
* fall back to software crypto. Note that this flag deals only with
* RX, if your crypto engine can't deal with TX you can also set the
* %IEEE80211_KEY_FLAG_SW_MGMT_TX flag to encrypt such frames in SW.
*/
enum
ieee80211_key_flags
{
IEEE80211_KEY_FLAG_WMM_STA
=
1
<<
0
,
IEEE80211_KEY_FLAG_GENERATE_IV
=
1
<<
1
,
IEEE80211_KEY_FLAG_GENERATE_MMIC
=
1
<<
2
,
IEEE80211_KEY_FLAG_PAIRWISE
=
1
<<
3
,
IEEE80211_KEY_FLAG_SW_MGMT
=
1
<<
4
,
IEEE80211_KEY_FLAG_SW_MGMT
_TX
=
1
<<
4
,
IEEE80211_KEY_FLAG_PUT_IV_SPACE
=
1
<<
5
,
IEEE80211_KEY_FLAG_RX_MGMT
=
1
<<
6
,
};
/**
...
...
net/mac80211/cfg.c
浏览文件 @
9b4e9e75
...
...
@@ -170,6 +170,38 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
}
}
switch
(
sdata
->
vif
.
type
)
{
case
NL80211_IFTYPE_STATION
:
if
(
sdata
->
u
.
mgd
.
mfp
!=
IEEE80211_MFP_DISABLED
)
key
->
conf
.
flags
|=
IEEE80211_KEY_FLAG_RX_MGMT
;
break
;
case
NL80211_IFTYPE_AP
:
case
NL80211_IFTYPE_AP_VLAN
:
/* Keys without a station are used for TX only */
if
(
key
->
sta
&&
test_sta_flag
(
key
->
sta
,
WLAN_STA_MFP
))
key
->
conf
.
flags
|=
IEEE80211_KEY_FLAG_RX_MGMT
;
break
;
case
NL80211_IFTYPE_ADHOC
:
/* no MFP (yet) */
break
;
case
NL80211_IFTYPE_MESH_POINT
:
#ifdef CONFIG_MAC80211_MESH
if
(
sdata
->
u
.
mesh
.
security
!=
IEEE80211_MESH_SEC_NONE
)
key
->
conf
.
flags
|=
IEEE80211_KEY_FLAG_RX_MGMT
;
break
;
#endif
case
NL80211_IFTYPE_WDS
:
case
NL80211_IFTYPE_MONITOR
:
case
NL80211_IFTYPE_P2P_DEVICE
:
case
NL80211_IFTYPE_UNSPECIFIED
:
case
NUM_NL80211_IFTYPES
:
case
NL80211_IFTYPE_P2P_CLIENT
:
case
NL80211_IFTYPE_P2P_GO
:
/* shouldn't happen */
WARN_ON_ONCE
(
1
);
break
;
}
err
=
ieee80211_key_link
(
key
,
sdata
,
sta
);
if
(
err
)
ieee80211_key_free
(
sdata
->
local
,
key
);
...
...
@@ -2038,9 +2070,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
*/
if
(
!
sdata
->
u
.
mgd
.
associated
||
sdata
->
vif
.
bss_conf
.
channel_type
==
NL80211_CHAN_NO_HT
)
{
mutex_lock
(
&
sdata
->
local
->
iflist_mtx
);
ieee80211_recalc_smps
(
sdata
->
local
);
mutex_unlock
(
&
sdata
->
local
->
iflist_mtx
);
return
0
;
}
...
...
net/mac80211/chan.c
浏览文件 @
9b4e9e75
...
...
@@ -68,16 +68,14 @@ ieee80211_get_channel_mode(struct ieee80211_local *local,
return
mode
;
}
bool
ieee80211_set_channel_type
(
struct
ieee80211_local
*
local
,
struct
ieee80211_sub_if_data
*
sdata
,
enum
nl80211_channel_type
chantype
)
static
enum
nl80211_channel_type
ieee80211_get_superchan
(
struct
ieee80211_local
*
local
,
struct
ieee80211_sub_if_data
*
sdata
)
{
struct
ieee80211_sub_if_data
*
tmp
;
enum
nl80211_channel_type
superchan
=
NL80211_CHAN_NO_HT
;
bool
result
;
struct
ieee80211_sub_if_data
*
tmp
;
mutex_lock
(
&
local
->
iflist_mtx
);
list_for_each_entry
(
tmp
,
&
local
->
interfaces
,
list
)
{
if
(
tmp
==
sdata
)
continue
;
...
...
@@ -103,39 +101,70 @@ bool ieee80211_set_channel_type(struct ieee80211_local *local,
break
;
}
}
mutex_unlock
(
&
local
->
iflist_mtx
);
switch
(
superchan
)
{
return
superchan
;
}
static
bool
ieee80211_channel_types_are_compatible
(
enum
nl80211_channel_type
chantype1
,
enum
nl80211_channel_type
chantype2
,
enum
nl80211_channel_type
*
compat
)
{
/*
* start out with chantype1 being the result,
* overwriting later if needed
*/
if
(
compat
)
*
compat
=
chantype1
;
switch
(
chantype1
)
{
case
NL80211_CHAN_NO_HT
:
if
(
compat
)
*
compat
=
chantype2
;
break
;
case
NL80211_CHAN_HT20
:
/*
* allow any change that doesn't go to no-HT
* (if it already is no-HT no change is needed)
*/
if
(
chantype
==
NL80211_CHAN_NO_HT
)
if
(
chantype
2
==
NL80211_CHAN_NO_HT
)
break
;
superchan
=
chantype
;
if
(
compat
)
*
compat
=
chantype2
;
break
;
case
NL80211_CHAN_HT40PLUS
:
case
NL80211_CHAN_HT40MINUS
:
/* allow smaller bandwidth and same */
if
(
chantype
==
NL80211_CHAN_NO_HT
)
if
(
chantype
2
==
NL80211_CHAN_NO_HT
)
break
;
if
(
chantype
==
NL80211_CHAN_HT20
)
if
(
chantype
2
==
NL80211_CHAN_HT20
)
break
;
if
(
superchan
==
chantype
)
if
(
chantype2
==
chantype1
)
break
;
result
=
false
;
goto
out
;
return
false
;
}
local
->
_oper_channel_type
=
superchan
;
return
true
;
}
bool
ieee80211_set_channel_type
(
struct
ieee80211_local
*
local
,
struct
ieee80211_sub_if_data
*
sdata
,
enum
nl80211_channel_type
chantype
)
{
enum
nl80211_channel_type
superchan
;
enum
nl80211_channel_type
compatchan
;
superchan
=
ieee80211_get_superchan
(
local
,
sdata
);
if
(
!
ieee80211_channel_types_are_compatible
(
superchan
,
chantype
,
&
compatchan
))
return
false
;
local
->
_oper_channel_type
=
compatchan
;
if
(
sdata
)
sdata
->
vif
.
bss_conf
.
channel_type
=
chantype
;
result
=
true
;
out:
mutex_unlock
(
&
local
->
iflist_mtx
);
return
true
;
return
result
;
}
net/mac80211/ibss.c
浏览文件 @
9b4e9e75
...
...
@@ -332,11 +332,27 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
return
ieee80211_ibss_finish_sta
(
sta
,
auth
);
}
static
void
ieee80211_rx_mgmt_deauth_ibss
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
ieee80211_mgmt
*
mgmt
,
size_t
len
)
{
u16
reason
=
le16_to_cpu
(
mgmt
->
u
.
deauth
.
reason_code
);
if
(
len
<
IEEE80211_DEAUTH_FRAME_LEN
)
return
;
ibss_dbg
(
sdata
,
"RX DeAuth SA=%pM DA=%pM BSSID=%pM (reason: %d)
\n
"
,
mgmt
->
sa
,
mgmt
->
da
,
mgmt
->
bssid
,
reason
);
sta_info_destroy_addr
(
sdata
,
mgmt
->
sa
);
}
static
void
ieee80211_rx_mgmt_auth_ibss
(
struct
ieee80211_sub_if_data
*
sdata
,
struct
ieee80211_mgmt
*
mgmt
,
size_t
len
)
{
u16
auth_alg
,
auth_transaction
;
struct
sta_info
*
sta
;
u8
deauth_frame_buf
[
IEEE80211_DEAUTH_FRAME_LEN
];
lockdep_assert_held
(
&
sdata
->
u
.
ibss
.
mtx
);
...
...
@@ -352,9 +368,21 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
"RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)
\n
"
,
mgmt
->
sa
,
mgmt
->
da
,
mgmt
->
bssid
,
auth_transaction
);
sta_info_destroy_addr
(
sdata
,
mgmt
->
sa
);
ieee80211_ibss_add_sta
(
sdata
,
mgmt
->
bssid
,
mgmt
->
sa
,
0
,
false
);
sta
=
ieee80211_ibss_add_sta
(
sdata
,
mgmt
->
bssid
,
mgmt
->
sa
,
0
,
false
);
rcu_read_unlock
();
/*
* if we have any problem in allocating the new station, we reply with a
* DEAUTH frame to tell the other end that we had a problem
*/
if
(
!
sta
)
{
ieee80211_send_deauth_disassoc
(
sdata
,
sdata
->
u
.
ibss
.
bssid
,
IEEE80211_STYPE_DEAUTH
,
WLAN_REASON_UNSPECIFIED
,
true
,
deauth_frame_buf
);
return
;
}
/*
* IEEE 802.11 standard does not require authentication in IBSS
* networks and most implementations do not seem to use it.
...
...
@@ -902,6 +930,9 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
case
IEEE80211_STYPE_AUTH
:
ieee80211_rx_mgmt_auth_ibss
(
sdata
,
mgmt
,
skb
->
len
);
break
;
case
IEEE80211_STYPE_DEAUTH
:
ieee80211_rx_mgmt_deauth_ibss
(
sdata
,
mgmt
,
skb
->
len
);
break
;
}
mgmt_out:
...
...
net/mac80211/ieee80211_i.h
浏览文件 @
9b4e9e75
...
...
@@ -68,6 +68,8 @@ struct ieee80211_local;
#define IEEE80211_DEFAULT_MAX_SP_LEN \
IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL
#define IEEE80211_DEAUTH_FRAME_LEN (24
/* hdr */
+ 2
/* reason */
)
struct
ieee80211_fragment_entry
{
unsigned
long
first_frag_time
;
unsigned
int
seq
;
...
...
@@ -411,6 +413,7 @@ struct ieee80211_if_managed {
struct
work_struct
monitor_work
;
struct
work_struct
chswitch_work
;
struct
work_struct
beacon_connection_loss_work
;
struct
work_struct
csa_connection_drop_work
;
unsigned
long
beacon_timeout
;
unsigned
long
probe_timeout
;
...
...
@@ -970,7 +973,6 @@ struct ieee80211_local {
int
scan_channel_idx
;
int
scan_ies_len
;
struct
ieee80211_sched_scan_ies
sched_scan_ies
;
struct
work_struct
sched_scan_stopped_work
;
struct
ieee80211_sub_if_data
__rcu
*
sched_scan_sdata
;
...
...
@@ -1057,7 +1059,7 @@ struct ieee80211_local {
bool
disable_dynamic_ps
;
int
user_power_level
;
/* in dBm */
int
power_const
r_level
;
/* in dBm */
int
ap_powe
r_level
;
/* in dBm */
enum
ieee80211_smps_mode
smps_mode
;
...
...
@@ -1165,7 +1167,6 @@ struct ieee802_11_elems {
u8
prep_len
;
u8
perr_len
;
u8
country_elem_len
;
u8
pwr_constr_elem_len
;
u8
quiet_elem_len
;
u8
num_of_quiet_elem
;
/* can be more the one */
u8
timeout_int_len
;
...
...
@@ -1367,7 +1368,6 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
int
ieee80211_reconfig
(
struct
ieee80211_local
*
local
);
void
ieee80211_stop_device
(
struct
ieee80211_local
*
local
);
#ifdef CONFIG_PM
int
__ieee80211_suspend
(
struct
ieee80211_hw
*
hw
,
struct
cfg80211_wowlan
*
wowlan
);
...
...
@@ -1381,18 +1381,6 @@ static inline int __ieee80211_resume(struct ieee80211_hw *hw)
return
ieee80211_reconfig
(
hw_to_local
(
hw
));
}
#else
static
inline
int
__ieee80211_suspend
(
struct
ieee80211_hw
*
hw
,
struct
cfg80211_wowlan
*
wowlan
)
{
return
0
;
}
static
inline
int
__ieee80211_resume
(
struct
ieee80211_hw
*
hw
)
{
return
0
;
}
#endif
/* utility functions/constants */
extern
void
*
mac80211_wiphy_privid
;
/* for wiphy privid */
...
...
@@ -1459,6 +1447,9 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
u16
transaction
,
u16
auth_alg
,
u8
*
extra
,
size_t
extra_len
,
const
u8
*
bssid
,
const
u8
*
da
,
const
u8
*
key
,
u8
key_len
,
u8
key_idx
);
void
ieee80211_send_deauth_disassoc
(
struct
ieee80211_sub_if_data
*
sdata
,
const
u8
*
bssid
,
u16
stype
,
u16
reason
,
bool
send_frame
,
u8
*
frame_buf
);
int
ieee80211_build_preq_ies
(
struct
ieee80211_local
*
local
,
u8
*
buffer
,
const
u8
*
ie
,
size_t
ie_len
,
enum
ieee80211_band
band
,
u32
rate_mask
,
...
...
net/mac80211/iface.c
浏览文件 @
9b4e9e75
...
...
@@ -793,11 +793,20 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
flush_work
(
&
sdata
->
work
);
/*
* When we get here, the interface is marked down.
* Call
synchronize_rcu() to wait
for the RX path
* Call
rcu_barrier() to wait both
for the RX path
* should it be using the interface and enqueuing
* frames at this very time on another CPU.
* frames at this very time on another CPU, and
* for the sta free call_rcu callbacks.
*/
synchronize_rcu
();
rcu_barrier
();
/*
* free_sta_rcu() enqueues a work for the actual
* sta cleanup, so we need to flush it while
* sdata is still valid.
*/
flush_workqueue
(
local
->
workqueue
);
skb_queue_purge
(
&
sdata
->
skb_queue
);
/*
...
...
net/mac80211/key.c
浏览文件 @
9b4e9e75
...
...
@@ -402,7 +402,7 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key)
* Synchronize so the TX path can no longer be using
* this key before we free/remove it.
*/
synchronize_
rcu
();
synchronize_
net
();
if
(
key
->
local
)
ieee80211_key_disable_hw_accel
(
key
);
...
...
net/mac80211/main.c
浏览文件 @
9b4e9e75
...
...
@@ -150,13 +150,11 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
if
(
test_bit
(
SCAN_SW_SCANNING
,
&
local
->
scanning
)
||
test_bit
(
SCAN_ONCHANNEL_SCANNING
,
&
local
->
scanning
)
||
test_bit
(
SCAN_HW_SCANNING
,
&
local
->
scanning
))
test_bit
(
SCAN_HW_SCANNING
,
&
local
->
scanning
)
||
!
local
->
ap_power_level
)
power
=
chan
->
max_power
;
else
power
=
local
->
power_constr_level
?
min
(
chan
->
max_power
,
(
chan
->
max_reg_power
-
local
->
power_constr_level
))
:
chan
->
max_power
;
power
=
min
(
chan
->
max_power
,
local
->
ap_power_level
);
if
(
local
->
user_power_level
>=
0
)
power
=
min
(
power
,
local
->
user_power_level
);
...
...
@@ -366,9 +364,7 @@ static void ieee80211_recalc_smps_work(struct work_struct *work)
struct
ieee80211_local
*
local
=
container_of
(
work
,
struct
ieee80211_local
,
recalc_smps
);
mutex_lock
(
&
local
->
iflist_mtx
);
ieee80211_recalc_smps
(
local
);
mutex_unlock
(
&
local
->
iflist_mtx
);
}
#ifdef CONFIG_INET
...
...
net/mac80211/mesh_plink.c
浏览文件 @
9b4e9e75
...
...
@@ -537,7 +537,8 @@ int mesh_plink_open(struct sta_info *sta)
spin_lock_bh
(
&
sta
->
lock
);
get_random_bytes
(
&
llid
,
2
);
sta
->
llid
=
llid
;
if
(
sta
->
plink_state
!=
NL80211_PLINK_LISTEN
)
{
if
(
sta
->
plink_state
!=
NL80211_PLINK_LISTEN
&&
sta
->
plink_state
!=
NL80211_PLINK_BLOCKED
)
{
spin_unlock_bh
(
&
sta
->
lock
);
return
-
EBUSY
;
}
...
...
net/mac80211/mlme.c
浏览文件 @
9b4e9e75
...
...
@@ -88,8 +88,6 @@ MODULE_PARM_DESC(probe_wait_ms,
#define TMR_RUNNING_TIMER 0
#define TMR_RUNNING_CHANSW 1
#define DEAUTH_DISASSOC_LEN (24
/* hdr */
+ 2
/* reason */
)
/*
* All cfg80211 functions have to be called outside a locked
* section so that they can acquire a lock themselves... This
...
...
@@ -574,46 +572,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
ieee80211_tx_skb
(
sdata
,
skb
);
}
static
void
ieee80211_send_deauth_disassoc
(
struct
ieee80211_sub_if_data
*
sdata
,
const
u8
*
bssid
,
u16
stype
,
u16
reason
,
bool
send_frame
,
u8
*
frame_buf
)
{
struct
ieee80211_local
*
local
=
sdata
->
local
;
struct
ieee80211_if_managed
*
ifmgd
=
&
sdata
->
u
.
mgd
;
struct
sk_buff
*
skb
;
struct
ieee80211_mgmt
*
mgmt
=
(
void
*
)
frame_buf
;
/* build frame */
mgmt
->
frame_control
=
cpu_to_le16
(
IEEE80211_FTYPE_MGMT
|
stype
);
mgmt
->
duration
=
0
;
/* initialize only */
mgmt
->
seq_ctrl
=
0
;
/* initialize only */
memcpy
(
mgmt
->
da
,
bssid
,
ETH_ALEN
);
memcpy
(
mgmt
->
sa
,
sdata
->
vif
.
addr
,
ETH_ALEN
);
memcpy
(
mgmt
->
bssid
,
bssid
,
ETH_ALEN
);
/* u.deauth.reason_code == u.disassoc.reason_code */
mgmt
->
u
.
deauth
.
reason_code
=
cpu_to_le16
(
reason
);
if
(
send_frame
)
{
skb
=
dev_alloc_skb
(
local
->
hw
.
extra_tx_headroom
+
DEAUTH_DISASSOC_LEN
);
if
(
!
skb
)
return
;
skb_reserve
(
skb
,
local
->
hw
.
extra_tx_headroom
);
/* copy in frame */
memcpy
(
skb_put
(
skb
,
DEAUTH_DISASSOC_LEN
),
mgmt
,
DEAUTH_DISASSOC_LEN
);
if
(
!
(
ifmgd
->
flags
&
IEEE80211_STA_MFP_ENABLED
))
IEEE80211_SKB_CB
(
skb
)
->
flags
|=
IEEE80211_TX_INTFL_DONT_ENCRYPT
;
ieee80211_tx_skb
(
sdata
,
skb
);
}
}
void
ieee80211_send_pspoll
(
struct
ieee80211_local
*
local
,
struct
ieee80211_sub_if_data
*
sdata
)
{
...
...
@@ -730,16 +688,13 @@ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
trace_api_chswitch_done
(
sdata
,
success
);
if
(
!
success
)
{
/*
* If the channel switch was not successful, stay
* around on the old channel. We currently lack
* good handling of this situation, possibly we
* should just drop the association.
*/
sdata
->
local
->
csa_channel
=
sdata
->
local
->
oper_channel
;
sdata_info
(
sdata
,
"driver channel switch failed, disconnecting
\n
"
);
ieee80211_queue_work
(
&
sdata
->
local
->
hw
,
&
ifmgd
->
csa_connection_drop_work
);
}
else
{
ieee80211_queue_work
(
&
sdata
->
local
->
hw
,
&
ifmgd
->
chswitch_work
);
}
ieee80211_queue_work
(
&
sdata
->
local
->
hw
,
&
ifmgd
->
chswitch_work
);
}
EXPORT_SYMBOL
(
ieee80211_chswitch_done
);
...
...
@@ -784,8 +739,14 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
return
;
new_ch
=
ieee80211_get_channel
(
sdata
->
local
->
hw
.
wiphy
,
new_freq
);
if
(
!
new_ch
||
new_ch
->
flags
&
IEEE80211_CHAN_DISABLED
)
if
(
!
new_ch
||
new_ch
->
flags
&
IEEE80211_CHAN_DISABLED
)
{
sdata_info
(
sdata
,
"AP %pM switches to unsupported channel (%d MHz), disconnecting
\n
"
,
ifmgd
->
associated
->
bssid
,
new_freq
);
ieee80211_queue_work
(
&
sdata
->
local
->
hw
,
&
ifmgd
->
csa_connection_drop_work
);
return
;
}
sdata
->
local
->
csa_channel
=
new_ch
;
...
...
@@ -818,23 +779,71 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
}
static
void
ieee80211_handle_pwr_constr
(
struct
ieee80211_sub_if_data
*
sdata
,
u16
capab_info
,
u8
*
pwr_constr_elem
,
u8
pwr_constr_elem_len
)
struct
ieee80211_channel
*
channel
,
const
u8
*
country_ie
,
u8
country_ie_len
,
const
u8
*
pwr_constr_elem
)
{
struct
ieee80211_conf
*
conf
=
&
sdata
->
local
->
hw
.
conf
;
struct
ieee80211_country_ie_triplet
*
triplet
;
int
chan
=
ieee80211_frequency_to_channel
(
channel
->
center_freq
);
int
i
,
chan_pwr
,
chan_increment
,
new_ap_level
;
bool
have_chan_pwr
=
false
;
if
(
!
(
capab_info
&
WLAN_CAPABILITY_SPECTRUM_MGMT
))
/* Invalid IE */
if
(
country_ie_len
%
2
||
country_ie_len
<
IEEE80211_COUNTRY_IE_MIN_LEN
)
return
;
/* Power constraint IE length should be 1 octet */
if
(
pwr_constr_elem_len
!=
1
)
return
;
triplet
=
(
void
*
)(
country_ie
+
3
);
country_ie_len
-=
3
;
if
((
*
pwr_constr_elem
<=
conf
->
channel
->
max_reg_power
)
&&
(
*
pwr_constr_elem
!=
sdata
->
local
->
power_constr_level
))
{
sdata
->
local
->
power_constr_level
=
*
pwr_constr_elem
;
ieee80211_hw_config
(
sdata
->
local
,
0
);
switch
(
channel
->
band
)
{
default:
WARN_ON_ONCE
(
1
);
/* fall through */
case
IEEE80211_BAND_2GHZ
:
case
IEEE80211_BAND_60GHZ
:
chan_increment
=
1
;
break
;
case
IEEE80211_BAND_5GHZ
:
chan_increment
=
4
;
break
;
}
/* find channel */
while
(
country_ie_len
>=
3
)
{
u8
first_channel
=
triplet
->
chans
.
first_channel
;
if
(
first_channel
>=
IEEE80211_COUNTRY_EXTENSION_ID
)
goto
next
;
for
(
i
=
0
;
i
<
triplet
->
chans
.
num_channels
;
i
++
)
{
if
(
first_channel
+
i
*
chan_increment
==
chan
)
{
have_chan_pwr
=
true
;
chan_pwr
=
triplet
->
chans
.
max_power
;
break
;
}
}
if
(
have_chan_pwr
)
break
;
next:
triplet
++
;
country_ie_len
-=
3
;
}
if
(
!
have_chan_pwr
)
return
;
new_ap_level
=
max_t
(
int
,
0
,
chan_pwr
-
*
pwr_constr_elem
);
if
(
sdata
->
local
->
ap_power_level
==
new_ap_level
)
return
;
sdata_info
(
sdata
,
"Limiting TX power to %d (%d - %d) dBm as advertised by %pM
\n
"
,
new_ap_level
,
chan_pwr
,
*
pwr_constr_elem
,
sdata
->
u
.
mgd
.
bssid
);
sdata
->
local
->
ap_power_level
=
new_ap_level
;
ieee80211_hw_config
(
sdata
->
local
,
0
);
}
void
ieee80211_enable_dyn_ps
(
struct
ieee80211_vif
*
vif
)
...
...
@@ -1339,9 +1348,9 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
mutex_lock
(
&
local
->
iflist_mtx
);
ieee80211_recalc_ps
(
local
,
-
1
);
ieee80211_recalc_smps
(
local
);
mutex_unlock
(
&
local
->
iflist_mtx
);
ieee80211_recalc_smps
(
local
);
ieee80211_recalc_ps_vif
(
sdata
);
netif_tx_start_all_queues
(
sdata
->
dev
);
...
...
@@ -1438,7 +1447,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
memset
(
&
ifmgd
->
ht_capa
,
0
,
sizeof
(
ifmgd
->
ht_capa
));
memset
(
&
ifmgd
->
ht_capa_mask
,
0
,
sizeof
(
ifmgd
->
ht_capa_mask
));
local
->
power_const
r_level
=
0
;
local
->
ap_powe
r_level
=
0
;
del_timer_sync
(
&
local
->
dynamic_ps_timer
);
cancel_work_sync
(
&
local
->
dynamic_ps_enable_work
);
...
...
@@ -1692,11 +1701,12 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL
(
ieee80211_ap_probereq_get
);
static
void
__ieee80211_connection_loss
(
struct
ieee80211_sub_if_data
*
sdata
)
static
void
__ieee80211_disconnect
(
struct
ieee80211_sub_if_data
*
sdata
,
bool
transmit_frame
)
{
struct
ieee80211_if_managed
*
ifmgd
=
&
sdata
->
u
.
mgd
;
struct
ieee80211_local
*
local
=
sdata
->
local
;
u8
frame_buf
[
DEAUTH_DISASSOC
_LEN
];
u8
frame_buf
[
IEEE80211_DEAUTH_FRAME
_LEN
];
mutex_lock
(
&
ifmgd
->
mtx
);
if
(
!
ifmgd
->
associated
)
{
...
...
@@ -1704,19 +1714,17 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
return
;
}
sdata_info
(
sdata
,
"Connection to AP %pM lost
\n
"
,
ifmgd
->
associated
->
bssid
);
ieee80211_set_disassoc
(
sdata
,
IEEE80211_STYPE_DEAUTH
,
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY
,
false
,
frame_buf
);
transmit_frame
,
frame_buf
);
ifmgd
->
flags
&=
~
IEEE80211_STA_CSA_RECEIVED
;
mutex_unlock
(
&
ifmgd
->
mtx
);
/*
* must be outside lock due to cfg80211,
* but that's not a problem.
*/
cfg80211_send_deauth
(
sdata
->
dev
,
frame_buf
,
DEAUTH_DISASSOC
_LEN
);
cfg80211_send_deauth
(
sdata
->
dev
,
frame_buf
,
IEEE80211_DEAUTH_FRAME
_LEN
);
mutex_lock
(
&
local
->
mtx
);
ieee80211_recalc_idle
(
local
);
...
...
@@ -1739,10 +1747,24 @@ static void ieee80211_beacon_connection_loss_work(struct work_struct *work)
rcu_read_unlock
();
}
if
(
sdata
->
local
->
hw
.
flags
&
IEEE80211_HW_CONNECTION_MONITOR
)
__ieee80211_connection_loss
(
sdata
);
else
if
(
sdata
->
local
->
hw
.
flags
&
IEEE80211_HW_CONNECTION_MONITOR
)
{
sdata_info
(
sdata
,
"Connection to AP %pM lost
\n
"
,
ifmgd
->
bssid
);
__ieee80211_disconnect
(
sdata
,
false
);
}
else
{
ieee80211_mgd_probe_ap
(
sdata
,
true
);
}
}
static
void
ieee80211_csa_connection_drop_work
(
struct
work_struct
*
work
)
{
struct
ieee80211_sub_if_data
*
sdata
=
container_of
(
work
,
struct
ieee80211_sub_if_data
,
u
.
mgd
.
csa_connection_drop_work
);
ieee80211_wake_queues_by_reason
(
&
sdata
->
local
->
hw
,
IEEE80211_QUEUE_STOP_REASON_CSA
);
__ieee80211_disconnect
(
sdata
,
true
);
}
void
ieee80211_beacon_loss
(
struct
ieee80211_vif
*
vif
)
...
...
@@ -2530,15 +2552,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
bssid
,
true
);
}
/* Note: country IE parsing is done for us by cfg80211 */
if
(
elems
.
country_elem
)
{
/* TODO: IBSS also needs this */
if
(
elems
.
pwr_constr_elem
)
ieee80211_handle_pwr_constr
(
sdata
,
le16_to_cpu
(
mgmt
->
u
.
probe_resp
.
capab_info
),
elems
.
pwr_constr_elem
,
elems
.
pwr_constr_elem_len
);
}
if
(
elems
.
country_elem
&&
elems
.
pwr_constr_elem
&&
mgmt
->
u
.
probe_resp
.
capab_info
&
cpu_to_le16
(
WLAN_CAPABILITY_SPECTRUM_MGMT
))
ieee80211_handle_pwr_constr
(
sdata
,
local
->
oper_channel
,
elems
.
country_elem
,
elems
.
country_elem_len
,
elems
.
pwr_constr_elem
);
ieee80211_bss_info_change_notify
(
sdata
,
changed
);
}
...
...
@@ -2635,7 +2655,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
{
struct
ieee80211_local
*
local
=
sdata
->
local
;
struct
ieee80211_if_managed
*
ifmgd
=
&
sdata
->
u
.
mgd
;
u8
frame_buf
[
DEAUTH_DISASSOC
_LEN
];
u8
frame_buf
[
IEEE80211_DEAUTH_FRAME
_LEN
];
ieee80211_set_disassoc
(
sdata
,
IEEE80211_STYPE_DEAUTH
,
reason
,
false
,
frame_buf
);
...
...
@@ -2645,7 +2665,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
* must be outside lock due to cfg80211,
* but that's not a problem.
*/
cfg80211_send_deauth
(
sdata
->
dev
,
frame_buf
,
DEAUTH_DISASSOC
_LEN
);
cfg80211_send_deauth
(
sdata
->
dev
,
frame_buf
,
IEEE80211_DEAUTH_FRAME
_LEN
);
mutex_lock
(
&
local
->
mtx
);
ieee80211_recalc_idle
(
local
);
...
...
@@ -2929,6 +2949,7 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
cancel_work_sync
(
&
ifmgd
->
monitor_work
);
cancel_work_sync
(
&
ifmgd
->
beacon_connection_loss_work
);
cancel_work_sync
(
&
ifmgd
->
csa_connection_drop_work
);
if
(
del_timer_sync
(
&
ifmgd
->
timer
))
set_bit
(
TMR_RUNNING_TIMER
,
&
ifmgd
->
timers_running
);
...
...
@@ -2985,6 +3006,8 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
INIT_WORK
(
&
ifmgd
->
chswitch_work
,
ieee80211_chswitch_work
);
INIT_WORK
(
&
ifmgd
->
beacon_connection_loss_work
,
ieee80211_beacon_connection_loss_work
);
INIT_WORK
(
&
ifmgd
->
csa_connection_drop_work
,
ieee80211_csa_connection_drop_work
);
INIT_WORK
(
&
ifmgd
->
request_smps_work
,
ieee80211_request_smps_work
);
setup_timer
(
&
ifmgd
->
timer
,
ieee80211_sta_timer
,
(
unsigned
long
)
sdata
);
...
...
@@ -3525,7 +3548,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
struct
cfg80211_deauth_request
*
req
)
{
struct
ieee80211_if_managed
*
ifmgd
=
&
sdata
->
u
.
mgd
;
u8
frame_buf
[
DEAUTH_DISASSOC
_LEN
];
u8
frame_buf
[
IEEE80211_DEAUTH_FRAME
_LEN
];
mutex_lock
(
&
ifmgd
->
mtx
);
...
...
@@ -3553,7 +3576,8 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
mutex_unlock
(
&
ifmgd
->
mtx
);
__cfg80211_send_deauth
(
sdata
->
dev
,
frame_buf
,
DEAUTH_DISASSOC_LEN
);
__cfg80211_send_deauth
(
sdata
->
dev
,
frame_buf
,
IEEE80211_DEAUTH_FRAME_LEN
);
mutex_lock
(
&
sdata
->
local
->
mtx
);
ieee80211_recalc_idle
(
sdata
->
local
);
...
...
@@ -3567,7 +3591,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
{
struct
ieee80211_if_managed
*
ifmgd
=
&
sdata
->
u
.
mgd
;
u8
bssid
[
ETH_ALEN
];
u8
frame_buf
[
DEAUTH_DISASSOC
_LEN
];
u8
frame_buf
[
IEEE80211_DEAUTH_FRAME
_LEN
];
mutex_lock
(
&
ifmgd
->
mtx
);
...
...
@@ -3592,7 +3616,8 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
frame_buf
);
mutex_unlock
(
&
ifmgd
->
mtx
);
__cfg80211_send_disassoc
(
sdata
->
dev
,
frame_buf
,
DEAUTH_DISASSOC_LEN
);
__cfg80211_send_disassoc
(
sdata
->
dev
,
frame_buf
,
IEEE80211_DEAUTH_FRAME_LEN
);
mutex_lock
(
&
sdata
->
local
->
mtx
);
ieee80211_recalc_idle
(
sdata
->
local
);
...
...
net/mac80211/offchannel.c
浏览文件 @
9b4e9e75
...
...
@@ -233,8 +233,7 @@ static void ieee80211_hw_roc_start(struct work_struct *work)
u32
dur
=
dep
->
duration
;
dep
->
duration
=
dur
-
roc
->
duration
;
roc
->
duration
=
dur
;
list_del
(
&
dep
->
list
);
list_add
(
&
dep
->
list
,
&
roc
->
list
);
list_move
(
&
dep
->
list
,
&
roc
->
list
);
}
}
out_unlock:
...
...
net/mac80211/scan.c
浏览文件 @
9b4e9e75
...
...
@@ -407,7 +407,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
enum
ieee80211_band
band
=
local
->
hw
.
conf
.
channel
->
band
;
sdata
=
rcu_dereference_protected
(
local
->
scan_sdata
,
lockdep_is_held
(
&
local
->
mtx
));
;
lockdep_is_held
(
&
local
->
mtx
));
for
(
i
=
0
;
i
<
local
->
scan_req
->
n_ssids
;
i
++
)
ieee80211_send_probe_req
(
...
...
@@ -917,6 +917,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
struct
cfg80211_sched_scan_request
*
req
)
{
struct
ieee80211_local
*
local
=
sdata
->
local
;
struct
ieee80211_sched_scan_ies
sched_scan_ies
;
int
ret
,
i
;
mutex_lock
(
&
local
->
mtx
);
...
...
@@ -935,33 +936,28 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
if
(
!
local
->
hw
.
wiphy
->
bands
[
i
])
continue
;
local
->
sched_scan_ies
.
ie
[
i
]
=
kzalloc
(
2
+
IEEE80211_MAX_SSID_LEN
+
local
->
scan_ies_len
+
req
->
ie_len
,
GFP_KERNEL
);
if
(
!
local
->
sched_scan_ies
.
ie
[
i
])
{
sched_scan_ies
.
ie
[
i
]
=
kzalloc
(
2
+
IEEE80211_MAX_SSID_LEN
+
local
->
scan_ies_len
+
req
->
ie_len
,
GFP_KERNEL
);
if
(
!
sched_scan_ies
.
ie
[
i
])
{
ret
=
-
ENOMEM
;
goto
out_free
;
}
local
->
sched_scan_ies
.
len
[
i
]
=
ieee80211_build_preq_ies
(
local
,
local
->
sched_scan_ies
.
ie
[
i
],
sched_scan_ies
.
len
[
i
]
=
ieee80211_build_preq_ies
(
local
,
sched_scan_ies
.
ie
[
i
],
req
->
ie
,
req
->
ie_len
,
i
,
(
u32
)
-
1
,
0
);
}
ret
=
drv_sched_scan_start
(
local
,
sdata
,
req
,
&
local
->
sched_scan_ies
);
if
(
ret
==
0
)
{
ret
=
drv_sched_scan_start
(
local
,
sdata
,
req
,
&
sched_scan_ies
);
if
(
ret
==
0
)
rcu_assign_pointer
(
local
->
sched_scan_sdata
,
sdata
);
goto
out
;
}
out_free:
while
(
i
>
0
)
kfree
(
local
->
sched_scan_ies
.
ie
[
--
i
]);
kfree
(
sched_scan_ies
.
ie
[
--
i
]);
out:
mutex_unlock
(
&
local
->
mtx
);
return
ret
;
...
...
@@ -970,7 +966,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
int
ieee80211_request_sched_scan_stop
(
struct
ieee80211_sub_if_data
*
sdata
)
{
struct
ieee80211_local
*
local
=
sdata
->
local
;
int
ret
=
0
,
i
;
int
ret
=
0
;
mutex_lock
(
&
local
->
mtx
);
...
...
@@ -979,12 +975,9 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata)
goto
out
;
}
if
(
rcu_access_pointer
(
local
->
sched_scan_sdata
))
{
for
(
i
=
0
;
i
<
IEEE80211_NUM_BANDS
;
i
++
)
kfree
(
local
->
sched_scan_ies
.
ie
[
i
]);
if
(
rcu_access_pointer
(
local
->
sched_scan_sdata
))
drv_sched_scan_stop
(
local
,
sdata
);
}
out:
mutex_unlock
(
&
local
->
mtx
);
...
...
@@ -1006,7 +999,6 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work)
struct
ieee80211_local
*
local
=
container_of
(
work
,
struct
ieee80211_local
,
sched_scan_stopped_work
);
int
i
;
mutex_lock
(
&
local
->
mtx
);
...
...
@@ -1015,9 +1007,6 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work)
return
;
}
for
(
i
=
0
;
i
<
IEEE80211_NUM_BANDS
;
i
++
)
kfree
(
local
->
sched_scan_ies
.
ie
[
i
]);
rcu_assign_pointer
(
local
->
sched_scan_sdata
,
NULL
);
mutex_unlock
(
&
local
->
mtx
);
...
...
net/mac80211/sta_info.c
浏览文件 @
9b4e9e75
...
...
@@ -91,6 +91,70 @@ static int sta_info_hash_del(struct ieee80211_local *local,
return
-
ENOENT
;
}
static
void
free_sta_work
(
struct
work_struct
*
wk
)
{
struct
sta_info
*
sta
=
container_of
(
wk
,
struct
sta_info
,
free_sta_wk
);
int
ac
,
i
;
struct
tid_ampdu_tx
*
tid_tx
;
struct
ieee80211_sub_if_data
*
sdata
=
sta
->
sdata
;
struct
ieee80211_local
*
local
=
sdata
->
local
;
/*
* At this point, when being called as call_rcu callback,
* neither mac80211 nor the driver can reference this
* sta struct any more except by still existing timers
* associated with this station that we clean up below.
*/
if
(
test_sta_flag
(
sta
,
WLAN_STA_PS_STA
))
{
BUG_ON
(
!
sdata
->
bss
);
clear_sta_flag
(
sta
,
WLAN_STA_PS_STA
);
atomic_dec
(
&
sdata
->
bss
->
num_sta_ps
);
sta_info_recalc_tim
(
sta
);
}
for
(
ac
=
0
;
ac
<
IEEE80211_NUM_ACS
;
ac
++
)
{
local
->
total_ps_buffered
-=
skb_queue_len
(
&
sta
->
ps_tx_buf
[
ac
]);
__skb_queue_purge
(
&
sta
->
ps_tx_buf
[
ac
]);
__skb_queue_purge
(
&
sta
->
tx_filtered
[
ac
]);
}
#ifdef CONFIG_MAC80211_MESH
if
(
ieee80211_vif_is_mesh
(
&
sdata
->
vif
))
{
mesh_accept_plinks_update
(
sdata
);
mesh_plink_deactivate
(
sta
);
del_timer_sync
(
&
sta
->
plink_timer
);
}
#endif
cancel_work_sync
(
&
sta
->
drv_unblock_wk
);
/*
* Destroy aggregation state here. It would be nice to wait for the
* driver to finish aggregation stop and then clean up, but for now
* drivers have to handle aggregation stop being requested, followed
* directly by station destruction.
*/
for
(
i
=
0
;
i
<
STA_TID_NUM
;
i
++
)
{
tid_tx
=
rcu_dereference_raw
(
sta
->
ampdu_mlme
.
tid_tx
[
i
]);
if
(
!
tid_tx
)
continue
;
__skb_queue_purge
(
&
tid_tx
->
pending
);
kfree
(
tid_tx
);
}
sta_info_free
(
local
,
sta
);
}
static
void
free_sta_rcu
(
struct
rcu_head
*
h
)
{
struct
sta_info
*
sta
=
container_of
(
h
,
struct
sta_info
,
rcu_head
);
ieee80211_queue_work
(
&
sta
->
local
->
hw
,
&
sta
->
free_sta_wk
);
}
/* protected by RCU */
struct
sta_info
*
sta_info_get
(
struct
ieee80211_sub_if_data
*
sdata
,
const
u8
*
addr
)
...
...
@@ -241,6 +305,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
spin_lock_init
(
&
sta
->
lock
);
INIT_WORK
(
&
sta
->
drv_unblock_wk
,
sta_unblock
);
INIT_WORK
(
&
sta
->
free_sta_wk
,
free_sta_work
);
INIT_WORK
(
&
sta
->
ampdu_mlme
.
work
,
ieee80211_ba_session_work
);
mutex_init
(
&
sta
->
ampdu_mlme
.
mtx
);
...
...
@@ -654,8 +719,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
{
struct
ieee80211_local
*
local
;
struct
ieee80211_sub_if_data
*
sdata
;
int
ret
,
i
,
ac
;
struct
tid_ampdu_tx
*
tid_tx
;
int
ret
,
i
;
might_sleep
();
...
...
@@ -711,65 +775,14 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
WARN_ON_ONCE
(
ret
!=
0
);
}
/*
* At this point, after we wait for an RCU grace period,
* neither mac80211 nor the driver can reference this
* sta struct any more except by still existing timers
* associated with this station that we clean up below.
*/
synchronize_rcu
();
if
(
test_sta_flag
(
sta
,
WLAN_STA_PS_STA
))
{
BUG_ON
(
!
sdata
->
bss
);
clear_sta_flag
(
sta
,
WLAN_STA_PS_STA
);
atomic_dec
(
&
sdata
->
bss
->
num_sta_ps
);
sta_info_recalc_tim
(
sta
);
}
for
(
ac
=
0
;
ac
<
IEEE80211_NUM_ACS
;
ac
++
)
{
local
->
total_ps_buffered
-=
skb_queue_len
(
&
sta
->
ps_tx_buf
[
ac
]);
__skb_queue_purge
(
&
sta
->
ps_tx_buf
[
ac
]);
__skb_queue_purge
(
&
sta
->
tx_filtered
[
ac
]);
}
#ifdef CONFIG_MAC80211_MESH
if
(
ieee80211_vif_is_mesh
(
&
sdata
->
vif
))
mesh_accept_plinks_update
(
sdata
);
#endif
sta_dbg
(
sdata
,
"Removed STA %pM
\n
"
,
sta
->
sta
.
addr
);
cancel_work_sync
(
&
sta
->
drv_unblock_wk
);
cfg80211_del_sta
(
sdata
->
dev
,
sta
->
sta
.
addr
,
GFP_KERNEL
);
rate_control_remove_sta_debugfs
(
sta
);
ieee80211_sta_debugfs_remove
(
sta
);
#ifdef CONFIG_MAC80211_MESH
if
(
ieee80211_vif_is_mesh
(
&
sta
->
sdata
->
vif
))
{
mesh_plink_deactivate
(
sta
);
del_timer_sync
(
&
sta
->
plink_timer
);
}
#endif
/*
* Destroy aggregation state here. It would be nice to wait for the
* driver to finish aggregation stop and then clean up, but for now
* drivers have to handle aggregation stop being requested, followed
* directly by station destruction.
*/
for
(
i
=
0
;
i
<
STA_TID_NUM
;
i
++
)
{
tid_tx
=
rcu_dereference_raw
(
sta
->
ampdu_mlme
.
tid_tx
[
i
]);
if
(
!
tid_tx
)
continue
;
__skb_queue_purge
(
&
tid_tx
->
pending
);
kfree
(
tid_tx
);
}
sta_info_free
(
local
,
sta
);
call_rcu
(
&
sta
->
rcu_head
,
free_sta_rcu
);
return
0
;
}
...
...
net/mac80211/sta_info.h
浏览文件 @
9b4e9e75
...
...
@@ -287,6 +287,7 @@ struct sta_ampdu_mlme {
struct
sta_info
{
/* General information, mostly static */
struct
list_head
list
;
struct
rcu_head
rcu_head
;
struct
sta_info
__rcu
*
hnext
;
struct
ieee80211_local
*
local
;
struct
ieee80211_sub_if_data
*
sdata
;
...
...
@@ -297,6 +298,7 @@ struct sta_info {
spinlock_t
lock
;
struct
work_struct
drv_unblock_wk
;
struct
work_struct
free_sta_wk
;
u16
listen_interval
;
...
...
net/mac80211/status.c
浏览文件 @
9b4e9e75
...
...
@@ -517,29 +517,41 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
if
(
info
->
flags
&
IEEE80211_TX_INTFL_NL80211_FRAME_TX
)
{
u64
cookie
=
(
unsigned
long
)
skb
;
bool
found
=
false
;
acked
=
info
->
flags
&
IEEE80211_TX_STAT_ACK
;
if
(
ieee80211_is_nullfunc
(
hdr
->
frame_control
)
||
ieee80211_is_qos_nullfunc
(
hdr
->
frame_control
))
{
cfg80211_probe_status
(
skb
->
dev
,
hdr
->
addr1
,
cookie
,
acked
,
GFP_ATOMIC
);
}
else
if
(
skb
->
dev
)
{
cfg80211_mgmt_tx_status
(
skb
->
dev
->
ieee80211_ptr
,
cookie
,
skb
->
data
,
skb
->
len
,
acked
,
GFP_ATOMIC
);
}
else
{
struct
ieee80211_sub_if_data
*
p2p_sdata
;
rcu_read_lock
();
list_for_each_entry_rcu
(
sdata
,
&
local
->
interfaces
,
list
)
{
if
(
!
sdata
->
dev
)
continue
;
rcu_read_lock
();
if
(
skb
->
dev
!=
sdata
->
dev
)
continue
;
p2p_sdata
=
rcu_dereference
(
local
->
p2p_sdata
);
if
(
p2p_sdata
)
{
cfg80211_mgmt_tx_status
(
&
p2p_sdata
->
wdev
,
cookie
,
skb
->
data
,
skb
->
len
,
acked
,
GFP_ATOMIC
);
}
rcu_read_unlock
();
found
=
true
;
break
;
}
if
(
!
skb
->
dev
)
{
sdata
=
rcu_dereference
(
local
->
p2p_sdata
);
if
(
sdata
)
found
=
true
;
}
if
(
!
found
)
skb
->
dev
=
NULL
;
else
if
(
ieee80211_is_nullfunc
(
hdr
->
frame_control
)
||
ieee80211_is_qos_nullfunc
(
hdr
->
frame_control
))
{
cfg80211_probe_status
(
sdata
->
dev
,
hdr
->
addr1
,
cookie
,
acked
,
GFP_ATOMIC
);
}
else
{
cfg80211_mgmt_tx_status
(
&
sdata
->
wdev
,
cookie
,
skb
->
data
,
skb
->
len
,
acked
,
GFP_ATOMIC
);
}
rcu_read_unlock
();
}
if
(
unlikely
(
info
->
ack_frame_id
))
{
...
...
net/mac80211/tx.c
浏览文件 @
9b4e9e75
...
...
@@ -580,7 +580,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
tx
->
key
=
NULL
;
else
skip_hw
=
(
tx
->
key
->
conf
.
flags
&
IEEE80211_KEY_FLAG_SW_MGMT
)
&&
IEEE80211_KEY_FLAG_SW_MGMT
_TX
)
&&
ieee80211_is_mgmt
(
hdr
->
frame_control
);
break
;
case
WLAN_CIPHER_SUITE_AES_CMAC
:
...
...
net/mac80211/util.c
浏览文件 @
9b4e9e75
...
...
@@ -792,8 +792,11 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
elems
->
country_elem_len
=
elen
;
break
;
case
WLAN_EID_PWR_CONSTRAINT
:
if
(
elen
!=
1
)
{
elem_parse_failed
=
true
;
break
;
}
elems
->
pwr_constr_elem
=
pos
;
elems
->
pwr_constr_elem_len
=
elen
;
break
;
case
WLAN_EID_TIMEOUT_INTERVAL
:
elems
->
timeout_int
=
pos
;
...
...
@@ -1004,6 +1007,45 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
ieee80211_tx_skb
(
sdata
,
skb
);
}
void
ieee80211_send_deauth_disassoc
(
struct
ieee80211_sub_if_data
*
sdata
,
const
u8
*
bssid
,
u16
stype
,
u16
reason
,
bool
send_frame
,
u8
*
frame_buf
)
{
struct
ieee80211_local
*
local
=
sdata
->
local
;
struct
sk_buff
*
skb
;
struct
ieee80211_mgmt
*
mgmt
=
(
void
*
)
frame_buf
;
/* build frame */
mgmt
->
frame_control
=
cpu_to_le16
(
IEEE80211_FTYPE_MGMT
|
stype
);
mgmt
->
duration
=
0
;
/* initialize only */
mgmt
->
seq_ctrl
=
0
;
/* initialize only */
memcpy
(
mgmt
->
da
,
bssid
,
ETH_ALEN
);
memcpy
(
mgmt
->
sa
,
sdata
->
vif
.
addr
,
ETH_ALEN
);
memcpy
(
mgmt
->
bssid
,
bssid
,
ETH_ALEN
);
/* u.deauth.reason_code == u.disassoc.reason_code */
mgmt
->
u
.
deauth
.
reason_code
=
cpu_to_le16
(
reason
);
if
(
send_frame
)
{
skb
=
dev_alloc_skb
(
local
->
hw
.
extra_tx_headroom
+
IEEE80211_DEAUTH_FRAME_LEN
);
if
(
!
skb
)
return
;
skb_reserve
(
skb
,
local
->
hw
.
extra_tx_headroom
);
/* copy in frame */
memcpy
(
skb_put
(
skb
,
IEEE80211_DEAUTH_FRAME_LEN
),
mgmt
,
IEEE80211_DEAUTH_FRAME_LEN
);
if
(
sdata
->
vif
.
type
!=
NL80211_IFTYPE_STATION
||
!
(
sdata
->
u
.
mgd
.
flags
&
IEEE80211_STA_MFP_ENABLED
))
IEEE80211_SKB_CB
(
skb
)
->
flags
|=
IEEE80211_TX_INTFL_DONT_ENCRYPT
;
ieee80211_tx_skb
(
sdata
,
skb
);
}
}
int
ieee80211_build_preq_ies
(
struct
ieee80211_local
*
local
,
u8
*
buffer
,
const
u8
*
ie
,
size_t
ie_len
,
enum
ieee80211_band
band
,
u32
rate_mask
,
...
...
@@ -1564,14 +1606,13 @@ static int check_mgd_smps(struct ieee80211_if_managed *ifmgd,
return
0
;
}
/* must hold iflist_mtx */
void
ieee80211_recalc_smps
(
struct
ieee80211_local
*
local
)
{
struct
ieee80211_sub_if_data
*
sdata
;
enum
ieee80211_smps_mode
smps_mode
=
IEEE80211_SMPS_OFF
;
int
count
=
0
;
lockdep_assert_held
(
&
local
->
iflist_mtx
);
mutex_lock
(
&
local
->
iflist_mtx
);
/*
* This function could be improved to handle multiple
...
...
@@ -1600,12 +1641,14 @@ void ieee80211_recalc_smps(struct ieee80211_local *local)
}
if
(
smps_mode
==
local
->
smps_mode
)
return
;
goto
unlock
;
set:
local
->
smps_mode
=
smps_mode
;
/* changed flag is auto-detected for this */
ieee80211_hw_config
(
local
,
0
);
unlock:
mutex_unlock
(
&
local
->
iflist_mtx
);
}
static
bool
ieee80211_id_in_list
(
const
u8
*
ids
,
int
n_ids
,
u8
id
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录