Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
66ba271a
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
160
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
66ba271a
编写于
6月 24, 2013
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-john' of
git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
上级
2b5e54e2
6c7c4cbf
变更
23
隐藏空白更改
内联
并排
Showing
23 changed file
with
415 addition
and
231 deletion
+415
-231
include/net/cfg80211.h
include/net/cfg80211.h
+38
-8
include/net/mac80211.h
include/net/mac80211.h
+2
-0
include/uapi/linux/nl80211.h
include/uapi/linux/nl80211.h
+4
-0
net/mac80211/cfg.c
net/mac80211/cfg.c
+2
-12
net/mac80211/ht.c
net/mac80211/ht.c
+3
-1
net/mac80211/ibss.c
net/mac80211/ibss.c
+20
-45
net/mac80211/ieee80211_i.h
net/mac80211/ieee80211_i.h
+3
-3
net/mac80211/mesh.c
net/mac80211/mesh.c
+44
-13
net/mac80211/mesh.h
net/mac80211/mesh.h
+2
-0
net/mac80211/mesh_plink.c
net/mac80211/mesh_plink.c
+7
-1
net/mac80211/mlme.c
net/mac80211/mlme.c
+26
-9
net/mac80211/rate.c
net/mac80211/rate.c
+7
-1
net/mac80211/scan.c
net/mac80211/scan.c
+9
-0
net/mac80211/sta_info.c
net/mac80211/sta_info.c
+2
-0
net/mac80211/sta_info.h
net/mac80211/sta_info.h
+1
-0
net/mac80211/vht.c
net/mac80211/vht.c
+1
-1
net/wireless/chan.c
net/wireless/chan.c
+49
-8
net/wireless/core.c
net/wireless/core.c
+6
-0
net/wireless/mlme.c
net/wireless/mlme.c
+9
-3
net/wireless/nl80211.c
net/wireless/nl80211.c
+158
-119
net/wireless/scan.c
net/wireless/scan.c
+4
-0
net/wireless/sme.c
net/wireless/sme.c
+17
-6
net/wireless/sysfs.c
net/wireless/sysfs.c
+1
-1
未找到文件。
include/net/cfg80211.h
浏览文件 @
66ba271a
...
...
@@ -188,6 +188,8 @@ struct ieee80211_channel {
* when used with 802.11g (on the 2.4 GHz band); filled by the
* core code when registering the wiphy.
* @IEEE80211_RATE_ERP_G: This is an ERP rate in 802.11g mode.
* @IEEE80211_RATE_SUPPORTS_5MHZ: Rate can be used in 5 MHz mode
* @IEEE80211_RATE_SUPPORTS_10MHZ: Rate can be used in 10 MHz mode
*/
enum
ieee80211_rate_flags
{
IEEE80211_RATE_SHORT_PREAMBLE
=
1
<<
0
,
...
...
@@ -195,6 +197,8 @@ enum ieee80211_rate_flags {
IEEE80211_RATE_MANDATORY_B
=
1
<<
2
,
IEEE80211_RATE_MANDATORY_G
=
1
<<
3
,
IEEE80211_RATE_ERP_G
=
1
<<
4
,
IEEE80211_RATE_SUPPORTS_5MHZ
=
1
<<
5
,
IEEE80211_RATE_SUPPORTS_10MHZ
=
1
<<
6
,
};
/**
...
...
@@ -432,6 +436,30 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
const
struct
cfg80211_chan_def
*
chandef
,
u32
prohibited_flags
);
/**
* ieee80211_chandef_rate_flags - returns rate flags for a channel
*
* In some channel types, not all rates may be used - for example CCK
* rates may not be used in 5/10 MHz channels.
*
* @chandef: channel definition for the channel
*
* Returns: rate flags which apply for this channel
*/
static
inline
enum
ieee80211_rate_flags
ieee80211_chandef_rate_flags
(
struct
cfg80211_chan_def
*
chandef
)
{
switch
(
chandef
->
width
)
{
case
NL80211_CHAN_WIDTH_5
:
return
IEEE80211_RATE_SUPPORTS_5MHZ
;
case
NL80211_CHAN_WIDTH_10
:
return
IEEE80211_RATE_SUPPORTS_10MHZ
;
default:
break
;
}
return
0
;
}
/**
* enum survey_info_flags - survey information flags
*
...
...
@@ -1431,7 +1459,8 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
* This structure provides information needed to complete IEEE 802.11
* authentication.
*
* @bss: The BSS to authenticate with.
* @bss: The BSS to authenticate with, the callee must obtain a reference
* to it if it needs to keep it.
* @auth_type: Authentication type (algorithm)
* @ie: Extra IEs to add to Authentication frame or %NULL
* @ie_len: Length of ie buffer in octets
...
...
@@ -1469,11 +1498,10 @@ enum cfg80211_assoc_req_flags {
*
* This structure provides information needed to complete IEEE 802.11
* (re)association.
* @bss: The BSS to associate with. If the call is successful the driver
* is given a reference that it must release, normally via a call to
* cfg80211_send_rx_assoc(), or, if association timed out, with a
* call to cfg80211_put_bss() (in addition to calling
* cfg80211_send_assoc_timeout())
* @bss: The BSS to associate with. If the call is successful the driver is
* given a reference that it must give back to cfg80211_send_rx_assoc()
* or to cfg80211_assoc_timeout(). To ensure proper refcounting, new
* association requests while already associating must be rejected.
* @ie: Extra IEs to add to (Re)Association Request frame or %NULL
* @ie_len: Length of ie buffer in octets
* @use_mfp: Use management frame protection (IEEE 802.11w) in this association
...
...
@@ -2342,6 +2370,7 @@ struct cfg80211_ops {
* responds to probe-requests in hardware.
* @WIPHY_FLAG_OFFCHAN_TX: Device supports direct off-channel TX.
* @WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL: Device supports remain-on-channel call.
* @WIPHY_FLAG_SUPPORTS_5_10_MHZ: Device supports 5 MHz and 10 MHz channels.
*/
enum
wiphy_flags
{
WIPHY_FLAG_CUSTOM_REGULATORY
=
BIT
(
0
),
...
...
@@ -2365,6 +2394,7 @@ enum wiphy_flags {
WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
=
BIT
(
19
),
WIPHY_FLAG_OFFCHAN_TX
=
BIT
(
20
),
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
=
BIT
(
21
),
WIPHY_FLAG_SUPPORTS_5_10_MHZ
=
BIT
(
22
),
};
/**
...
...
@@ -3492,11 +3522,11 @@ void cfg80211_rx_assoc_resp(struct net_device *dev,
/**
* cfg80211_assoc_timeout - notification of timed out association
* @dev: network device
* @
addr: The MAC address of the device with which the association timed out
* @
bss: The BSS entry with which association timed out.
*
* This function may sleep. The caller must hold the corresponding wdev's mutex.
*/
void
cfg80211_assoc_timeout
(
struct
net_device
*
dev
,
const
u8
*
addr
);
void
cfg80211_assoc_timeout
(
struct
net_device
*
dev
,
struct
cfg80211_bss
*
bss
);
/**
* cfg80211_tx_mlme_mgmt - notification of transmitted deauth/disassoc frame
...
...
include/net/mac80211.h
浏览文件 @
66ba271a
...
...
@@ -305,6 +305,7 @@ enum ieee80211_rssi_event {
* @basic_rates: bitmap of basic rates, each bit stands for an
* index into the rate table configured by the driver in
* the current band.
* @beacon_rate: associated AP's beacon TX rate
* @mcast_rate: per-band multicast rate index + 1 (0: disabled)
* @bssid: The BSSID for this BSS
* @enable_beacon: whether beaconing should be enabled or not
...
...
@@ -352,6 +353,7 @@ struct ieee80211_bss_conf {
u32
sync_device_ts
;
u8
sync_dtim_count
;
u32
basic_rates
;
struct
ieee80211_rate
*
beacon_rate
;
int
mcast_rate
[
IEEE80211_NUM_BANDS
];
u16
ht_operation_mode
;
s32
cqm_rssi_thold
;
...
...
include/uapi/linux/nl80211.h
浏览文件 @
66ba271a
...
...
@@ -2758,6 +2758,8 @@ enum nl80211_channel_type {
* and %NL80211_ATTR_CENTER_FREQ2 attributes must be provided as well
* @NL80211_CHAN_WIDTH_160: 160 MHz channel, the %NL80211_ATTR_CENTER_FREQ1
* attribute must be provided as well
* @NL80211_CHAN_WIDTH_5: 5 MHz OFDM channel
* @NL80211_CHAN_WIDTH_10: 10 MHz OFDM channel
*/
enum
nl80211_chan_width
{
NL80211_CHAN_WIDTH_20_NOHT
,
...
...
@@ -2766,6 +2768,8 @@ enum nl80211_chan_width {
NL80211_CHAN_WIDTH_80
,
NL80211_CHAN_WIDTH_80P80
,
NL80211_CHAN_WIDTH_160
,
NL80211_CHAN_WIDTH_5
,
NL80211_CHAN_WIDTH_10
,
};
/**
...
...
net/mac80211/cfg.c
浏览文件 @
66ba271a
...
...
@@ -2827,7 +2827,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
!
rcu_access_pointer
(
sdata
->
bss
->
beacon
))
need_offchan
=
true
;
if
(
!
ieee80211_is_action
(
mgmt
->
frame_control
)
||
mgmt
->
u
.
action
.
category
==
WLAN_CATEGORY_PUBLIC
)
mgmt
->
u
.
action
.
category
==
WLAN_CATEGORY_PUBLIC
||
mgmt
->
u
.
action
.
category
==
WLAN_CATEGORY_SELF_PROTECTED
)
break
;
rcu_read_lock
();
sta
=
sta_info_get
(
sdata
,
mgmt
->
da
);
...
...
@@ -2930,19 +2931,8 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
u16
frame_type
,
bool
reg
)
{
struct
ieee80211_local
*
local
=
wiphy_priv
(
wiphy
);
struct
ieee80211_sub_if_data
*
sdata
=
IEEE80211_WDEV_TO_SUB_IF
(
wdev
);
switch
(
frame_type
)
{
case
IEEE80211_FTYPE_MGMT
|
IEEE80211_STYPE_AUTH
:
if
(
sdata
->
vif
.
type
==
NL80211_IFTYPE_ADHOC
)
{
struct
ieee80211_if_ibss
*
ifibss
=
&
sdata
->
u
.
ibss
;
if
(
reg
)
ifibss
->
auth_frame_registrations
++
;
else
ifibss
->
auth_frame_registrations
--
;
}
break
;
case
IEEE80211_FTYPE_MGMT
|
IEEE80211_STYPE_PROBE_REQ
:
if
(
reg
)
local
->
probe_req_reg
++
;
...
...
net/mac80211/ht.c
浏览文件 @
66ba271a
...
...
@@ -281,13 +281,14 @@ void ieee80211_ba_session_work(struct work_struct *work)
sta
,
tid
,
WLAN_BACK_RECIPIENT
,
WLAN_REASON_UNSPECIFIED
,
true
);
spin_lock_bh
(
&
sta
->
lock
);
tid_tx
=
sta
->
ampdu_mlme
.
tid_start_tx
[
tid
];
if
(
tid_tx
)
{
/*
* Assign it over to the normal tid_tx array
* where it "goes live".
*/
spin_lock_bh
(
&
sta
->
lock
);
sta
->
ampdu_mlme
.
tid_start_tx
[
tid
]
=
NULL
;
/* could there be a race? */
...
...
@@ -300,6 +301,7 @@ void ieee80211_ba_session_work(struct work_struct *work)
ieee80211_tx_ba_session_handle_start
(
sta
,
tid
);
continue
;
}
spin_unlock_bh
(
&
sta
->
lock
);
tid_tx
=
rcu_dereference_protected_tid_tx
(
sta
,
tid
);
if
(
tid_tx
&&
test_and_clear_bit
(
HT_AGG_STATE_WANT_STOP
,
...
...
net/mac80211/ibss.c
浏览文件 @
66ba271a
...
...
@@ -81,7 +81,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
sdata
->
drop_unencrypted
=
capability
&
WLAN_CAPABILITY_PRIVACY
?
1
:
0
;
c
fg80211_chandef_create
(
&
chandef
,
chan
,
ifibss
->
channel_type
)
;
c
handef
=
ifibss
->
chandef
;
if
(
!
cfg80211_reg_can_beacon
(
local
->
hw
.
wiphy
,
&
chandef
))
{
chandef
.
width
=
NL80211_CHAN_WIDTH_20
;
chandef
.
center_freq1
=
chan
->
center_freq
;
...
...
@@ -176,6 +176,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
/* add HT capability and information IEs */
if
(
chandef
.
width
!=
NL80211_CHAN_WIDTH_20_NOHT
&&
chandef
.
width
!=
NL80211_CHAN_WIDTH_5
&&
chandef
.
width
!=
NL80211_CHAN_WIDTH_10
&&
sband
->
ht_cap
.
ht_supported
)
{
pos
=
ieee80211_ie_build_ht_cap
(
pos
,
&
sband
->
ht_cap
,
sband
->
ht_cap
.
cap
);
...
...
@@ -298,8 +300,7 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
tsf
,
false
);
}
static
struct
sta_info
*
ieee80211_ibss_finish_sta
(
struct
sta_info
*
sta
,
bool
auth
)
static
struct
sta_info
*
ieee80211_ibss_finish_sta
(
struct
sta_info
*
sta
)
__acquires
(
RCU
)
{
struct
ieee80211_sub_if_data
*
sdata
=
sta
->
sdata
;
...
...
@@ -321,20 +322,12 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta,
/* If it fails, maybe we raced another insertion? */
if
(
sta_info_insert_rcu
(
sta
))
return
sta_info_get
(
sdata
,
addr
);
if
(
auth
&&
!
sdata
->
u
.
ibss
.
auth_frame_registrations
)
{
ibss_dbg
(
sdata
,
"TX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=1)
\n
"
,
sdata
->
vif
.
addr
,
addr
,
sdata
->
u
.
ibss
.
bssid
);
ieee80211_send_auth
(
sdata
,
1
,
WLAN_AUTH_OPEN
,
0
,
NULL
,
0
,
addr
,
sdata
->
u
.
ibss
.
bssid
,
NULL
,
0
,
0
,
0
);
}
return
sta
;
}
static
struct
sta_info
*
ieee80211_ibss_add_sta
(
struct
ieee80211_sub_if_data
*
sdata
,
const
u8
*
bssid
,
const
u8
*
addr
,
u32
supp_rates
,
bool
auth
)
ieee80211_ibss_add_sta
(
struct
ieee80211_sub_if_data
*
sdata
,
const
u8
*
bssid
,
const
u8
*
addr
,
u32
supp_rates
)
__acquires
(
RCU
)
{
struct
ieee80211_if_ibss
*
ifibss
=
&
sdata
->
u
.
ibss
;
...
...
@@ -385,7 +378,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
sta
->
sta
.
supp_rates
[
band
]
=
supp_rates
|
ieee80211_mandatory_rates
(
sband
);
return
ieee80211_ibss_finish_sta
(
sta
,
auth
);
return
ieee80211_ibss_finish_sta
(
sta
);
}
static
void
ieee80211_rx_mgmt_deauth_ibss
(
struct
ieee80211_sub_if_data
*
sdata
,
...
...
@@ -407,8 +400,6 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
size_t
len
)
{
u16
auth_alg
,
auth_transaction
;
struct
sta_info
*
sta
;
u8
deauth_frame_buf
[
IEEE80211_DEAUTH_FRAME_LEN
];
sdata_assert_lock
(
sdata
);
...
...
@@ -425,22 +416,6 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
if
(
auth_alg
!=
WLAN_AUTH_OPEN
||
auth_transaction
!=
1
)
return
;
sta_info_destroy_addr
(
sdata
,
mgmt
->
sa
);
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.
...
...
@@ -506,7 +481,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
}
else
{
rcu_read_unlock
();
sta
=
ieee80211_ibss_add_sta
(
sdata
,
mgmt
->
bssid
,
mgmt
->
sa
,
supp_rates
,
true
);
mgmt
->
sa
,
supp_rates
);
}
}
...
...
@@ -514,7 +489,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
set_sta_flag
(
sta
,
WLAN_STA_WME
);
if
(
sta
&&
elems
->
ht_operation
&&
elems
->
ht_cap_elem
&&
sdata
->
u
.
ibss
.
channel_type
!=
NL80211_CHAN_NO_HT
)
{
sdata
->
u
.
ibss
.
chandef
.
width
!=
NL80211_CHAN_WIDTH_20_NOHT
&&
sdata
->
u
.
ibss
.
chandef
.
width
!=
NL80211_CHAN_WIDTH_5
&&
sdata
->
u
.
ibss
.
chandef
.
width
!=
NL80211_CHAN_WIDTH_10
)
{
/* we both use HT */
struct
ieee80211_ht_cap
htcap_ie
;
struct
cfg80211_chan_def
chandef
;
...
...
@@ -529,8 +506,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
* fall back to HT20 if we don't use or use
* the other extension channel
*/
if
(
c
fg80211_get_chandef_type
(
&
chandef
)
!=
sdata
->
u
.
ibss
.
channel_type
)
if
(
c
handef
.
center_freq1
!=
sdata
->
u
.
ibss
.
chandef
.
center_freq1
)
htcap_ie
.
cap_info
&=
cpu_to_le16
(
~
IEEE80211_HT_CAP_SUP_WIDTH_20_40
);
...
...
@@ -569,7 +546,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
/* different channel */
if
(
sdata
->
u
.
ibss
.
fixed_channel
&&
sdata
->
u
.
ibss
.
chan
nel
!=
cbss
->
channel
)
sdata
->
u
.
ibss
.
chan
def
.
chan
!=
cbss
->
channel
)
goto
put_bss
;
/* different SSID */
...
...
@@ -610,7 +587,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
ieee80211_sta_join_ibss
(
sdata
,
bss
);
supp_rates
=
ieee80211_sta_get_rates
(
local
,
elems
,
band
,
NULL
);
ieee80211_ibss_add_sta
(
sdata
,
mgmt
->
bssid
,
mgmt
->
sa
,
supp_rates
,
true
);
supp_rates
);
rcu_read_unlock
();
}
...
...
@@ -759,7 +736,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
sdata
->
drop_unencrypted
=
0
;
__ieee80211_sta_join_ibss
(
sdata
,
bssid
,
sdata
->
vif
.
bss_conf
.
beacon_int
,
ifibss
->
chan
nel
,
ifibss
->
basic_rates
,
ifibss
->
chan
def
.
chan
,
ifibss
->
basic_rates
,
capability
,
0
,
true
);
}
...
...
@@ -791,7 +768,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
if
(
ifibss
->
fixed_bssid
)
bssid
=
ifibss
->
bssid
;
if
(
ifibss
->
fixed_channel
)
chan
=
ifibss
->
chan
nel
;
chan
=
ifibss
->
chan
def
.
chan
;
if
(
!
is_zero_ether_addr
(
ifibss
->
bssid
))
bssid
=
ifibss
->
bssid
;
cbss
=
cfg80211_get_bss
(
local
->
hw
.
wiphy
,
chan
,
bssid
,
...
...
@@ -982,7 +959,7 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
list_del
(
&
sta
->
list
);
spin_unlock_bh
(
&
ifibss
->
incomplete_lock
);
ieee80211_ibss_finish_sta
(
sta
,
true
);
ieee80211_ibss_finish_sta
(
sta
);
rcu_read_unlock
();
spin_lock_bh
(
&
ifibss
->
incomplete_lock
);
}
...
...
@@ -1058,9 +1035,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
sdata
->
vif
.
bss_conf
.
beacon_int
=
params
->
beacon_interval
;
sdata
->
u
.
ibss
.
channel
=
params
->
chandef
.
chan
;
sdata
->
u
.
ibss
.
channel_type
=
cfg80211_get_chandef_type
(
&
params
->
chandef
);
sdata
->
u
.
ibss
.
chandef
=
params
->
chandef
;
sdata
->
u
.
ibss
.
fixed_channel
=
params
->
channel_fixed
;
if
(
params
->
ie
)
{
...
...
@@ -1119,7 +1094,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
if
(
ifibss
->
privacy
)
capability
|=
WLAN_CAPABILITY_PRIVACY
;
cbss
=
cfg80211_get_bss
(
local
->
hw
.
wiphy
,
ifibss
->
chan
nel
,
cbss
=
cfg80211_get_bss
(
local
->
hw
.
wiphy
,
ifibss
->
chan
def
.
chan
,
ifibss
->
bssid
,
ifibss
->
ssid
,
ifibss
->
ssid_len
,
WLAN_CAPABILITY_IBSS
|
WLAN_CAPABILITY_PRIVACY
,
...
...
net/mac80211/ieee80211_i.h
浏览文件 @
66ba271a
...
...
@@ -94,6 +94,7 @@ struct ieee80211_bss {
#define IEEE80211_MAX_SUPP_RATES 32
u8
supp_rates
[
IEEE80211_MAX_SUPP_RATES
];
size_t
supp_rates_len
;
struct
ieee80211_rate
*
beacon_rate
;
/*
* During association, we save an ERP value from a probe response so
...
...
@@ -497,14 +498,12 @@ struct ieee80211_if_ibss {
bool
privacy
;
bool
control_port
;
unsigned
int
auth_frame_registrations
;
u8
bssid
[
ETH_ALEN
]
__aligned
(
2
);
u8
ssid
[
IEEE80211_MAX_SSID_LEN
];
u8
ssid_len
,
ie_len
;
u8
*
ie
;
struct
ieee80211_channel
*
channel
;
enum
nl80211_channel_type
channel_type
;
struct
cfg80211_chan_def
chandef
;
unsigned
long
ibss_join_req
;
/* probe response/beacon for IBSS */
...
...
@@ -543,6 +542,7 @@ struct ieee80211_if_mesh {
struct
timer_list
mesh_path_root_timer
;
unsigned
long
wrkq_flags
;
unsigned
long
mbss_changed
;
u8
mesh_id
[
IEEE80211_MAX_MESH_ID_LEN
];
size_t
mesh_id_len
;
...
...
net/mac80211/mesh.c
浏览文件 @
66ba271a
...
...
@@ -161,11 +161,8 @@ void mesh_sta_cleanup(struct sta_info *sta)
del_timer_sync
(
&
sta
->
plink_timer
);
}
if
(
changed
)
{
sdata_lock
(
sdata
);
if
(
changed
)
ieee80211_mbss_info_change_notify
(
sdata
,
changed
);
sdata_unlock
(
sdata
);
}
}
int
mesh_rmc_init
(
struct
ieee80211_sub_if_data
*
sdata
)
...
...
@@ -419,7 +416,9 @@ int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata,
sband
=
local
->
hw
.
wiphy
->
bands
[
band
];
if
(
!
sband
->
ht_cap
.
ht_supported
||
sdata
->
vif
.
bss_conf
.
chandef
.
width
==
NL80211_CHAN_WIDTH_20_NOHT
)
sdata
->
vif
.
bss_conf
.
chandef
.
width
==
NL80211_CHAN_WIDTH_20_NOHT
||
sdata
->
vif
.
bss_conf
.
chandef
.
width
==
NL80211_CHAN_WIDTH_5
||
sdata
->
vif
.
bss_conf
.
chandef
.
width
==
NL80211_CHAN_WIDTH_10
)
return
0
;
if
(
skb_tailroom
(
skb
)
<
2
+
sizeof
(
struct
ieee80211_ht_cap
))
...
...
@@ -719,14 +718,18 @@ ieee80211_mesh_rebuild_beacon(struct ieee80211_sub_if_data *sdata)
void
ieee80211_mbss_info_change_notify
(
struct
ieee80211_sub_if_data
*
sdata
,
u32
changed
)
{
if
(
sdata
->
vif
.
bss_conf
.
enable_beacon
&&
(
changed
&
(
BSS_CHANGED_BEACON
|
BSS_CHANGED_HT
|
BSS_CHANGED_BASIC_RATES
|
BSS_CHANGED_BEACON_INT
)))
if
(
ieee80211_mesh_rebuild_beacon
(
sdata
))
return
;
ieee80211_bss_info_change_notify
(
sdata
,
changed
);
struct
ieee80211_if_mesh
*
ifmsh
=
&
sdata
->
u
.
mesh
;
unsigned
long
bits
=
changed
;
u32
bit
;
if
(
!
bits
)
return
;
/* if we race with running work, worst case this work becomes a noop */
for_each_set_bit
(
bit
,
&
bits
,
sizeof
(
changed
)
*
BITS_PER_BYTE
)
set_bit
(
bit
,
&
ifmsh
->
mbss_changed
);
set_bit
(
MESH_WORK_MBSS_CHANGED
,
&
ifmsh
->
wrkq_flags
);
ieee80211_queue_work
(
&
sdata
->
local
->
hw
,
&
sdata
->
work
);
}
int
ieee80211_start_mesh
(
struct
ieee80211_sub_if_data
*
sdata
)
...
...
@@ -799,6 +802,10 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
del_timer_sync
(
&
sdata
->
u
.
mesh
.
mesh_path_root_timer
);
del_timer_sync
(
&
sdata
->
u
.
mesh
.
mesh_path_timer
);
/* clear any mesh work (for next join) we may have accrued */
ifmsh
->
wrkq_flags
=
0
;
ifmsh
->
mbss_changed
=
0
;
local
->
fif_other_bss
--
;
atomic_dec
(
&
local
->
iff_allmultis
);
ieee80211_configure_filter
(
local
);
...
...
@@ -965,6 +972,28 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
sdata_unlock
(
sdata
);
}
static
void
mesh_bss_info_changed
(
struct
ieee80211_sub_if_data
*
sdata
)
{
struct
ieee80211_if_mesh
*
ifmsh
=
&
sdata
->
u
.
mesh
;
u32
bit
,
changed
=
0
;
for_each_set_bit
(
bit
,
&
ifmsh
->
mbss_changed
,
sizeof
(
changed
)
*
BITS_PER_BYTE
)
{
clear_bit
(
bit
,
&
ifmsh
->
mbss_changed
);
changed
|=
BIT
(
bit
);
}
if
(
sdata
->
vif
.
bss_conf
.
enable_beacon
&&
(
changed
&
(
BSS_CHANGED_BEACON
|
BSS_CHANGED_HT
|
BSS_CHANGED_BASIC_RATES
|
BSS_CHANGED_BEACON_INT
)))
if
(
ieee80211_mesh_rebuild_beacon
(
sdata
))
return
;
ieee80211_bss_info_change_notify
(
sdata
,
changed
);
}
void
ieee80211_mesh_work
(
struct
ieee80211_sub_if_data
*
sdata
)
{
struct
ieee80211_if_mesh
*
ifmsh
=
&
sdata
->
u
.
mesh
;
...
...
@@ -995,6 +1024,8 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
if
(
test_and_clear_bit
(
MESH_WORK_DRIFT_ADJUST
,
&
ifmsh
->
wrkq_flags
))
mesh_sync_adjust_tbtt
(
sdata
);
if
(
test_and_clear_bit
(
MESH_WORK_MBSS_CHANGED
,
&
ifmsh
->
wrkq_flags
))
mesh_bss_info_changed
(
sdata
);
out:
sdata_unlock
(
sdata
);
}
...
...
net/mac80211/mesh.h
浏览文件 @
66ba271a
...
...
@@ -58,6 +58,7 @@ enum mesh_path_flags {
* @MESH_WORK_ROOT: the mesh root station needs to send a frame
* @MESH_WORK_DRIFT_ADJUST: time to compensate for clock drift relative to other
* mesh nodes
* @MESH_WORK_MBSS_CHANGED: rebuild beacon and notify driver of BSS changes
*/
enum
mesh_deferred_task_flags
{
MESH_WORK_HOUSEKEEPING
,
...
...
@@ -65,6 +66,7 @@ enum mesh_deferred_task_flags {
MESH_WORK_GROW_MPP_TABLE
,
MESH_WORK_ROOT
,
MESH_WORK_DRIFT_ADJUST
,
MESH_WORK_MBSS_CHANGED
,
};
/**
...
...
net/mac80211/mesh_plink.c
浏览文件 @
66ba271a
...
...
@@ -154,8 +154,14 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
u16
ht_opmode
;
bool
non_ht_sta
=
false
,
ht20_sta
=
false
;
if
(
sdata
->
vif
.
bss_conf
.
chandef
.
width
==
NL80211_CHAN_WIDTH_20_NOHT
)
switch
(
sdata
->
vif
.
bss_conf
.
chandef
.
width
)
{
case
NL80211_CHAN_WIDTH_20_NOHT
:
case
NL80211_CHAN_WIDTH_5
:
case
NL80211_CHAN_WIDTH_10
:
return
0
;
default:
break
;
}
rcu_read_lock
();
list_for_each_entry_rcu
(
sta
,
&
local
->
sta_list
,
list
)
{
...
...
net/mac80211/mlme.c
浏览文件 @
66ba271a
...
...
@@ -190,6 +190,12 @@ static u32 chandef_downgrade(struct cfg80211_chan_def *c)
c
->
width
=
NL80211_CHAN_WIDTH_20_NOHT
;
ret
=
IEEE80211_STA_DISABLE_HT
|
IEEE80211_STA_DISABLE_VHT
;
break
;
case
NL80211_CHAN_WIDTH_5
:
case
NL80211_CHAN_WIDTH_10
:
WARN_ON_ONCE
(
1
);
/* keep c->width */
ret
=
IEEE80211_STA_DISABLE_HT
|
IEEE80211_STA_DISABLE_VHT
;
break
;
}
WARN_ON_ONCE
(
!
cfg80211_chandef_valid
(
c
));
...
...
@@ -1779,8 +1785,10 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
* probably just won't work at all.
*/
bss_conf
->
dtim_period
=
sdata
->
u
.
mgd
.
dtim_period
?:
1
;
bss_conf
->
beacon_rate
=
bss
->
beacon_rate
;
bss_info_changed
|=
BSS_CHANGED_BEACON_INFO
;
}
else
{
bss_conf
->
beacon_rate
=
NULL
;
bss_conf
->
dtim_period
=
0
;
}
...
...
@@ -1903,6 +1911,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
del_timer_sync
(
&
sdata
->
u
.
mgd
.
chswitch_timer
);
sdata
->
vif
.
bss_conf
.
dtim_period
=
0
;
sdata
->
vif
.
bss_conf
.
beacon_rate
=
NULL
;
ifmgd
->
have_beacon
=
false
;
ifmgd
->
flags
=
0
;
...
...
@@ -2785,8 +2795,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
if
(
!
ieee80211_assoc_success
(
sdata
,
bss
,
mgmt
,
len
))
{
/* oops -- internal error -- send timeout for now */
ieee80211_destroy_assoc_data
(
sdata
,
false
);
cfg80211_put_bss
(
sdata
->
local
->
hw
.
wiphy
,
bss
);
cfg80211_assoc_timeout
(
sdata
->
dev
,
mgmt
->
bssid
);
cfg80211_assoc_timeout
(
sdata
->
dev
,
bss
);
return
;
}
sdata_info
(
sdata
,
"associated
\n
"
);
...
...
@@ -2827,8 +2836,10 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
bss
=
ieee80211_bss_info_update
(
local
,
rx_status
,
mgmt
,
len
,
elems
,
channel
);
if
(
bss
)
if
(
bss
)
{
ieee80211_rx_bss_put
(
local
,
bss
);
sdata
->
vif
.
bss_conf
.
beacon_rate
=
bss
->
beacon_rate
;
}
if
(
!
sdata
->
u
.
mgd
.
associated
||
!
ether_addr_equal
(
mgmt
->
bssid
,
sdata
->
u
.
mgd
.
associated
->
bssid
))
...
...
@@ -3501,13 +3512,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
time_after
(
jiffies
,
ifmgd
->
assoc_data
->
timeout
))
{
if
((
ifmgd
->
assoc_data
->
need_beacon
&&
!
ifmgd
->
have_beacon
)
||
ieee80211_do_assoc
(
sdata
))
{
u8
bssid
[
ETH_ALEN
];
memcpy
(
bssid
,
ifmgd
->
assoc_data
->
bss
->
bssid
,
ETH_ALEN
);
struct
cfg80211_bss
*
bss
=
ifmgd
->
assoc_data
->
bss
;
ieee80211_destroy_assoc_data
(
sdata
,
false
);
cfg80211_assoc_timeout
(
sdata
->
dev
,
bssid
);
cfg80211_assoc_timeout
(
sdata
->
dev
,
bss
);
}
}
else
if
(
ifmgd
->
assoc_data
&&
ifmgd
->
assoc_data
->
timeout_started
)
run_again
(
sdata
,
ifmgd
->
assoc_data
->
timeout
);
...
...
@@ -3838,6 +3846,12 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
*/
ret
=
ieee80211_vif_use_channel
(
sdata
,
&
chandef
,
IEEE80211_CHANCTX_SHARED
);
/* don't downgrade for 5 and 10 MHz channels, though. */
if
(
chandef
.
width
==
NL80211_CHAN_WIDTH_5
||
chandef
.
width
==
NL80211_CHAN_WIDTH_10
)
return
ret
;
while
(
ret
&&
chandef
.
width
!=
NL80211_CHAN_WIDTH_20_NOHT
)
{
ifmgd
->
flags
|=
chandef_downgrade
(
&
chandef
);
ret
=
ieee80211_vif_use_channel
(
sdata
,
&
chandef
,
...
...
@@ -4427,8 +4441,11 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
cancel_work_sync
(
&
ifmgd
->
chswitch_work
);
sdata_lock
(
sdata
);
if
(
ifmgd
->
assoc_data
)
if
(
ifmgd
->
assoc_data
)
{
struct
cfg80211_bss
*
bss
=
ifmgd
->
assoc_data
->
bss
;
ieee80211_destroy_assoc_data
(
sdata
,
false
);
cfg80211_assoc_timeout
(
sdata
->
dev
,
bss
);
}
if
(
ifmgd
->
auth_data
)
ieee80211_destroy_auth_data
(
sdata
,
false
);
del_timer_sync
(
&
ifmgd
->
timer
);
...
...
net/mac80211/rate.c
浏览文件 @
66ba271a
...
...
@@ -397,8 +397,14 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
return
;
/* if HT BSS, and we handle a data frame, also try HT rates */
if
(
chan_width
==
NL80211_CHAN_WIDTH_20_NOHT
)
switch
(
chan_width
)
{
case
NL80211_CHAN_WIDTH_20_NOHT
:
case
NL80211_CHAN_WIDTH_5
:
case
NL80211_CHAN_WIDTH_10
:
return
;
default:
break
;
}
alt_rate
.
idx
=
0
;
/* keep protection flags */
...
...
net/mac80211/scan.c
浏览文件 @
66ba271a
...
...
@@ -140,6 +140,15 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
bss
->
valid_data
|=
IEEE80211_BSS_VALID_WMM
;
}
if
(
beacon
)
{
struct
ieee80211_supported_band
*
sband
=
local
->
hw
.
wiphy
->
bands
[
rx_status
->
band
];
if
(
!
(
rx_status
->
flag
&
RX_FLAG_HT
)
&&
!
(
rx_status
->
flag
&
RX_FLAG_VHT
))
bss
->
beacon_rate
=
&
sband
->
bitrates
[
rx_status
->
rate_idx
];
}
return
bss
;
}
...
...
net/mac80211/sta_info.c
浏览文件 @
66ba271a
...
...
@@ -149,6 +149,7 @@ static void cleanup_single_sta(struct sta_info *sta)
* directly by station destruction.
*/
for
(
i
=
0
;
i
<
IEEE80211_NUM_TIDS
;
i
++
)
{
kfree
(
sta
->
ampdu_mlme
.
tid_start_tx
[
i
]);
tid_tx
=
rcu_dereference_raw
(
sta
->
ampdu_mlme
.
tid_tx
[
i
]);
if
(
!
tid_tx
)
continue
;
...
...
@@ -346,6 +347,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
if
(
ieee80211_vif_is_mesh
(
&
sdata
->
vif
)
&&
!
sdata
->
u
.
mesh
.
user_mpm
)
init_timer
(
&
sta
->
plink_timer
);
sta
->
nonpeer_pm
=
NL80211_MESH_POWER_ACTIVE
;
#endif
memcpy
(
sta
->
sta
.
addr
,
addr
,
ETH_ALEN
);
...
...
net/mac80211/sta_info.h
浏览文件 @
66ba271a
...
...
@@ -203,6 +203,7 @@ struct tid_ampdu_rx {
* driver requested to close until the work for it runs
* @mtx: mutex to protect all TX data (except non-NULL assignments
* to tid_tx[idx], which are protected by the sta spinlock)
* tid_start_tx is also protected by sta->lock.
*/
struct
sta_ampdu_mlme
{
struct
mutex
mtx
;
...
...
net/mac80211/vht.c
浏览文件 @
66ba271a
...
...
@@ -396,7 +396,7 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
new_bw
=
ieee80211_sta_cur_vht_bw
(
sta
);
if
(
new_bw
!=
sta
->
sta
.
bandwidth
)
{
sta
->
sta
.
bandwidth
=
new_bw
;
changed
|=
IEEE80211_RC_
NSS
_CHANGED
;
changed
|=
IEEE80211_RC_
BW
_CHANGED
;
}
change:
...
...
net/wireless/chan.c
浏览文件 @
66ba271a
...
...
@@ -54,6 +54,8 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
control_freq
=
chandef
->
chan
->
center_freq
;
switch
(
chandef
->
width
)
{
case
NL80211_CHAN_WIDTH_5
:
case
NL80211_CHAN_WIDTH_10
:
case
NL80211_CHAN_WIDTH_20
:
case
NL80211_CHAN_WIDTH_20_NOHT
:
if
(
chandef
->
center_freq1
!=
control_freq
)
...
...
@@ -152,6 +154,12 @@ static int cfg80211_chandef_get_width(const struct cfg80211_chan_def *c)
int
width
;
switch
(
c
->
width
)
{
case
NL80211_CHAN_WIDTH_5
:
width
=
5
;
break
;
case
NL80211_CHAN_WIDTH_10
:
width
=
10
;
break
;
case
NL80211_CHAN_WIDTH_20
:
case
NL80211_CHAN_WIDTH_20_NOHT
:
width
=
20
;
...
...
@@ -194,6 +202,16 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1,
if
(
c1
->
width
==
c2
->
width
)
return
NULL
;
/*
* can't be compatible if one of them is 5 or 10 MHz,
* but they don't have the same width.
*/
if
(
c1
->
width
==
NL80211_CHAN_WIDTH_5
||
c1
->
width
==
NL80211_CHAN_WIDTH_10
||
c2
->
width
==
NL80211_CHAN_WIDTH_5
||
c2
->
width
==
NL80211_CHAN_WIDTH_10
)
return
NULL
;
if
(
c1
->
width
==
NL80211_CHAN_WIDTH_20_NOHT
||
c1
->
width
==
NL80211_CHAN_WIDTH_20
)
return
c2
;
...
...
@@ -264,11 +282,17 @@ static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy,
u32
bandwidth
)
{
struct
ieee80211_channel
*
c
;
u32
freq
;
u32
freq
,
start_freq
,
end_freq
;
if
(
bandwidth
<=
20
)
{
start_freq
=
center_freq
;
end_freq
=
center_freq
;
}
else
{
start_freq
=
center_freq
-
bandwidth
/
2
+
10
;
end_freq
=
center_freq
+
bandwidth
/
2
-
10
;
}
for
(
freq
=
center_freq
-
bandwidth
/
2
+
10
;
freq
<=
center_freq
+
bandwidth
/
2
-
10
;
freq
+=
20
)
{
for
(
freq
=
start_freq
;
freq
<=
end_freq
;
freq
+=
20
)
{
c
=
ieee80211_get_channel
(
wiphy
,
freq
);
if
(
!
c
)
return
-
EINVAL
;
...
...
@@ -310,11 +334,17 @@ static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
u32
prohibited_flags
)
{
struct
ieee80211_channel
*
c
;
u32
freq
;
u32
freq
,
start_freq
,
end_freq
;
if
(
bandwidth
<=
20
)
{
start_freq
=
center_freq
;
end_freq
=
center_freq
;
}
else
{
start_freq
=
center_freq
-
bandwidth
/
2
+
10
;
end_freq
=
center_freq
+
bandwidth
/
2
-
10
;
}
for
(
freq
=
center_freq
-
bandwidth
/
2
+
10
;
freq
<=
center_freq
+
bandwidth
/
2
-
10
;
freq
+=
20
)
{
for
(
freq
=
start_freq
;
freq
<=
end_freq
;
freq
+=
20
)
{
c
=
ieee80211_get_channel
(
wiphy
,
freq
);
if
(
!
c
)
return
false
;
...
...
@@ -349,6 +379,12 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
control_freq
=
chandef
->
chan
->
center_freq
;
switch
(
chandef
->
width
)
{
case
NL80211_CHAN_WIDTH_5
:
width
=
5
;
break
;
case
NL80211_CHAN_WIDTH_10
:
width
=
10
;
break
;
case
NL80211_CHAN_WIDTH_20
:
if
(
!
ht_cap
->
ht_supported
)
return
false
;
...
...
@@ -405,6 +441,11 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
if
(
width
>
20
)
prohibited_flags
|=
IEEE80211_CHAN_NO_OFDM
;
/* 5 and 10 MHz are only defined for the OFDM PHY */
if
(
width
<
20
)
prohibited_flags
|=
IEEE80211_CHAN_NO_OFDM
;
if
(
!
cfg80211_secondary_chans_ok
(
wiphy
,
chandef
->
center_freq1
,
width
,
prohibited_flags
))
return
false
;
...
...
net/wireless/core.c
浏览文件 @
66ba271a
...
...
@@ -934,6 +934,12 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
* freed.
*/
cfg80211_process_wdev_events
(
wdev
);
if
(
WARN_ON
(
wdev
->
current_bss
))
{
cfg80211_unhold_bss
(
wdev
->
current_bss
);
cfg80211_put_bss
(
wdev
->
wiphy
,
&
wdev
->
current_bss
->
pub
);
wdev
->
current_bss
=
NULL
;
}
break
;
case
NETDEV_PRE_UP
:
if
(
!
(
wdev
->
wiphy
->
interface_modes
&
BIT
(
wdev
->
iftype
)))
...
...
net/wireless/mlme.c
浏览文件 @
66ba271a
...
...
@@ -38,6 +38,7 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss,
* frame instead of reassoc.
*/
if
(
cfg80211_sme_rx_assoc_resp
(
wdev
,
status_code
))
{
cfg80211_unhold_bss
(
bss_from_pub
(
bss
));
cfg80211_put_bss
(
wiphy
,
bss
);
return
;
}
...
...
@@ -131,16 +132,19 @@ void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr)
}
EXPORT_SYMBOL
(
cfg80211_auth_timeout
);
void
cfg80211_assoc_timeout
(
struct
net_device
*
dev
,
const
u8
*
addr
)
void
cfg80211_assoc_timeout
(
struct
net_device
*
dev
,
struct
cfg80211_bss
*
bss
)
{
struct
wireless_dev
*
wdev
=
dev
->
ieee80211_ptr
;
struct
wiphy
*
wiphy
=
wdev
->
wiphy
;
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wiphy
);
trace_cfg80211_send_assoc_timeout
(
dev
,
addr
);
trace_cfg80211_send_assoc_timeout
(
dev
,
bss
->
bssid
);
nl80211_send_assoc_timeout
(
rdev
,
dev
,
addr
,
GFP_KERNEL
);
nl80211_send_assoc_timeout
(
rdev
,
dev
,
bss
->
bssid
,
GFP_KERNEL
);
cfg80211_sme_assoc_timeout
(
wdev
);
cfg80211_unhold_bss
(
bss_from_pub
(
bss
));
cfg80211_put_bss
(
wiphy
,
bss
);
}
EXPORT_SYMBOL
(
cfg80211_assoc_timeout
);
...
...
@@ -307,6 +311,8 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
goto
out
;
err
=
rdev_assoc
(
rdev
,
dev
,
req
);
if
(
!
err
)
cfg80211_hold_bss
(
bss_from_pub
(
req
->
bss
));
out:
if
(
err
)
...
...
net/wireless/nl80211.c
浏览文件 @
66ba271a
...
...
@@ -1111,10 +1111,16 @@ nl80211_send_mgmt_stypes(struct sk_buff *msg,
return
0
;
}
struct
nl80211_dump_wiphy_state
{
s64
filter_wiphy
;
long
start
;
long
split_start
,
band_start
,
chan_start
;
bool
split
;
};
static
int
nl80211_send_wiphy
(
struct
cfg80211_registered_device
*
dev
,
struct
sk_buff
*
msg
,
u32
portid
,
u32
seq
,
int
flags
,
bool
split
,
long
*
split_start
,
long
*
band_start
,
long
*
chan_start
)
int
flags
,
struct
nl80211_dump_wiphy_state
*
state
)
{
void
*
hdr
;
struct
nlattr
*
nl_bands
,
*
nl_band
;
...
...
@@ -1125,19 +1131,14 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
int
i
;
const
struct
ieee80211_txrx_stypes
*
mgmt_stypes
=
dev
->
wiphy
.
mgmt_stypes
;
long
start
=
0
,
start_chan
=
0
,
start_band
=
0
;
u32
features
;
hdr
=
nl80211hdr_put
(
msg
,
portid
,
seq
,
flags
,
NL80211_CMD_NEW_WIPHY
);
if
(
!
hdr
)
return
-
ENOBUFS
;
/* allow always using the variables */
if
(
!
split
)
{
split_start
=
&
start
;
band_start
=
&
start_band
;
chan_start
=
&
start_chan
;
}
if
(
WARN_ON
(
!
state
))
return
-
EINVAL
;
if
(
nla_put_u32
(
msg
,
NL80211_ATTR_WIPHY
,
dev
->
wiphy_idx
)
||
nla_put_string
(
msg
,
NL80211_ATTR_WIPHY_NAME
,
...
...
@@ -1146,7 +1147,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
cfg80211_rdev_list_generation
))
goto
nla_put_failure
;
switch
(
*
split_start
)
{
switch
(
state
->
split_start
)
{
case
0
:
if
(
nla_put_u8
(
msg
,
NL80211_ATTR_WIPHY_RETRY_SHORT
,
dev
->
wiphy
.
retry_short
)
||
...
...
@@ -1188,9 +1189,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
if
((
dev
->
wiphy
.
flags
&
WIPHY_FLAG_TDLS_EXTERNAL_SETUP
)
&&
nla_put_flag
(
msg
,
NL80211_ATTR_TDLS_EXTERNAL_SETUP
))
goto
nla_put_failure
;
if
((
dev
->
wiphy
.
flags
&
WIPHY_FLAG_SUPPORTS_5_10_MHZ
)
&&
nla_put_flag
(
msg
,
WIPHY_FLAG_SUPPORTS_5_10_MHZ
))
goto
nla_put_failure
;
(
*
split_start
)
++
;
if
(
split
)
state
->
split_start
++
;
if
(
s
tate
->
s
plit
)
break
;
case
1
:
if
(
nla_put
(
msg
,
NL80211_ATTR_CIPHER_SUITES
,
...
...
@@ -1234,22 +1238,23 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
}
}
(
*
split_start
)
++
;
if
(
split
)
state
->
split_start
++
;
if
(
s
tate
->
s
plit
)
break
;
case
2
:
if
(
nl80211_put_iftypes
(
msg
,
NL80211_ATTR_SUPPORTED_IFTYPES
,
dev
->
wiphy
.
interface_modes
))
goto
nla_put_failure
;
(
*
split_start
)
++
;
if
(
split
)
state
->
split_start
++
;
if
(
s
tate
->
s
plit
)
break
;
case
3
:
nl_bands
=
nla_nest_start
(
msg
,
NL80211_ATTR_WIPHY_BANDS
);
if
(
!
nl_bands
)
goto
nla_put_failure
;
for
(
band
=
*
band_start
;
band
<
IEEE80211_NUM_BANDS
;
band
++
)
{
for
(
band
=
state
->
band_start
;
band
<
IEEE80211_NUM_BANDS
;
band
++
)
{
struct
ieee80211_supported_band
*
sband
;
sband
=
dev
->
wiphy
.
bands
[
band
];
...
...
@@ -1261,12 +1266,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
if
(
!
nl_band
)
goto
nla_put_failure
;
switch
(
*
chan_start
)
{
switch
(
state
->
chan_start
)
{
case
0
:
if
(
nl80211_send_band_rateinfo
(
msg
,
sband
))
goto
nla_put_failure
;
(
*
chan_start
)
++
;
if
(
split
)
state
->
chan_start
++
;
if
(
s
tate
->
s
plit
)
break
;
default:
/* add frequencies */
...
...
@@ -1275,7 +1280,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
if
(
!
nl_freqs
)
goto
nla_put_failure
;
for
(
i
=
*
chan_start
-
1
;
for
(
i
=
state
->
chan_start
-
1
;
i
<
sband
->
n_channels
;
i
++
)
{
nl_freq
=
nla_nest_start
(
msg
,
i
);
...
...
@@ -1284,26 +1289,27 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
chan
=
&
sband
->
channels
[
i
];
if
(
nl80211_msg_put_channel
(
msg
,
chan
,
split
))
if
(
nl80211_msg_put_channel
(
msg
,
chan
,
state
->
split
))
goto
nla_put_failure
;
nla_nest_end
(
msg
,
nl_freq
);
if
(
split
)
if
(
s
tate
->
s
plit
)
break
;
}
if
(
i
<
sband
->
n_channels
)
*
chan_start
=
i
+
2
;
state
->
chan_start
=
i
+
2
;
else
*
chan_start
=
0
;
state
->
chan_start
=
0
;
nla_nest_end
(
msg
,
nl_freqs
);
}
nla_nest_end
(
msg
,
nl_band
);
if
(
split
)
{
if
(
s
tate
->
s
plit
)
{
/* start again here */
if
(
*
chan_start
)
if
(
state
->
chan_start
)
band
--
;
break
;
}
...
...
@@ -1311,14 +1317,14 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
nla_nest_end
(
msg
,
nl_bands
);
if
(
band
<
IEEE80211_NUM_BANDS
)
*
band_start
=
band
+
1
;
state
->
band_start
=
band
+
1
;
else
*
band_start
=
0
;
state
->
band_start
=
0
;
/* if bands & channels are done, continue outside */
if
(
*
band_start
==
0
&&
*
chan_start
==
0
)
(
*
split_start
)
++
;
if
(
split
)
if
(
state
->
band_start
==
0
&&
state
->
chan_start
==
0
)
state
->
split_start
++
;
if
(
s
tate
->
s
plit
)
break
;
case
4
:
nl_cmds
=
nla_nest_start
(
msg
,
NL80211_ATTR_SUPPORTED_COMMANDS
);
...
...
@@ -1384,7 +1390,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
}
CMD
(
start_p2p_device
,
START_P2P_DEVICE
);
CMD
(
set_mcast_rate
,
SET_MCAST_RATE
);
if
(
split
)
{
if
(
s
tate
->
s
plit
)
{
CMD
(
crit_proto_start
,
CRIT_PROTOCOL_START
);
CMD
(
crit_proto_stop
,
CRIT_PROTOCOL_STOP
);
}
...
...
@@ -1408,8 +1414,8 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
}
nla_nest_end
(
msg
,
nl_cmds
);
(
*
split_start
)
++
;
if
(
split
)
state
->
split_start
++
;
if
(
s
tate
->
s
plit
)
break
;
case
5
:
if
(
dev
->
ops
->
remain_on_channel
&&
...
...
@@ -1425,29 +1431,30 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
if
(
nl80211_send_mgmt_stypes
(
msg
,
mgmt_stypes
))
goto
nla_put_failure
;
(
*
split_start
)
++
;
if
(
split
)
state
->
split_start
++
;
if
(
s
tate
->
s
plit
)
break
;
case
6
:
#ifdef CONFIG_PM
if
(
nl80211_send_wowlan
(
msg
,
dev
,
split
))
if
(
nl80211_send_wowlan
(
msg
,
dev
,
s
tate
->
s
plit
))
goto
nla_put_failure
;
(
*
split_start
)
++
;
if
(
split
)
state
->
split_start
++
;
if
(
s
tate
->
s
plit
)
break
;
#else
(
*
split_start
)
++
;
state
->
split_start
++
;
#endif
case
7
:
if
(
nl80211_put_iftypes
(
msg
,
NL80211_ATTR_SOFTWARE_IFTYPES
,
dev
->
wiphy
.
software_iftypes
))
goto
nla_put_failure
;
if
(
nl80211_put_iface_combinations
(
&
dev
->
wiphy
,
msg
,
split
))
if
(
nl80211_put_iface_combinations
(
&
dev
->
wiphy
,
msg
,
state
->
split
))
goto
nla_put_failure
;
(
*
split_start
)
++
;
if
(
split
)
state
->
split_start
++
;
if
(
s
tate
->
s
plit
)
break
;
case
8
:
if
((
dev
->
wiphy
.
flags
&
WIPHY_FLAG_HAVE_AP_SME
)
&&
...
...
@@ -1461,7 +1468,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
* dump is split, otherwise it makes it too big. Therefore
* only advertise it in that case.
*/
if
(
split
)
if
(
s
tate
->
s
plit
)
features
|=
NL80211_FEATURE_ADVERTISE_CHAN_LIMITS
;
if
(
nla_put_u32
(
msg
,
NL80211_ATTR_FEATURE_FLAGS
,
features
))
goto
nla_put_failure
;
...
...
@@ -1488,7 +1495,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
* case we'll continue with more data in the next round,
* but break unconditionally so unsplit data stops here.
*/
(
*
split_start
)
++
;
state
->
split_start
++
;
break
;
case
9
:
if
(
dev
->
wiphy
.
extended_capabilities
&&
...
...
@@ -1507,7 +1514,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
goto
nla_put_failure
;
/* done */
*
split_start
=
0
;
state
->
split_start
=
0
;
break
;
}
return
genlmsg_end
(
msg
,
hdr
);
...
...
@@ -1517,59 +1524,76 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
return
-
EMSGSIZE
;
}
static
int
nl80211_dump_wiphy_parse
(
struct
sk_buff
*
skb
,
struct
netlink_callback
*
cb
,
struct
nl80211_dump_wiphy_state
*
state
)
{
struct
nlattr
**
tb
=
nl80211_fam
.
attrbuf
;
int
ret
=
nlmsg_parse
(
cb
->
nlh
,
GENL_HDRLEN
+
nl80211_fam
.
hdrsize
,
tb
,
nl80211_fam
.
maxattr
,
nl80211_policy
);
/* ignore parse errors for backward compatibility */
if
(
ret
)
return
0
;
state
->
split
=
tb
[
NL80211_ATTR_SPLIT_WIPHY_DUMP
];
if
(
tb
[
NL80211_ATTR_WIPHY
])
state
->
filter_wiphy
=
nla_get_u32
(
tb
[
NL80211_ATTR_WIPHY
]);
if
(
tb
[
NL80211_ATTR_WDEV
])
state
->
filter_wiphy
=
nla_get_u64
(
tb
[
NL80211_ATTR_WDEV
])
>>
32
;
if
(
tb
[
NL80211_ATTR_IFINDEX
])
{
struct
net_device
*
netdev
;
struct
cfg80211_registered_device
*
rdev
;
int
ifidx
=
nla_get_u32
(
tb
[
NL80211_ATTR_IFINDEX
]);
netdev
=
dev_get_by_index
(
sock_net
(
skb
->
sk
),
ifidx
);
if
(
!
netdev
)
return
-
ENODEV
;
if
(
netdev
->
ieee80211_ptr
)
{
rdev
=
wiphy_to_dev
(
netdev
->
ieee80211_ptr
->
wiphy
);
state
->
filter_wiphy
=
rdev
->
wiphy_idx
;
}
dev_put
(
netdev
);
}
return
0
;
}
static
int
nl80211_dump_wiphy
(
struct
sk_buff
*
skb
,
struct
netlink_callback
*
cb
)
{
int
idx
=
0
,
ret
;
int
start
=
cb
->
args
[
0
];
struct
nl80211_dump_wiphy_state
*
state
=
(
void
*
)
cb
->
args
[
0
];
struct
cfg80211_registered_device
*
dev
;
s64
filter_wiphy
=
-
1
;
bool
split
=
false
;
struct
nlattr
**
tb
=
nl80211_fam
.
attrbuf
;
int
res
;
rtnl_lock
();
res
=
nlmsg_parse
(
cb
->
nlh
,
GENL_HDRLEN
+
nl80211_fam
.
hdrsize
,
tb
,
nl80211_fam
.
maxattr
,
nl80211_policy
);
if
(
res
==
0
)
{
split
=
tb
[
NL80211_ATTR_SPLIT_WIPHY_DUMP
];
if
(
tb
[
NL80211_ATTR_WIPHY
])
filter_wiphy
=
nla_get_u32
(
tb
[
NL80211_ATTR_WIPHY
]);
if
(
tb
[
NL80211_ATTR_WDEV
])
filter_wiphy
=
nla_get_u64
(
tb
[
NL80211_ATTR_WDEV
])
>>
32
;
if
(
tb
[
NL80211_ATTR_IFINDEX
])
{
struct
net_device
*
netdev
;
int
ifidx
=
nla_get_u32
(
tb
[
NL80211_ATTR_IFINDEX
]);
netdev
=
dev_get_by_index
(
sock_net
(
skb
->
sk
),
ifidx
);
if
(
!
netdev
)
{
rtnl_unlock
();
return
-
ENODEV
;
}
if
(
netdev
->
ieee80211_ptr
)
{
dev
=
wiphy_to_dev
(
netdev
->
ieee80211_ptr
->
wiphy
);
filter_wiphy
=
dev
->
wiphy_idx
;
}
dev_put
(
netdev
);
if
(
!
state
)
{
state
=
kzalloc
(
sizeof
(
*
state
),
GFP_KERNEL
);
if
(
!
state
)
return
-
ENOMEM
;
state
->
filter_wiphy
=
-
1
;
ret
=
nl80211_dump_wiphy_parse
(
skb
,
cb
,
state
);
if
(
ret
)
{
kfree
(
state
);
rtnl_unlock
();
return
ret
;
}
cb
->
args
[
0
]
=
(
long
)
state
;
}
list_for_each_entry
(
dev
,
&
cfg80211_rdev_list
,
list
)
{
if
(
!
net_eq
(
wiphy_net
(
&
dev
->
wiphy
),
sock_net
(
skb
->
sk
)))
continue
;
if
(
++
idx
<=
start
)
if
(
++
idx
<=
sta
te
->
sta
rt
)
continue
;
if
(
filter_wiphy
!=
-
1
&&
dev
->
wiphy_idx
!=
filter_wiphy
)
if
(
state
->
filter_wiphy
!=
-
1
&&
state
->
filter_wiphy
!=
dev
->
wiphy_idx
)
continue
;
/* attempt to fit multiple wiphy data chunks into the skb */
do
{
ret
=
nl80211_send_wiphy
(
dev
,
skb
,
NETLINK_CB
(
cb
->
skb
).
portid
,
cb
->
nlh
->
nlmsg_seq
,
NLM_F_MULTI
,
split
,
&
cb
->
args
[
1
],
&
cb
->
args
[
2
],
&
cb
->
args
[
3
]);
NLM_F_MULTI
,
state
);
if
(
ret
<
0
)
{
/*
* If sending the wiphy data didn't fit (ENOBUFS
...
...
@@ -1594,27 +1618,34 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
idx
--
;
break
;
}
}
while
(
cb
->
args
[
1
]
>
0
);
}
while
(
state
->
split_start
>
0
);
break
;
}
rtnl_unlock
();
cb
->
args
[
0
]
=
idx
;
state
->
start
=
idx
;
return
skb
->
len
;
}
static
int
nl80211_dump_wiphy_done
(
struct
netlink_callback
*
cb
)
{
kfree
((
void
*
)
cb
->
args
[
0
]);
return
0
;
}
static
int
nl80211_get_wiphy
(
struct
sk_buff
*
skb
,
struct
genl_info
*
info
)
{
struct
sk_buff
*
msg
;
struct
cfg80211_registered_device
*
dev
=
info
->
user_ptr
[
0
];
struct
nl80211_dump_wiphy_state
state
=
{};
msg
=
nlmsg_new
(
4096
,
GFP_KERNEL
);
if
(
!
msg
)
return
-
ENOMEM
;
if
(
nl80211_send_wiphy
(
dev
,
msg
,
info
->
snd_portid
,
info
->
snd_seq
,
0
,
false
,
NULL
,
NULL
,
NULL
)
<
0
)
{
&
state
)
<
0
)
{
nlmsg_free
(
msg
);
return
-
ENOBUFS
;
}
...
...
@@ -1731,6 +1762,11 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
IEEE80211_CHAN_DISABLED
))
return
-
EINVAL
;
if
((
chandef
->
width
==
NL80211_CHAN_WIDTH_5
||
chandef
->
width
==
NL80211_CHAN_WIDTH_10
)
&&
!
(
rdev
->
wiphy
.
flags
&
WIPHY_FLAG_SUPPORTS_5_10_MHZ
))
return
-
EINVAL
;
return
0
;
}
...
...
@@ -2882,61 +2918,58 @@ static int nl80211_set_mac_acl(struct sk_buff *skb, struct genl_info *info)
return
err
;
}
static
int
nl80211_parse_beacon
(
struct
genl_info
*
info
,
static
int
nl80211_parse_beacon
(
struct
nlattr
*
attrs
[]
,
struct
cfg80211_beacon_data
*
bcn
)
{
bool
haveinfo
=
false
;
if
(
!
is_valid_ie_attr
(
info
->
attrs
[
NL80211_ATTR_BEACON_TAIL
])
||
!
is_valid_ie_attr
(
info
->
attrs
[
NL80211_ATTR_IE
])
||
!
is_valid_ie_attr
(
info
->
attrs
[
NL80211_ATTR_IE_PROBE_RESP
])
||
!
is_valid_ie_attr
(
info
->
attrs
[
NL80211_ATTR_IE_ASSOC_RESP
]))
if
(
!
is_valid_ie_attr
(
attrs
[
NL80211_ATTR_BEACON_TAIL
])
||
!
is_valid_ie_attr
(
attrs
[
NL80211_ATTR_IE
])
||
!
is_valid_ie_attr
(
attrs
[
NL80211_ATTR_IE_PROBE_RESP
])
||
!
is_valid_ie_attr
(
attrs
[
NL80211_ATTR_IE_ASSOC_RESP
]))
return
-
EINVAL
;
memset
(
bcn
,
0
,
sizeof
(
*
bcn
));
if
(
info
->
attrs
[
NL80211_ATTR_BEACON_HEAD
])
{
bcn
->
head
=
nla_data
(
info
->
attrs
[
NL80211_ATTR_BEACON_HEAD
]);
bcn
->
head_len
=
nla_len
(
info
->
attrs
[
NL80211_ATTR_BEACON_HEAD
]);
if
(
attrs
[
NL80211_ATTR_BEACON_HEAD
])
{
bcn
->
head
=
nla_data
(
attrs
[
NL80211_ATTR_BEACON_HEAD
]);
bcn
->
head_len
=
nla_len
(
attrs
[
NL80211_ATTR_BEACON_HEAD
]);
if
(
!
bcn
->
head_len
)
return
-
EINVAL
;
haveinfo
=
true
;
}
if
(
info
->
attrs
[
NL80211_ATTR_BEACON_TAIL
])
{
bcn
->
tail
=
nla_data
(
info
->
attrs
[
NL80211_ATTR_BEACON_TAIL
]);
bcn
->
tail_len
=
nla_len
(
info
->
attrs
[
NL80211_ATTR_BEACON_TAIL
]);
if
(
attrs
[
NL80211_ATTR_BEACON_TAIL
])
{
bcn
->
tail
=
nla_data
(
attrs
[
NL80211_ATTR_BEACON_TAIL
]);
bcn
->
tail_len
=
nla_len
(
attrs
[
NL80211_ATTR_BEACON_TAIL
]);
haveinfo
=
true
;
}
if
(
!
haveinfo
)
return
-
EINVAL
;
if
(
info
->
attrs
[
NL80211_ATTR_IE
])
{
bcn
->
beacon_ies
=
nla_data
(
info
->
attrs
[
NL80211_ATTR_IE
]);
bcn
->
beacon_ies_len
=
nla_len
(
info
->
attrs
[
NL80211_ATTR_IE
]);
if
(
attrs
[
NL80211_ATTR_IE
])
{
bcn
->
beacon_ies
=
nla_data
(
attrs
[
NL80211_ATTR_IE
]);
bcn
->
beacon_ies_len
=
nla_len
(
attrs
[
NL80211_ATTR_IE
]);
}
if
(
info
->
attrs
[
NL80211_ATTR_IE_PROBE_RESP
])
{
if
(
attrs
[
NL80211_ATTR_IE_PROBE_RESP
])
{
bcn
->
proberesp_ies
=
nla_data
(
info
->
attrs
[
NL80211_ATTR_IE_PROBE_RESP
]);
nla_data
(
attrs
[
NL80211_ATTR_IE_PROBE_RESP
]);
bcn
->
proberesp_ies_len
=
nla_len
(
info
->
attrs
[
NL80211_ATTR_IE_PROBE_RESP
]);
nla_len
(
attrs
[
NL80211_ATTR_IE_PROBE_RESP
]);
}
if
(
info
->
attrs
[
NL80211_ATTR_IE_ASSOC_RESP
])
{
if
(
attrs
[
NL80211_ATTR_IE_ASSOC_RESP
])
{
bcn
->
assocresp_ies
=
nla_data
(
info
->
attrs
[
NL80211_ATTR_IE_ASSOC_RESP
]);
nla_data
(
attrs
[
NL80211_ATTR_IE_ASSOC_RESP
]);
bcn
->
assocresp_ies_len
=
nla_len
(
info
->
attrs
[
NL80211_ATTR_IE_ASSOC_RESP
]);
nla_len
(
attrs
[
NL80211_ATTR_IE_ASSOC_RESP
]);
}
if
(
info
->
attrs
[
NL80211_ATTR_PROBE_RESP
])
{
bcn
->
probe_resp
=
nla_data
(
info
->
attrs
[
NL80211_ATTR_PROBE_RESP
]);
bcn
->
probe_resp_len
=
nla_len
(
info
->
attrs
[
NL80211_ATTR_PROBE_RESP
]);
if
(
attrs
[
NL80211_ATTR_PROBE_RESP
])
{
bcn
->
probe_resp
=
nla_data
(
attrs
[
NL80211_ATTR_PROBE_RESP
]);
bcn
->
probe_resp_len
=
nla_len
(
attrs
[
NL80211_ATTR_PROBE_RESP
]);
}
return
0
;
...
...
@@ -3015,7 +3048,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
!
info
->
attrs
[
NL80211_ATTR_BEACON_HEAD
])
return
-
EINVAL
;
err
=
nl80211_parse_beacon
(
info
,
&
params
.
beacon
);
err
=
nl80211_parse_beacon
(
info
->
attrs
,
&
params
.
beacon
);
if
(
err
)
return
err
;
...
...
@@ -3167,7 +3200,7 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
if
(
!
wdev
->
beacon_interval
)
return
-
EINVAL
;
err
=
nl80211_parse_beacon
(
info
,
&
params
);
err
=
nl80211_parse_beacon
(
info
->
attrs
,
&
params
);
if
(
err
)
return
err
;
...
...
@@ -6283,11 +6316,16 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
if
(
!
cfg80211_reg_can_beacon
(
&
rdev
->
wiphy
,
&
ibss
.
chandef
))
return
-
EINVAL
;
if
(
ibss
.
chandef
.
width
>
NL80211_CHAN_WIDTH_40
)
return
-
EINVAL
;
if
(
ibss
.
chandef
.
width
!=
NL80211_CHAN_WIDTH_20_NOHT
&&
!
(
rdev
->
wiphy
.
features
&
NL80211_FEATURE_HT_IBSS
))
switch
(
ibss
.
chandef
.
width
)
{
case
NL80211_CHAN_WIDTH_20_NOHT
:
break
;
case
NL80211_CHAN_WIDTH_20
:
case
NL80211_CHAN_WIDTH_40
:
if
(
rdev
->
wiphy
.
features
&
NL80211_FEATURE_HT_IBSS
)
break
;
default:
return
-
EINVAL
;
}
ibss
.
channel_fixed
=
!!
info
->
attrs
[
NL80211_ATTR_FREQ_FIXED
];
ibss
.
privacy
=
!!
info
->
attrs
[
NL80211_ATTR_PRIVACY
];
...
...
@@ -8401,6 +8439,7 @@ static struct genl_ops nl80211_ops[] = {
.
cmd
=
NL80211_CMD_GET_WIPHY
,
.
doit
=
nl80211_get_wiphy
,
.
dumpit
=
nl80211_dump_wiphy
,
.
done
=
nl80211_dump_wiphy_done
,
.
policy
=
nl80211_policy
,
/* can be retrieved by unprivileged users */
.
internal_flags
=
NL80211_FLAG_NEED_WIPHY
|
...
...
@@ -9021,13 +9060,13 @@ static struct genl_multicast_group nl80211_regulatory_mcgrp = {
void
nl80211_notify_dev_rename
(
struct
cfg80211_registered_device
*
rdev
)
{
struct
sk_buff
*
msg
;
struct
nl80211_dump_wiphy_state
state
=
{};
msg
=
nlmsg_new
(
NLMSG_DEFAULT_SIZE
,
GFP_KERNEL
);
if
(
!
msg
)
return
;
if
(
nl80211_send_wiphy
(
rdev
,
msg
,
0
,
0
,
0
,
false
,
NULL
,
NULL
,
NULL
)
<
0
)
{
if
(
nl80211_send_wiphy
(
rdev
,
msg
,
0
,
0
,
0
,
&
state
)
<
0
)
{
nlmsg_free
(
msg
);
return
;
}
...
...
net/wireless/scan.c
浏览文件 @
66ba271a
...
...
@@ -523,6 +523,7 @@ static int cmp_bss(struct cfg80211_bss *a,
}
}
/* Returned bss is reference counted and must be cleaned up appropriately. */
struct
cfg80211_bss
*
cfg80211_get_bss
(
struct
wiphy
*
wiphy
,
struct
ieee80211_channel
*
channel
,
const
u8
*
bssid
,
...
...
@@ -678,6 +679,7 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev,
return
true
;
}
/* Returned bss is reference counted and must be cleaned up appropriately. */
static
struct
cfg80211_internal_bss
*
cfg80211_bss_update
(
struct
cfg80211_registered_device
*
dev
,
struct
cfg80211_internal_bss
*
tmp
)
...
...
@@ -866,6 +868,7 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen,
return
channel
;
}
/* Returned bss is reference counted and must be cleaned up appropriately. */
struct
cfg80211_bss
*
cfg80211_inform_bss
(
struct
wiphy
*
wiphy
,
struct
ieee80211_channel
*
channel
,
...
...
@@ -923,6 +926,7 @@ cfg80211_inform_bss(struct wiphy *wiphy,
}
EXPORT_SYMBOL
(
cfg80211_inform_bss
);
/* Returned bss is reference counted and must be cleaned up appropriately. */
struct
cfg80211_bss
*
cfg80211_inform_bss_frame
(
struct
wiphy
*
wiphy
,
struct
ieee80211_channel
*
channel
,
...
...
net/wireless/sme.c
浏览文件 @
66ba271a
...
...
@@ -239,6 +239,7 @@ void cfg80211_conn_work(struct work_struct *work)
rtnl_unlock
();
}
/* Returned bss is reference counted and must be cleaned up appropriately. */
static
struct
cfg80211_bss
*
cfg80211_get_conn_bss
(
struct
wireless_dev
*
wdev
)
{
struct
cfg80211_registered_device
*
rdev
=
wiphy_to_dev
(
wdev
->
wiphy
);
...
...
@@ -557,6 +558,7 @@ static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
* SME event handling
*/
/* This method must consume bss one way or another */
void
__cfg80211_connect_result
(
struct
net_device
*
dev
,
const
u8
*
bssid
,
const
u8
*
req_ie
,
size_t
req_ie_len
,
const
u8
*
resp_ie
,
size_t
resp_ie_len
,
...
...
@@ -572,8 +574,10 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
ASSERT_WDEV_LOCK
(
wdev
);
if
(
WARN_ON
(
wdev
->
iftype
!=
NL80211_IFTYPE_STATION
&&
wdev
->
iftype
!=
NL80211_IFTYPE_P2P_CLIENT
))
wdev
->
iftype
!=
NL80211_IFTYPE_P2P_CLIENT
))
{
cfg80211_put_bss
(
wdev
->
wiphy
,
bss
);
return
;
}
nl80211_send_connect_result
(
wiphy_to_dev
(
wdev
->
wiphy
),
dev
,
bssid
,
req_ie
,
req_ie_len
,
...
...
@@ -615,19 +619,24 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
kfree
(
wdev
->
connect_keys
);
wdev
->
connect_keys
=
NULL
;
wdev
->
ssid_len
=
0
;
cfg80211_put_bss
(
wdev
->
wiphy
,
bss
);
if
(
bss
)
{
cfg80211_unhold_bss
(
bss_from_pub
(
bss
));
cfg80211_put_bss
(
wdev
->
wiphy
,
bss
);
}
return
;
}
if
(
!
bss
)
if
(
!
bss
)
{
WARN_ON_ONCE
(
!
wiphy_to_dev
(
wdev
->
wiphy
)
->
ops
->
connect
);
bss
=
cfg80211_get_bss
(
wdev
->
wiphy
,
NULL
,
bssid
,
wdev
->
ssid
,
wdev
->
ssid_len
,
WLAN_CAPABILITY_ESS
,
WLAN_CAPABILITY_ESS
);
if
(
WARN_ON
(
!
bss
))
return
;
if
(
WARN_ON
(
!
bss
))
return
;
cfg80211_hold_bss
(
bss_from_pub
(
bss
));
}
cfg80211_hold_bss
(
bss_from_pub
(
bss
));
wdev
->
current_bss
=
bss_from_pub
(
bss
);
cfg80211_upload_connect_keys
(
wdev
);
...
...
@@ -691,6 +700,7 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
}
EXPORT_SYMBOL
(
cfg80211_connect_result
);
/* Consumes bss object one way or another */
void
__cfg80211_roamed
(
struct
wireless_dev
*
wdev
,
struct
cfg80211_bss
*
bss
,
const
u8
*
req_ie
,
size_t
req_ie_len
,
...
...
@@ -767,6 +777,7 @@ void cfg80211_roamed(struct net_device *dev,
}
EXPORT_SYMBOL
(
cfg80211_roamed
);
/* Consumes bss object one way or another */
void
cfg80211_roamed_bss
(
struct
net_device
*
dev
,
struct
cfg80211_bss
*
bss
,
const
u8
*
req_ie
,
size_t
req_ie_len
,
const
u8
*
resp_ie
,
...
...
net/wireless/sysfs.c
浏览文件 @
66ba271a
...
...
@@ -83,6 +83,7 @@ static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env)
return
0
;
}
#ifdef CONFIG_PM
static
void
cfg80211_leave_all
(
struct
cfg80211_registered_device
*
rdev
)
{
struct
wireless_dev
*
wdev
;
...
...
@@ -91,7 +92,6 @@ 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
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录