Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
dee04cac
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看板
提交
dee04cac
编写于
4月 29, 2011
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of
git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-next-2.6
上级
ce6cac88
7cbc9bd9
变更
15
展开全部
隐藏空白更改
内联
并排
Showing
15 changed file
with
907 addition
and
504 deletion
+907
-504
include/net/bluetooth/hci.h
include/net/bluetooth/hci.h
+9
-0
include/net/bluetooth/hci_core.h
include/net/bluetooth/hci_core.h
+11
-5
include/net/bluetooth/l2cap.h
include/net/bluetooth/l2cap.h
+36
-33
include/net/bluetooth/mgmt.h
include/net/bluetooth/mgmt.h
+9
-1
net/bluetooth/cmtp/core.c
net/bluetooth/cmtp/core.c
+2
-1
net/bluetooth/hci_conn.c
net/bluetooth/hci_conn.c
+68
-10
net/bluetooth/hci_core.c
net/bluetooth/hci_core.c
+66
-9
net/bluetooth/hci_event.c
net/bluetooth/hci_event.c
+141
-22
net/bluetooth/hci_sysfs.c
net/bluetooth/hci_sysfs.c
+31
-0
net/bluetooth/hidp/core.c
net/bluetooth/hidp/core.c
+4
-2
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_core.c
+289
-299
net/bluetooth/l2cap_sock.c
net/bluetooth/l2cap_sock.c
+137
-105
net/bluetooth/mgmt.c
net/bluetooth/mgmt.c
+89
-6
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/core.c
+12
-9
net/bluetooth/rfcomm/sock.c
net/bluetooth/rfcomm/sock.c
+3
-2
未找到文件。
include/net/bluetooth/hci.h
浏览文件 @
dee04cac
...
...
@@ -246,6 +246,15 @@ enum {
#define HCI_AT_GENERAL_BONDING 0x04
#define HCI_AT_GENERAL_BONDING_MITM 0x05
/* Link Key types */
#define HCI_LK_COMBINATION 0x00
#define HCI_LK_LOCAL_UNIT 0x01
#define HCI_LK_REMOTE_UNIT 0x02
#define HCI_LK_DEBUG_COMBINATION 0x03
#define HCI_LK_UNAUTH_COMBINATION 0x04
#define HCI_LK_AUTH_COMBINATION 0x05
#define HCI_LK_CHANGED_COMBINATION 0x06
/* ----- HCI Commands ---- */
#define HCI_OP_NOP 0x0000
...
...
include/net/bluetooth/hci_core.h
浏览文件 @
dee04cac
...
...
@@ -126,6 +126,8 @@ struct hci_dev {
__u16
sniff_min_interval
;
__u16
sniff_max_interval
;
unsigned
int
auto_accept_delay
;
unsigned
long
quirks
;
atomic_t
cmd_cnt
;
...
...
@@ -226,6 +228,7 @@ struct hci_conn {
__u16
pkt_type
;
__u16
link_policy
;
__u32
link_mode
;
__u8
key_type
;
__u8
auth_type
;
__u8
sec_level
;
__u8
pending_sec_level
;
...
...
@@ -245,6 +248,7 @@ struct hci_conn {
struct
timer_list
disc_timer
;
struct
timer_list
idle_timer
;
struct
timer_list
auto_accept_timer
;
struct
work_struct
work_add
;
struct
work_struct
work_del
;
...
...
@@ -511,8 +515,8 @@ int hci_uuids_clear(struct hci_dev *hdev);
int
hci_link_keys_clear
(
struct
hci_dev
*
hdev
);
struct
link_key
*
hci_find_link_key
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
);
int
hci_add_link_key
(
struct
hci_dev
*
hdev
,
int
new_key
,
bdaddr_t
*
bdaddr
,
u8
*
key
,
u8
type
,
u8
pin_len
);
int
hci_add_link_key
(
struct
hci_dev
*
hdev
,
struct
hci_conn
*
conn
,
int
new_key
,
bdaddr_t
*
bdaddr
,
u8
*
val
,
u8
type
,
u8
pin_len
);
int
hci_remove_link_key
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
);
int
hci_remote_oob_data_clear
(
struct
hci_dev
*
hdev
);
...
...
@@ -771,15 +775,16 @@ int mgmt_index_removed(u16 index);
int
mgmt_powered
(
u16
index
,
u8
powered
);
int
mgmt_discoverable
(
u16
index
,
u8
discoverable
);
int
mgmt_connectable
(
u16
index
,
u8
connectable
);
int
mgmt_new_key
(
u16
index
,
struct
link_key
*
key
,
u8
old_key_type
);
int
mgmt_new_key
(
u16
index
,
struct
link_key
*
key
,
u8
persistent
);
int
mgmt_connected
(
u16
index
,
bdaddr_t
*
bdaddr
);
int
mgmt_disconnected
(
u16
index
,
bdaddr_t
*
bdaddr
);
int
mgmt_disconnect_failed
(
u16
index
);
int
mgmt_connect_failed
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
status
);
int
mgmt_pin_code_request
(
u16
index
,
bdaddr_t
*
bdaddr
);
int
mgmt_pin_code_request
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
secure
);
int
mgmt_pin_code_reply_complete
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
status
);
int
mgmt_pin_code_neg_reply_complete
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
status
);
int
mgmt_user_confirm_request
(
u16
index
,
bdaddr_t
*
bdaddr
,
__le32
value
);
int
mgmt_user_confirm_request
(
u16
index
,
bdaddr_t
*
bdaddr
,
__le32
value
,
u8
confirm_hint
);
int
mgmt_user_confirm_reply_complete
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
status
);
int
mgmt_user_confirm_neg_reply_complete
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
status
);
...
...
@@ -790,6 +795,7 @@ int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
int
mgmt_device_found
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
*
dev_class
,
s8
rssi
,
u8
*
eir
);
int
mgmt_remote_name
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
*
name
);
int
mgmt_discovering
(
u16
index
,
u8
discovering
);
/* HCI info for socket */
#define hci_pi(sk) ((struct hci_pinfo *) sk)
...
...
include/net/bluetooth/l2cap.h
浏览文件 @
dee04cac
...
...
@@ -284,6 +284,25 @@ struct srej_list {
struct
l2cap_chan
{
struct
sock
*
sk
;
struct
l2cap_conn
*
conn
;
__le16
psm
;
__u16
dcid
;
__u16
scid
;
__u16
imtu
;
__u16
omtu
;
__u16
flush_to
;
__u8
mode
;
__le16
sport
;
__u8
sec_level
;
__u8
role_switch
;
__u8
force_reliable
;
__u8
flushable
;
__u8
ident
;
__u8
conf_req
[
64
];
...
...
@@ -291,6 +310,15 @@ struct l2cap_chan {
__u8
num_conf_req
;
__u8
num_conf_rsp
;
__u8
fcs
;
__u8
tx_win
;
__u8
max_tx
;
__u16
retrans_timeout
;
__u16
monitor_timeout
;
__u16
mps
;
__u8
conf_state
;
__u16
conn_state
;
__u8
next_tx_seq
;
...
...
@@ -360,32 +388,6 @@ struct l2cap_conn {
struct
l2cap_pinfo
{
struct
bt_sock
bt
;
__le16
psm
;
__u16
dcid
;
__u16
scid
;
__u16
imtu
;
__u16
omtu
;
__u16
flush_to
;
__u8
mode
;
__u8
fcs
;
__u8
sec_level
;
__u8
role_switch
;
__u8
force_reliable
;
__u8
flushable
;
__u8
conf_state
;
__u8
tx_win
;
__u8
max_tx
;
__u16
retrans_timeout
;
__u16
monitor_timeout
;
__u16
mps
;
__le16
sport
;
struct
l2cap_conn
*
conn
;
struct
l2cap_chan
*
chan
;
};
...
...
@@ -439,21 +441,20 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
#define __is_sar_start(ctrl) (((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START)
extern
int
disable_ertm
;
extern
const
struct
proto_ops
l2cap_sock_ops
;
extern
struct
bt_sock_list
l2cap_sk_list
;
int
l2cap_init_sockets
(
void
);
void
l2cap_cleanup_sockets
(
void
);
void
l2cap_send_cmd
(
struct
l2cap_conn
*
conn
,
u8
ident
,
u8
code
,
u16
len
,
void
*
data
);
void
__l2cap_connect_rsp_defer
(
struct
sock
*
sk
);
void
__l2cap_connect_rsp_defer
(
struct
l2cap_chan
*
chan
);
int
__l2cap_wait_ack
(
struct
sock
*
sk
);
struct
sk_buff
*
l2cap_create_connless_pdu
(
struct
sock
*
sk
,
struct
msghdr
*
msg
,
size_t
len
);
struct
sk_buff
*
l2cap_create_basic_pdu
(
struct
sock
*
sk
,
struct
msghdr
*
msg
,
size_t
len
);
struct
sk_buff
*
l2cap_create_iframe_pdu
(
struct
sock
*
sk
,
struct
msghdr
*
msg
,
size_t
len
,
u16
control
,
u16
sdulen
);
struct
sk_buff
*
l2cap_create_connless_pdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
);
struct
sk_buff
*
l2cap_create_basic_pdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
);
struct
sk_buff
*
l2cap_create_iframe_pdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
,
u16
control
,
u16
sdulen
);
int
l2cap_sar_segment_sdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
);
void
l2cap_do_send
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
);
void
l2cap_do_send
(
struct
l2cap_chan
*
chan
,
struct
sk_buff
*
skb
);
void
l2cap_streaming_send
(
struct
l2cap_chan
*
chan
);
int
l2cap_ertm_send
(
struct
l2cap_chan
*
chan
);
...
...
@@ -465,7 +466,9 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent);
struct
sock
*
l2cap_sock_alloc
(
struct
net
*
net
,
struct
socket
*
sock
,
int
proto
,
gfp_t
prio
);
void
l2cap_send_disconn_req
(
struct
l2cap_conn
*
conn
,
struct
l2cap_chan
*
chan
,
int
err
);
struct
l2cap_chan
*
l2cap_chan_alloc
(
struct
sock
*
sk
);
void
l2cap_chan_del
(
struct
l2cap_chan
*
chan
,
int
err
);
int
l2cap_do_connect
(
struct
sock
*
sk
);
void
l2cap_chan_free
(
struct
l2cap_chan
*
chan
);
int
l2cap_chan_connect
(
struct
l2cap_chan
*
chan
);
#endif
/* __L2CAP_H */
include/net/bluetooth/mgmt.h
浏览文件 @
dee04cac
...
...
@@ -195,6 +195,10 @@ struct mgmt_cp_remove_remote_oob_data {
bdaddr_t
bdaddr
;
}
__packed
;
#define MGMT_OP_START_DISCOVERY 0x001B
#define MGMT_OP_STOP_DISCOVERY 0x001C
#define MGMT_EV_CMD_COMPLETE 0x0001
struct
mgmt_ev_cmd_complete
{
__le16
opcode
;
...
...
@@ -226,8 +230,8 @@ struct mgmt_ev_controller_error {
#define MGMT_EV_NEW_KEY 0x000A
struct
mgmt_ev_new_key
{
__u8
store_hint
;
struct
mgmt_key_info
key
;
__u8
old_key_type
;
}
__packed
;
#define MGMT_EV_CONNECTED 0x000B
...
...
@@ -249,11 +253,13 @@ struct mgmt_ev_connect_failed {
#define MGMT_EV_PIN_CODE_REQUEST 0x000E
struct
mgmt_ev_pin_code_request
{
bdaddr_t
bdaddr
;
__u8
secure
;
}
__packed
;
#define MGMT_EV_USER_CONFIRM_REQUEST 0x000F
struct
mgmt_ev_user_confirm_request
{
bdaddr_t
bdaddr
;
__u8
confirm_hint
;
__le32
value
;
}
__packed
;
...
...
@@ -281,3 +287,5 @@ struct mgmt_ev_remote_name {
bdaddr_t
bdaddr
;
__u8
name
[
MGMT_MAX_NAME_LENGTH
];
}
__packed
;
#define MGMT_EV_DISCOVERING 0x0014
net/bluetooth/cmtp/core.c
浏览文件 @
dee04cac
...
...
@@ -346,7 +346,8 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
bacpy
(
&
session
->
bdaddr
,
&
bt_sk
(
sock
->
sk
)
->
dst
);
session
->
mtu
=
min_t
(
uint
,
l2cap_pi
(
sock
->
sk
)
->
omtu
,
l2cap_pi
(
sock
->
sk
)
->
imtu
);
session
->
mtu
=
min_t
(
uint
,
l2cap_pi
(
sock
->
sk
)
->
chan
->
omtu
,
l2cap_pi
(
sock
->
sk
)
->
chan
->
imtu
);
BT_DBG
(
"mtu %d"
,
session
->
mtu
);
...
...
net/bluetooth/hci_conn.c
浏览文件 @
dee04cac
...
...
@@ -269,6 +269,19 @@ static void hci_conn_idle(unsigned long arg)
hci_conn_enter_sniff_mode
(
conn
);
}
static
void
hci_conn_auto_accept
(
unsigned
long
arg
)
{
struct
hci_conn
*
conn
=
(
void
*
)
arg
;
struct
hci_dev
*
hdev
=
conn
->
hdev
;
hci_dev_lock
(
hdev
);
hci_send_cmd
(
hdev
,
HCI_OP_USER_CONFIRM_REPLY
,
sizeof
(
conn
->
dst
),
&
conn
->
dst
);
hci_dev_unlock
(
hdev
);
}
struct
hci_conn
*
hci_conn_add
(
struct
hci_dev
*
hdev
,
int
type
,
bdaddr_t
*
dst
)
{
struct
hci_conn
*
conn
;
...
...
@@ -287,6 +300,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
conn
->
auth_type
=
HCI_AT_GENERAL_BONDING
;
conn
->
io_capability
=
hdev
->
io_capability
;
conn
->
remote_auth
=
0xff
;
conn
->
key_type
=
0xff
;
conn
->
power_save
=
1
;
conn
->
disc_timeout
=
HCI_DISCONN_TIMEOUT
;
...
...
@@ -311,6 +325,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
setup_timer
(
&
conn
->
disc_timer
,
hci_conn_timeout
,
(
unsigned
long
)
conn
);
setup_timer
(
&
conn
->
idle_timer
,
hci_conn_idle
,
(
unsigned
long
)
conn
);
setup_timer
(
&
conn
->
auto_accept_timer
,
hci_conn_auto_accept
,
(
unsigned
long
)
conn
);
atomic_set
(
&
conn
->
refcnt
,
0
);
...
...
@@ -341,6 +357,8 @@ int hci_conn_del(struct hci_conn *conn)
del_timer
(
&
conn
->
disc_timer
);
del_timer
(
&
conn
->
auto_accept_timer
);
if
(
conn
->
type
==
ACL_LINK
)
{
struct
hci_conn
*
sco
=
conn
->
link
;
if
(
sco
)
...
...
@@ -535,32 +553,72 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
return
0
;
}
/* Encrypt the the link */
static
void
hci_conn_encrypt
(
struct
hci_conn
*
conn
)
{
BT_DBG
(
"conn %p"
,
conn
);
if
(
!
test_and_set_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
conn
->
pend
))
{
struct
hci_cp_set_conn_encrypt
cp
;
cp
.
handle
=
cpu_to_le16
(
conn
->
handle
);
cp
.
encrypt
=
0x01
;
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_SET_CONN_ENCRYPT
,
sizeof
(
cp
),
&
cp
);
}
}
/* Enable security */
int
hci_conn_security
(
struct
hci_conn
*
conn
,
__u8
sec_level
,
__u8
auth_type
)
{
BT_DBG
(
"conn %p"
,
conn
);
/* For sdp we don't need the link key. */
if
(
sec_level
==
BT_SECURITY_SDP
)
return
1
;
/* For non 2.1 devices and low security level we don't need the link
key. */
if
(
sec_level
==
BT_SECURITY_LOW
&&
(
!
conn
->
ssp_mode
||
!
conn
->
hdev
->
ssp_mode
))
return
1
;
if
(
conn
->
link_mode
&
HCI_LM_ENCRYPT
)
return
hci_conn_auth
(
conn
,
sec_level
,
auth_type
);
/* For other security levels we need the link key. */
if
(
!
(
conn
->
link_mode
&
HCI_LM_AUTH
))
goto
auth
;
/* An authenticated combination key has sufficient security for any
security level. */
if
(
conn
->
key_type
==
HCI_LK_AUTH_COMBINATION
)
goto
encrypt
;
/* An unauthenticated combination key has sufficient security for
security level 1 and 2. */
if
(
conn
->
key_type
==
HCI_LK_UNAUTH_COMBINATION
&&
(
sec_level
==
BT_SECURITY_MEDIUM
||
sec_level
==
BT_SECURITY_LOW
))
goto
encrypt
;
/* A combination key has always sufficient security for the security
levels 1 or 2. High security level requires the combination key
is generated using maximum PIN code length (16).
For pre 2.1 units. */
if
(
conn
->
key_type
==
HCI_LK_COMBINATION
&&
(
sec_level
!=
BT_SECURITY_HIGH
||
conn
->
pin_length
==
16
))
goto
encrypt
;
auth:
if
(
test_and_set_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
conn
->
pend
))
return
0
;
if
(
hci_conn_auth
(
conn
,
sec_level
,
auth_type
))
{
struct
hci_cp_set_conn_encrypt
cp
;
cp
.
handle
=
cpu_to_le16
(
conn
->
handle
);
cp
.
encrypt
=
1
;
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_SET_CONN_ENCRYPT
,
sizeof
(
cp
),
&
cp
);
}
hci_conn_auth
(
conn
,
sec_level
,
auth_type
);
return
0
;
encrypt:
if
(
conn
->
link_mode
&
HCI_LM_ENCRYPT
)
return
1
;
hci_conn_encrypt
(
conn
);
return
0
;
}
EXPORT_SYMBOL
(
hci_conn_security
);
...
...
net/bluetooth/hci_core.c
浏览文件 @
dee04cac
...
...
@@ -1020,18 +1020,54 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
return
NULL
;
}
int
hci_add_link_key
(
struct
hci_dev
*
hdev
,
int
new_key
,
bdaddr_t
*
bdaddr
,
u8
*
val
,
u8
type
,
u8
pin_len
)
static
int
hci_persistent_key
(
struct
hci_dev
*
hdev
,
struct
hci_conn
*
conn
,
u8
key_type
,
u8
old_key_type
)
{
/* Legacy key */
if
(
key_type
<
0x03
)
return
1
;
/* Debug keys are insecure so don't store them persistently */
if
(
key_type
==
HCI_LK_DEBUG_COMBINATION
)
return
0
;
/* Changed combination key and there's no previous one */
if
(
key_type
==
HCI_LK_CHANGED_COMBINATION
&&
old_key_type
==
0xff
)
return
0
;
/* Security mode 3 case */
if
(
!
conn
)
return
1
;
/* Neither local nor remote side had no-bonding as requirement */
if
(
conn
->
auth_type
>
0x01
&&
conn
->
remote_auth
>
0x01
)
return
1
;
/* Local side had dedicated bonding as requirement */
if
(
conn
->
auth_type
==
0x02
||
conn
->
auth_type
==
0x03
)
return
1
;
/* Remote side had dedicated bonding as requirement */
if
(
conn
->
remote_auth
==
0x02
||
conn
->
remote_auth
==
0x03
)
return
1
;
/* If none of the above criteria match, then don't store the key
* persistently */
return
0
;
}
int
hci_add_link_key
(
struct
hci_dev
*
hdev
,
struct
hci_conn
*
conn
,
int
new_key
,
bdaddr_t
*
bdaddr
,
u8
*
val
,
u8
type
,
u8
pin_len
)
{
struct
link_key
*
key
,
*
old_key
;
u8
old_key_type
;
u8
old_key_type
,
persistent
;
old_key
=
hci_find_link_key
(
hdev
,
bdaddr
);
if
(
old_key
)
{
old_key_type
=
old_key
->
type
;
key
=
old_key
;
}
else
{
old_key_type
=
0xff
;
old_key_type
=
conn
?
conn
->
key_type
:
0xff
;
key
=
kzalloc
(
sizeof
(
*
key
),
GFP_ATOMIC
);
if
(
!
key
)
return
-
ENOMEM
;
...
...
@@ -1040,16 +1076,37 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
BT_DBG
(
"%s key for %s type %u"
,
hdev
->
name
,
batostr
(
bdaddr
),
type
);
/* Some buggy controller combinations generate a changed
* combination key for legacy pairing even when there's no
* previous key */
if
(
type
==
HCI_LK_CHANGED_COMBINATION
&&
(
!
conn
||
conn
->
remote_auth
==
0xff
)
&&
old_key_type
==
0xff
)
{
type
=
HCI_LK_COMBINATION
;
if
(
conn
)
conn
->
key_type
=
type
;
}
bacpy
(
&
key
->
bdaddr
,
bdaddr
);
memcpy
(
key
->
val
,
val
,
16
);
key
->
type
=
type
;
key
->
pin_len
=
pin_len
;
if
(
new_key
)
mgmt_new_key
(
hdev
->
id
,
key
,
old_key_type
);
if
(
type
==
0x06
)
if
(
type
==
HCI_LK_CHANGED_COMBINATION
)
key
->
type
=
old_key_type
;
else
key
->
type
=
type
;
if
(
!
new_key
)
return
0
;
persistent
=
hci_persistent_key
(
hdev
,
conn
,
type
,
old_key_type
);
mgmt_new_key
(
hdev
->
id
,
key
,
persistent
);
if
(
!
persistent
)
{
list_del
(
&
key
->
list
);
kfree
(
key
);
}
return
0
;
}
...
...
net/bluetooth/hci_event.c
浏览文件 @
dee04cac
...
...
@@ -56,7 +56,9 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
if
(
status
)
return
;
clear_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
);
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
)
&&
test_and_clear_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
))
mgmt_discovering
(
hdev
->
id
,
0
);
hci_req_complete
(
hdev
,
HCI_OP_INQUIRY_CANCEL
,
status
);
...
...
@@ -72,7 +74,9 @@ static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
if
(
status
)
return
;
clear_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
);
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
)
&&
test_and_clear_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
))
mgmt_discovering
(
hdev
->
id
,
0
);
hci_conn_check_pending
(
hdev
);
}
...
...
@@ -841,10 +845,14 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
if
(
status
)
{
hci_req_complete
(
hdev
,
HCI_OP_INQUIRY
,
status
);
hci_conn_check_pending
(
hdev
);
}
else
set_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
);
return
;
}
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
)
&&
!
test_and_set_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
))
mgmt_discovering
(
hdev
->
id
,
1
);
}
static
inline
void
hci_cs_create_conn
(
struct
hci_dev
*
hdev
,
__u8
status
)
...
...
@@ -1013,12 +1021,19 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
cp
->
bdaddr
);
if
(
conn
&&
hci_outgoing_auth_needed
(
hdev
,
conn
))
{
if
(
!
conn
)
goto
unlock
;
if
(
!
hci_outgoing_auth_needed
(
hdev
,
conn
))
goto
unlock
;
if
(
!
test_and_set_bit
(
HCI_CONN_AUTH_PEND
,
&
conn
->
pend
))
{
struct
hci_cp_auth_requested
cp
;
cp
.
handle
=
__cpu_to_le16
(
conn
->
handle
);
hci_send_cmd
(
hdev
,
HCI_OP_AUTH_REQUESTED
,
sizeof
(
cp
),
&
cp
);
}
unlock:
hci_dev_unlock
(
hdev
);
}
...
...
@@ -1208,7 +1223,9 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff
BT_DBG
(
"%s status %d"
,
hdev
->
name
,
status
);
clear_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
);
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
)
&&
test_and_clear_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
))
mgmt_discovering
(
hdev
->
id
,
0
);
hci_req_complete
(
hdev
,
HCI_OP_INQUIRY
,
status
);
...
...
@@ -1228,6 +1245,12 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
hci_dev_lock
(
hdev
);
if
(
!
test_and_set_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
))
{
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
mgmt_discovering
(
hdev
->
id
,
1
);
}
for
(;
num_rsp
;
num_rsp
--
,
info
++
)
{
bacpy
(
&
data
.
bdaddr
,
&
info
->
bdaddr
);
data
.
pscan_rep_mode
=
info
->
pscan_rep_mode
;
...
...
@@ -1443,7 +1466,6 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
conn
->
sec_level
=
conn
->
pending_sec_level
;
}
else
{
mgmt_auth_failed
(
hdev
->
id
,
&
conn
->
dst
,
ev
->
status
);
conn
->
sec_level
=
BT_SECURITY_LOW
;
}
clear_bit
(
HCI_CONN_AUTH_PEND
,
&
conn
->
pend
);
...
...
@@ -1501,12 +1523,19 @@ static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb
mgmt_remote_name
(
hdev
->
id
,
&
ev
->
bdaddr
,
ev
->
name
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
ev
->
bdaddr
);
if
(
conn
&&
hci_outgoing_auth_needed
(
hdev
,
conn
))
{
if
(
!
conn
)
goto
unlock
;
if
(
!
hci_outgoing_auth_needed
(
hdev
,
conn
))
goto
unlock
;
if
(
!
test_and_set_bit
(
HCI_CONN_AUTH_PEND
,
&
conn
->
pend
))
{
struct
hci_cp_auth_requested
cp
;
cp
.
handle
=
__cpu_to_le16
(
conn
->
handle
);
hci_send_cmd
(
hdev
,
HCI_OP_AUTH_REQUESTED
,
sizeof
(
cp
),
&
cp
);
}
unlock:
hci_dev_unlock
(
hdev
);
}
...
...
@@ -2006,9 +2035,16 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff
if
(
!
test_bit
(
HCI_PAIRABLE
,
&
hdev
->
flags
))
hci_send_cmd
(
hdev
,
HCI_OP_PIN_CODE_NEG_REPLY
,
sizeof
(
ev
->
bdaddr
),
&
ev
->
bdaddr
);
else
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
{
u8
secure
;
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
mgmt_pin_code_request
(
hdev
->
id
,
&
ev
->
bdaddr
);
if
(
conn
->
pending_sec_level
==
BT_SECURITY_HIGH
)
secure
=
1
;
else
secure
=
0
;
mgmt_pin_code_request
(
hdev
->
id
,
&
ev
->
bdaddr
,
secure
);
}
hci_dev_unlock
(
hdev
);
}
...
...
@@ -2037,17 +2073,30 @@ static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff
BT_DBG
(
"%s found key type %u for %s"
,
hdev
->
name
,
key
->
type
,
batostr
(
&
ev
->
bdaddr
));
if
(
!
test_bit
(
HCI_DEBUG_KEYS
,
&
hdev
->
flags
)
&&
key
->
type
==
0x03
)
{
if
(
!
test_bit
(
HCI_DEBUG_KEYS
,
&
hdev
->
flags
)
&&
key
->
type
==
HCI_LK_DEBUG_COMBINATION
)
{
BT_DBG
(
"%s ignoring debug key"
,
hdev
->
name
);
goto
not_found
;
}
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
ev
->
bdaddr
);
if
(
conn
)
{
if
(
key
->
type
==
HCI_LK_UNAUTH_COMBINATION
&&
conn
->
auth_type
!=
0xff
&&
(
conn
->
auth_type
&
0x01
))
{
BT_DBG
(
"%s ignoring unauthenticated key"
,
hdev
->
name
);
goto
not_found
;
}
if
(
key
->
type
==
0x04
&&
conn
&&
conn
->
auth_type
!=
0xff
&&
(
conn
->
auth_type
&
0x01
))
{
BT_DBG
(
"%s ignoring unauthenticated key"
,
hdev
->
name
);
goto
not_found
;
if
(
key
->
type
==
HCI_LK_COMBINATION
&&
key
->
pin_len
<
16
&&
conn
->
pending_sec_level
==
BT_SECURITY_HIGH
)
{
BT_DBG
(
"%s ignoring key unauthenticated for high \
security"
,
hdev
->
name
);
goto
not_found
;
}
conn
->
key_type
=
key
->
type
;
conn
->
pin_length
=
key
->
pin_len
;
}
bacpy
(
&
cp
.
bdaddr
,
&
ev
->
bdaddr
);
...
...
@@ -2079,11 +2128,15 @@ static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff
hci_conn_hold
(
conn
);
conn
->
disc_timeout
=
HCI_DISCONN_TIMEOUT
;
pin_len
=
conn
->
pin_length
;
if
(
ev
->
key_type
!=
HCI_LK_CHANGED_COMBINATION
)
conn
->
key_type
=
ev
->
key_type
;
hci_conn_put
(
conn
);
}
if
(
test_bit
(
HCI_LINK_KEYS
,
&
hdev
->
flags
))
hci_add_link_key
(
hdev
,
1
,
&
ev
->
bdaddr
,
ev
->
link_key
,
hci_add_link_key
(
hdev
,
conn
,
1
,
&
ev
->
bdaddr
,
ev
->
link_key
,
ev
->
key_type
,
pin_len
);
hci_dev_unlock
(
hdev
);
...
...
@@ -2158,6 +2211,12 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
hci_dev_lock
(
hdev
);
if
(
!
test_and_set_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
))
{
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
mgmt_discovering
(
hdev
->
id
,
1
);
}
if
((
skb
->
len
-
1
)
/
num_rsp
!=
sizeof
(
struct
inquiry_info_with_rssi
))
{
struct
inquiry_info_with_rssi_and_pscan_mode
*
info
;
info
=
(
void
*
)
(
skb
->
data
+
1
);
...
...
@@ -2320,6 +2379,12 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
if
(
!
num_rsp
)
return
;
if
(
!
test_and_set_bit
(
HCI_INQUIRY
,
&
hdev
->
flags
))
{
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
mgmt_discovering
(
hdev
->
id
,
1
);
}
hci_dev_lock
(
hdev
);
for
(;
num_rsp
;
num_rsp
--
,
info
++
)
{
...
...
@@ -2353,7 +2418,7 @@ static inline u8 hci_get_auth_req(struct hci_conn *conn)
/* If remote requests no-bonding follow that lead */
if
(
conn
->
remote_auth
==
0x00
||
conn
->
remote_auth
==
0x01
)
return
0x00
;
return
conn
->
remote_auth
|
(
conn
->
auth_type
&
0x01
)
;
return
conn
->
auth_type
;
}
...
...
@@ -2382,7 +2447,8 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff
bacpy
(
&
cp
.
bdaddr
,
&
ev
->
bdaddr
);
cp
.
capability
=
conn
->
io_capability
;
cp
.
authentication
=
hci_get_auth_req
(
conn
);
conn
->
auth_type
=
hci_get_auth_req
(
conn
);
cp
.
authentication
=
conn
->
auth_type
;
if
((
conn
->
out
==
0x01
||
conn
->
remote_oob
==
0x01
)
&&
hci_find_remote_oob_data
(
hdev
,
&
conn
->
dst
))
...
...
@@ -2396,7 +2462,7 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff
struct
hci_cp_io_capability_neg_reply
cp
;
bacpy
(
&
cp
.
bdaddr
,
&
ev
->
bdaddr
);
cp
.
reason
=
0x1
6
;
/* Pairing not allowed */
cp
.
reason
=
0x1
8
;
/* Pairing not allowed */
hci_send_cmd
(
hdev
,
HCI_OP_IO_CAPABILITY_NEG_REPLY
,
sizeof
(
cp
),
&
cp
);
...
...
@@ -2431,14 +2497,67 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
struct
sk_buff
*
skb
)
{
struct
hci_ev_user_confirm_req
*
ev
=
(
void
*
)
skb
->
data
;
int
loc_mitm
,
rem_mitm
,
confirm_hint
=
0
;
struct
hci_conn
*
conn
;
BT_DBG
(
"%s"
,
hdev
->
name
);
hci_dev_lock
(
hdev
);
if
(
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
mgmt_user_confirm_request
(
hdev
->
id
,
&
ev
->
bdaddr
,
ev
->
passkey
);
if
(
!
test_bit
(
HCI_MGMT
,
&
hdev
->
flags
))
goto
unlock
;
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
ev
->
bdaddr
);
if
(
!
conn
)
goto
unlock
;
loc_mitm
=
(
conn
->
auth_type
&
0x01
);
rem_mitm
=
(
conn
->
remote_auth
&
0x01
);
/* If we require MITM but the remote device can't provide that
* (it has NoInputNoOutput) then reject the confirmation
* request. The only exception is when we're dedicated bonding
* initiators (connect_cfm_cb set) since then we always have the MITM
* bit set. */
if
(
!
conn
->
connect_cfm_cb
&&
loc_mitm
&&
conn
->
remote_cap
==
0x03
)
{
BT_DBG
(
"Rejecting request: remote device can't provide MITM"
);
hci_send_cmd
(
hdev
,
HCI_OP_USER_CONFIRM_NEG_REPLY
,
sizeof
(
ev
->
bdaddr
),
&
ev
->
bdaddr
);
goto
unlock
;
}
/* If no side requires MITM protection; auto-accept */
if
((
!
loc_mitm
||
conn
->
remote_cap
==
0x03
)
&&
(
!
rem_mitm
||
conn
->
io_capability
==
0x03
))
{
/* If we're not the initiators request authorization to
* proceed from user space (mgmt_user_confirm with
* confirm_hint set to 1). */
if
(
!
test_bit
(
HCI_CONN_AUTH_PEND
,
&
conn
->
pend
))
{
BT_DBG
(
"Confirming auto-accept as acceptor"
);
confirm_hint
=
1
;
goto
confirm
;
}
BT_DBG
(
"Auto-accept of user confirmation with %ums delay"
,
hdev
->
auto_accept_delay
);
if
(
hdev
->
auto_accept_delay
>
0
)
{
int
delay
=
msecs_to_jiffies
(
hdev
->
auto_accept_delay
);
mod_timer
(
&
conn
->
auto_accept_timer
,
jiffies
+
delay
);
goto
unlock
;
}
hci_send_cmd
(
hdev
,
HCI_OP_USER_CONFIRM_REPLY
,
sizeof
(
ev
->
bdaddr
),
&
ev
->
bdaddr
);
goto
unlock
;
}
confirm:
mgmt_user_confirm_request
(
hdev
->
id
,
&
ev
->
bdaddr
,
ev
->
passkey
,
confirm_hint
);
unlock:
hci_dev_unlock
(
hdev
);
}
...
...
net/bluetooth/hci_sysfs.c
浏览文件 @
dee04cac
...
...
@@ -511,6 +511,35 @@ static const struct file_operations uuids_fops = {
.
release
=
single_release
,
};
static
int
auto_accept_delay_set
(
void
*
data
,
u64
val
)
{
struct
hci_dev
*
hdev
=
data
;
hci_dev_lock_bh
(
hdev
);
hdev
->
auto_accept_delay
=
val
;
hci_dev_unlock_bh
(
hdev
);
return
0
;
}
static
int
auto_accept_delay_get
(
void
*
data
,
u64
*
val
)
{
struct
hci_dev
*
hdev
=
data
;
hci_dev_lock_bh
(
hdev
);
*
val
=
hdev
->
auto_accept_delay
;
hci_dev_unlock_bh
(
hdev
);
return
0
;
}
DEFINE_SIMPLE_ATTRIBUTE
(
auto_accept_delay_fops
,
auto_accept_delay_get
,
auto_accept_delay_set
,
"%llu
\n
"
);
int
hci_register_sysfs
(
struct
hci_dev
*
hdev
)
{
struct
device
*
dev
=
&
hdev
->
dev
;
...
...
@@ -545,6 +574,8 @@ int hci_register_sysfs(struct hci_dev *hdev)
debugfs_create_file
(
"uuids"
,
0444
,
hdev
->
debugfs
,
hdev
,
&
uuids_fops
);
debugfs_create_file
(
"auto_accept_delay"
,
0444
,
hdev
->
debugfs
,
hdev
,
&
auto_accept_delay_fops
);
return
0
;
}
...
...
net/bluetooth/hidp/core.c
浏览文件 @
dee04cac
...
...
@@ -979,8 +979,10 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
bacpy
(
&
session
->
bdaddr
,
&
bt_sk
(
ctrl_sock
->
sk
)
->
dst
);
session
->
ctrl_mtu
=
min_t
(
uint
,
l2cap_pi
(
ctrl_sock
->
sk
)
->
omtu
,
l2cap_pi
(
ctrl_sock
->
sk
)
->
imtu
);
session
->
intr_mtu
=
min_t
(
uint
,
l2cap_pi
(
intr_sock
->
sk
)
->
omtu
,
l2cap_pi
(
intr_sock
->
sk
)
->
imtu
);
session
->
ctrl_mtu
=
min_t
(
uint
,
l2cap_pi
(
ctrl_sock
->
sk
)
->
chan
->
omtu
,
l2cap_pi
(
ctrl_sock
->
sk
)
->
chan
->
imtu
);
session
->
intr_mtu
=
min_t
(
uint
,
l2cap_pi
(
intr_sock
->
sk
)
->
chan
->
omtu
,
l2cap_pi
(
intr_sock
->
sk
)
->
chan
->
imtu
);
BT_DBG
(
"ctrl mtu %d intr mtu %d"
,
session
->
ctrl_mtu
,
session
->
intr_mtu
);
...
...
net/bluetooth/l2cap_core.c
浏览文件 @
dee04cac
此差异已折叠。
点击以展开。
net/bluetooth/l2cap_sock.c
浏览文件 @
dee04cac
...
...
@@ -30,6 +30,8 @@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
static
const
struct
proto_ops
l2cap_sock_ops
;
/* ---- L2CAP timers ---- */
static
void
l2cap_sock_timeout
(
unsigned
long
arg
)
{
...
...
@@ -51,7 +53,7 @@ static void l2cap_sock_timeout(unsigned long arg)
if
(
sk
->
sk_state
==
BT_CONNECTED
||
sk
->
sk_state
==
BT_CONFIG
)
reason
=
ECONNREFUSED
;
else
if
(
sk
->
sk_state
==
BT_CONNECT
&&
l2cap_pi
(
sk
)
->
sec_level
!=
BT_SECURITY_SDP
)
l2cap_pi
(
sk
)
->
chan
->
sec_level
!=
BT_SECURITY_SDP
)
reason
=
ECONNREFUSED
;
else
reason
=
ETIMEDOUT
;
...
...
@@ -80,9 +82,13 @@ static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
{
struct
sock
*
sk
;
struct
hlist_node
*
node
;
sk_for_each
(
sk
,
node
,
&
l2cap_sk_list
.
head
)
if
(
l2cap_pi
(
sk
)
->
sport
==
psm
&&
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
src
))
sk_for_each
(
sk
,
node
,
&
l2cap_sk_list
.
head
)
{
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
if
(
chan
->
sport
==
psm
&&
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
src
))
goto
found
;
}
sk
=
NULL
;
found:
return
sk
;
...
...
@@ -91,6 +97,7 @@ static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
static
int
l2cap_sock_bind
(
struct
socket
*
sock
,
struct
sockaddr
*
addr
,
int
alen
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
struct
sockaddr_l2
la
;
int
len
,
err
=
0
;
...
...
@@ -136,17 +143,17 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
}
else
{
/* Save source address */
bacpy
(
&
bt_sk
(
sk
)
->
src
,
&
la
.
l2_bdaddr
);
l2cap_pi
(
sk
)
->
psm
=
la
.
l2_psm
;
l2cap_pi
(
sk
)
->
sport
=
la
.
l2_psm
;
chan
->
psm
=
la
.
l2_psm
;
chan
->
sport
=
la
.
l2_psm
;
sk
->
sk_state
=
BT_BOUND
;
if
(
__le16_to_cpu
(
la
.
l2_psm
)
==
0x0001
||
__le16_to_cpu
(
la
.
l2_psm
)
==
0x0003
)
l2cap_pi
(
sk
)
->
sec_level
=
BT_SECURITY_SDP
;
chan
->
sec_level
=
BT_SECURITY_SDP
;
}
if
(
la
.
l2_cid
)
l2cap_pi
(
sk
)
->
scid
=
la
.
l2_cid
;
chan
->
scid
=
la
.
l2_cid
;
write_unlock_bh
(
&
l2cap_sk_list
.
lock
);
...
...
@@ -158,6 +165,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
static
int
l2cap_sock_connect
(
struct
socket
*
sock
,
struct
sockaddr
*
addr
,
int
alen
,
int
flags
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
struct
sockaddr_l2
la
;
int
len
,
err
=
0
;
...
...
@@ -182,7 +190,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
goto
done
;
}
switch
(
l2cap_pi
(
sk
)
->
mode
)
{
switch
(
chan
->
mode
)
{
case
L2CAP_MODE_BASIC
:
break
;
case
L2CAP_MODE_ERTM
:
...
...
@@ -226,10 +234,10 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
/* Set destination address and psm */
bacpy
(
&
bt_sk
(
sk
)
->
dst
,
&
la
.
l2_bdaddr
);
l2cap_pi
(
sk
)
->
psm
=
la
.
l2_psm
;
l2cap_pi
(
sk
)
->
dcid
=
la
.
l2_cid
;
chan
->
psm
=
la
.
l2_psm
;
chan
->
dcid
=
la
.
l2_cid
;
err
=
l2cap_
do_connect
(
sk
);
err
=
l2cap_
chan_connect
(
l2cap_pi
(
sk
)
->
chan
);
if
(
err
)
goto
done
;
...
...
@@ -244,6 +252,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
static
int
l2cap_sock_listen
(
struct
socket
*
sock
,
int
backlog
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
int
err
=
0
;
BT_DBG
(
"sk %p backlog %d"
,
sk
,
backlog
);
...
...
@@ -256,7 +265,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
goto
done
;
}
switch
(
l2cap_pi
(
sk
)
->
mode
)
{
switch
(
chan
->
mode
)
{
case
L2CAP_MODE_BASIC
:
break
;
case
L2CAP_MODE_ERTM
:
...
...
@@ -269,7 +278,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
goto
done
;
}
if
(
!
l2cap_pi
(
sk
)
->
psm
&&
!
l2cap_pi
(
sk
)
->
scid
)
{
if
(
!
chan
->
psm
&&
!
chan
->
scid
)
{
bdaddr_t
*
src
=
&
bt_sk
(
sk
)
->
src
;
u16
psm
;
...
...
@@ -279,8 +288,8 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
for
(
psm
=
0x1001
;
psm
<
0x1100
;
psm
+=
2
)
if
(
!
__l2cap_get_sock_by_addr
(
cpu_to_le16
(
psm
),
src
))
{
l2cap_pi
(
sk
)
->
psm
=
cpu_to_le16
(
psm
);
l2cap_pi
(
sk
)
->
sport
=
cpu_to_le16
(
psm
);
chan
->
psm
=
cpu_to_le16
(
psm
);
chan
->
sport
=
cpu_to_le16
(
psm
);
err
=
0
;
break
;
}
...
...
@@ -360,6 +369,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
{
struct
sockaddr_l2
*
la
=
(
struct
sockaddr_l2
*
)
addr
;
struct
sock
*
sk
=
sock
->
sk
;
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
BT_DBG
(
"sock %p, sk %p"
,
sock
,
sk
);
...
...
@@ -367,13 +377,13 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
*
len
=
sizeof
(
struct
sockaddr_l2
);
if
(
peer
)
{
la
->
l2_psm
=
l2cap_pi
(
sk
)
->
psm
;
la
->
l2_psm
=
chan
->
psm
;
bacpy
(
&
la
->
l2_bdaddr
,
&
bt_sk
(
sk
)
->
dst
);
la
->
l2_cid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
dcid
);
la
->
l2_cid
=
cpu_to_le16
(
chan
->
dcid
);
}
else
{
la
->
l2_psm
=
l2cap_pi
(
sk
)
->
sport
;
la
->
l2_psm
=
chan
->
sport
;
bacpy
(
&
la
->
l2_bdaddr
,
&
bt_sk
(
sk
)
->
src
);
la
->
l2_cid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
la
->
l2_cid
=
cpu_to_le16
(
chan
->
scid
);
}
return
0
;
...
...
@@ -382,6 +392,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
static
int
l2cap_sock_getsockopt_old
(
struct
socket
*
sock
,
int
optname
,
char
__user
*
optval
,
int
__user
*
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
struct
l2cap_options
opts
;
struct
l2cap_conninfo
cinfo
;
int
len
,
err
=
0
;
...
...
@@ -397,13 +408,13 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
switch
(
optname
)
{
case
L2CAP_OPTIONS
:
memset
(
&
opts
,
0
,
sizeof
(
opts
));
opts
.
imtu
=
l2cap_pi
(
sk
)
->
imtu
;
opts
.
omtu
=
l2cap_pi
(
sk
)
->
omtu
;
opts
.
flush_to
=
l2cap_pi
(
sk
)
->
flush_to
;
opts
.
mode
=
l2cap_pi
(
sk
)
->
mode
;
opts
.
fcs
=
l2cap_pi
(
sk
)
->
fcs
;
opts
.
max_tx
=
l2cap_pi
(
sk
)
->
max_tx
;
opts
.
txwin_size
=
(
__u16
)
l2cap_pi
(
sk
)
->
tx_win
;
opts
.
imtu
=
chan
->
imtu
;
opts
.
omtu
=
chan
->
omtu
;
opts
.
flush_to
=
chan
->
flush_to
;
opts
.
mode
=
chan
->
mode
;
opts
.
fcs
=
chan
->
fcs
;
opts
.
max_tx
=
chan
->
max_tx
;
opts
.
txwin_size
=
(
__u16
)
chan
->
tx_win
;
len
=
min_t
(
unsigned
int
,
len
,
sizeof
(
opts
));
if
(
copy_to_user
(
optval
,
(
char
*
)
&
opts
,
len
))
...
...
@@ -412,7 +423,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
break
;
case
L2CAP_LM
:
switch
(
l2cap_pi
(
sk
)
->
sec_level
)
{
switch
(
chan
->
sec_level
)
{
case
BT_SECURITY_LOW
:
opt
=
L2CAP_LM_AUTH
;
break
;
...
...
@@ -428,10 +439,10 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
break
;
}
if
(
l2cap_pi
(
sk
)
->
role_switch
)
if
(
chan
->
role_switch
)
opt
|=
L2CAP_LM_MASTER
;
if
(
l2cap_pi
(
sk
)
->
force_reliable
)
if
(
chan
->
force_reliable
)
opt
|=
L2CAP_LM_RELIABLE
;
if
(
put_user
(
opt
,
(
u32
__user
*
)
optval
))
...
...
@@ -446,8 +457,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
break
;
}
cinfo
.
hci_handle
=
l2cap_pi
(
sk
)
->
conn
->
hcon
->
handle
;
memcpy
(
cinfo
.
dev_class
,
l2cap_pi
(
sk
)
->
conn
->
hcon
->
dev_class
,
3
);
cinfo
.
hci_handle
=
chan
->
conn
->
hcon
->
handle
;
memcpy
(
cinfo
.
dev_class
,
chan
->
conn
->
hcon
->
dev_class
,
3
);
len
=
min_t
(
unsigned
int
,
len
,
sizeof
(
cinfo
));
if
(
copy_to_user
(
optval
,
(
char
*
)
&
cinfo
,
len
))
...
...
@@ -467,6 +478,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
static
int
l2cap_sock_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
__user
*
optval
,
int
__user
*
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
struct
bt_security
sec
;
int
len
,
err
=
0
;
...
...
@@ -491,7 +503,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
break
;
}
sec
.
level
=
l2cap_pi
(
sk
)
->
sec_level
;
sec
.
level
=
chan
->
sec_level
;
len
=
min_t
(
unsigned
int
,
len
,
sizeof
(
sec
));
if
(
copy_to_user
(
optval
,
(
char
*
)
&
sec
,
len
))
...
...
@@ -511,7 +523,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
break
;
case
BT_FLUSHABLE
:
if
(
put_user
(
l2cap_pi
(
sk
)
->
flushable
,
(
u32
__user
*
)
optval
))
if
(
put_user
(
chan
->
flushable
,
(
u32
__user
*
)
optval
))
err
=
-
EFAULT
;
break
;
...
...
@@ -528,6 +540,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
static
int
l2cap_sock_setsockopt_old
(
struct
socket
*
sock
,
int
optname
,
char
__user
*
optval
,
unsigned
int
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
struct
l2cap_options
opts
;
int
len
,
err
=
0
;
u32
opt
;
...
...
@@ -543,13 +556,13 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
break
;
}
opts
.
imtu
=
l2cap_pi
(
sk
)
->
imtu
;
opts
.
omtu
=
l2cap_pi
(
sk
)
->
omtu
;
opts
.
flush_to
=
l2cap_pi
(
sk
)
->
flush_to
;
opts
.
mode
=
l2cap_pi
(
sk
)
->
mode
;
opts
.
fcs
=
l2cap_pi
(
sk
)
->
fcs
;
opts
.
max_tx
=
l2cap_pi
(
sk
)
->
max_tx
;
opts
.
txwin_size
=
(
__u16
)
l2cap_pi
(
sk
)
->
tx_win
;
opts
.
imtu
=
chan
->
imtu
;
opts
.
omtu
=
chan
->
omtu
;
opts
.
flush_to
=
chan
->
flush_to
;
opts
.
mode
=
chan
->
mode
;
opts
.
fcs
=
chan
->
fcs
;
opts
.
max_tx
=
chan
->
max_tx
;
opts
.
txwin_size
=
(
__u16
)
chan
->
tx_win
;
len
=
min_t
(
unsigned
int
,
sizeof
(
opts
),
optlen
);
if
(
copy_from_user
((
char
*
)
&
opts
,
optval
,
len
))
{
...
...
@@ -562,10 +575,10 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
break
;
}
l2cap_pi
(
sk
)
->
mode
=
opts
.
mode
;
switch
(
l2cap_pi
(
sk
)
->
mode
)
{
chan
->
mode
=
opts
.
mode
;
switch
(
chan
->
mode
)
{
case
L2CAP_MODE_BASIC
:
l2cap_pi
(
sk
)
->
conf_state
&=
~
L2CAP_CONF_STATE2_DEVICE
;
chan
->
conf_state
&=
~
L2CAP_CONF_STATE2_DEVICE
;
break
;
case
L2CAP_MODE_ERTM
:
case
L2CAP_MODE_STREAMING
:
...
...
@@ -577,11 +590,11 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
break
;
}
l2cap_pi
(
sk
)
->
imtu
=
opts
.
imtu
;
l2cap_pi
(
sk
)
->
omtu
=
opts
.
omtu
;
l2cap_pi
(
sk
)
->
fcs
=
opts
.
fcs
;
l2cap_pi
(
sk
)
->
max_tx
=
opts
.
max_tx
;
l2cap_pi
(
sk
)
->
tx_win
=
(
__u8
)
opts
.
txwin_size
;
chan
->
imtu
=
opts
.
imtu
;
chan
->
omtu
=
opts
.
omtu
;
chan
->
fcs
=
opts
.
fcs
;
chan
->
max_tx
=
opts
.
max_tx
;
chan
->
tx_win
=
(
__u8
)
opts
.
txwin_size
;
break
;
case
L2CAP_LM
:
...
...
@@ -591,14 +604,14 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
}
if
(
opt
&
L2CAP_LM_AUTH
)
l2cap_pi
(
sk
)
->
sec_level
=
BT_SECURITY_LOW
;
chan
->
sec_level
=
BT_SECURITY_LOW
;
if
(
opt
&
L2CAP_LM_ENCRYPT
)
l2cap_pi
(
sk
)
->
sec_level
=
BT_SECURITY_MEDIUM
;
chan
->
sec_level
=
BT_SECURITY_MEDIUM
;
if
(
opt
&
L2CAP_LM_SECURE
)
l2cap_pi
(
sk
)
->
sec_level
=
BT_SECURITY_HIGH
;
chan
->
sec_level
=
BT_SECURITY_HIGH
;
l2cap_pi
(
sk
)
->
role_switch
=
(
opt
&
L2CAP_LM_MASTER
);
l2cap_pi
(
sk
)
->
force_reliable
=
(
opt
&
L2CAP_LM_RELIABLE
);
chan
->
role_switch
=
(
opt
&
L2CAP_LM_MASTER
);
chan
->
force_reliable
=
(
opt
&
L2CAP_LM_RELIABLE
);
break
;
default:
...
...
@@ -613,6 +626,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
static
int
l2cap_sock_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
__user
*
optval
,
unsigned
int
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
struct
bt_security
sec
;
int
len
,
err
=
0
;
u32
opt
;
...
...
@@ -649,7 +663,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
break
;
}
l2cap_pi
(
sk
)
->
sec_level
=
sec
.
level
;
chan
->
sec_level
=
sec
.
level
;
break
;
case
BT_DEFER_SETUP
:
...
...
@@ -678,7 +692,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
}
if
(
opt
==
BT_FLUSHABLE_OFF
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
struct
l2cap_conn
*
conn
=
chan
->
conn
;
/* proceed futher only when we have l2cap_conn and
No Flush support in the LM */
if
(
!
conn
||
!
lmp_no_flush_capable
(
conn
->
hcon
->
hdev
))
{
...
...
@@ -687,7 +701,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
}
}
l2cap_pi
(
sk
)
->
flushable
=
opt
;
chan
->
flushable
=
opt
;
break
;
default:
...
...
@@ -702,7 +716,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
static
int
l2cap_sock_sendmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
msg
,
size_t
len
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
l2cap_
pinfo
*
pi
=
l2cap_pi
(
sk
)
;
struct
l2cap_
chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
struct
sk_buff
*
skb
;
u16
control
;
int
err
;
...
...
@@ -725,76 +739,77 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
/* Connectionless channel */
if
(
sk
->
sk_type
==
SOCK_DGRAM
)
{
skb
=
l2cap_create_connless_pdu
(
sk
,
msg
,
len
);
skb
=
l2cap_create_connless_pdu
(
chan
,
msg
,
len
);
if
(
IS_ERR
(
skb
))
{
err
=
PTR_ERR
(
skb
);
}
else
{
l2cap_do_send
(
sk
,
skb
);
l2cap_do_send
(
chan
,
skb
);
err
=
len
;
}
goto
done
;
}
switch
(
pi
->
mode
)
{
switch
(
chan
->
mode
)
{
case
L2CAP_MODE_BASIC
:
/* Check outgoing MTU */
if
(
len
>
pi
->
omtu
)
{
if
(
len
>
chan
->
omtu
)
{
err
=
-
EMSGSIZE
;
goto
done
;
}
/* Create a basic PDU */
skb
=
l2cap_create_basic_pdu
(
sk
,
msg
,
len
);
skb
=
l2cap_create_basic_pdu
(
chan
,
msg
,
len
);
if
(
IS_ERR
(
skb
))
{
err
=
PTR_ERR
(
skb
);
goto
done
;
}
l2cap_do_send
(
sk
,
skb
);
l2cap_do_send
(
chan
,
skb
);
err
=
len
;
break
;
case
L2CAP_MODE_ERTM
:
case
L2CAP_MODE_STREAMING
:
/* Entire SDU fits into one PDU */
if
(
len
<=
pi
->
chan
->
remote_mps
)
{
if
(
len
<=
chan
->
remote_mps
)
{
control
=
L2CAP_SDU_UNSEGMENTED
;
skb
=
l2cap_create_iframe_pdu
(
sk
,
msg
,
len
,
control
,
0
);
skb
=
l2cap_create_iframe_pdu
(
chan
,
msg
,
len
,
control
,
0
);
if
(
IS_ERR
(
skb
))
{
err
=
PTR_ERR
(
skb
);
goto
done
;
}
__skb_queue_tail
(
&
pi
->
chan
->
tx_q
,
skb
);
__skb_queue_tail
(
&
chan
->
tx_q
,
skb
);
if
(
pi
->
chan
->
tx_send_head
==
NULL
)
pi
->
chan
->
tx_send_head
=
skb
;
if
(
chan
->
tx_send_head
==
NULL
)
chan
->
tx_send_head
=
skb
;
}
else
{
/* Segment SDU into multiples PDUs */
err
=
l2cap_sar_segment_sdu
(
pi
->
chan
,
msg
,
len
);
err
=
l2cap_sar_segment_sdu
(
chan
,
msg
,
len
);
if
(
err
<
0
)
goto
done
;
}
if
(
pi
->
mode
==
L2CAP_MODE_STREAMING
)
{
l2cap_streaming_send
(
pi
->
chan
);
if
(
chan
->
mode
==
L2CAP_MODE_STREAMING
)
{
l2cap_streaming_send
(
chan
);
err
=
len
;
break
;
}
if
((
pi
->
chan
->
conn_state
&
L2CAP_CONN_REMOTE_BUSY
)
&&
(
pi
->
chan
->
conn_state
&
L2CAP_CONN_WAIT_F
))
{
if
((
chan
->
conn_state
&
L2CAP_CONN_REMOTE_BUSY
)
&&
(
chan
->
conn_state
&
L2CAP_CONN_WAIT_F
))
{
err
=
len
;
break
;
}
err
=
l2cap_ertm_send
(
pi
->
chan
);
err
=
l2cap_ertm_send
(
chan
);
if
(
err
>=
0
)
err
=
len
;
break
;
default:
BT_DBG
(
"bad state %1.1x"
,
pi
->
mode
);
BT_DBG
(
"bad state %1.1x"
,
chan
->
mode
);
err
=
-
EBADFD
;
}
...
...
@@ -810,7 +825,9 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms
lock_sock
(
sk
);
if
(
sk
->
sk_state
==
BT_CONNECT2
&&
bt_sk
(
sk
)
->
defer_setup
)
{
__l2cap_connect_rsp_defer
(
sk
);
sk
->
sk_state
=
BT_CONFIG
;
__l2cap_connect_rsp_defer
(
l2cap_pi
(
sk
)
->
chan
);
release_sock
(
sk
);
return
0
;
}
...
...
@@ -834,6 +851,8 @@ void l2cap_sock_kill(struct sock *sk)
BT_DBG
(
"sk %p state %d"
,
sk
,
sk
->
sk_state
);
/* Kill poor orphan */
l2cap_chan_free
(
l2cap_pi
(
sk
)
->
chan
);
bt_sock_unlink
(
&
l2cap_sk_list
,
sk
);
sock_set_flag
(
sk
,
SOCK_DEAD
);
sock_put
(
sk
);
...
...
@@ -865,8 +884,8 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
void
__l2cap_sock_close
(
struct
sock
*
sk
,
int
reason
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
struct
l2cap_conn
*
conn
=
chan
->
conn
;
BT_DBG
(
"sk %p state %d socket %p"
,
sk
,
sk
->
sk_state
,
sk
->
sk_socket
);
...
...
@@ -898,8 +917,8 @@ void __l2cap_sock_close(struct sock *sk, int reason)
else
result
=
L2CAP_CR_BAD_PSM
;
rsp
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
dcid
);
rsp
.
dcid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
rsp
.
scid
=
cpu_to_le16
(
chan
->
dcid
);
rsp
.
dcid
=
cpu_to_le16
(
chan
->
scid
);
rsp
.
result
=
cpu_to_le16
(
result
);
rsp
.
status
=
cpu_to_le16
(
L2CAP_CS_NO_INFO
);
l2cap_send_cmd
(
conn
,
chan
->
ident
,
L2CAP_CONN_RSP
,
...
...
@@ -923,6 +942,7 @@ void __l2cap_sock_close(struct sock *sk, int reason)
static
int
l2cap_sock_shutdown
(
struct
socket
*
sock
,
int
how
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
int
err
=
0
;
BT_DBG
(
"sock %p, sk %p"
,
sock
,
sk
);
...
...
@@ -932,7 +952,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
lock_sock
(
sk
);
if
(
!
sk
->
sk_shutdown
)
{
if
(
l2cap_pi
(
sk
)
->
mode
==
L2CAP_MODE_ERTM
)
if
(
chan
->
mode
==
L2CAP_MODE_ERTM
)
err
=
__l2cap_wait_ack
(
sk
);
sk
->
sk_shutdown
=
SHUTDOWN_MASK
;
...
...
@@ -979,44 +999,47 @@ static void l2cap_sock_destruct(struct sock *sk)
void
l2cap_sock_init
(
struct
sock
*
sk
,
struct
sock
*
parent
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
struct
l2cap_chan
*
chan
=
pi
->
chan
;
BT_DBG
(
"sk %p"
,
sk
);
if
(
parent
)
{
struct
l2cap_chan
*
pchan
=
l2cap_pi
(
parent
)
->
chan
;
sk
->
sk_type
=
parent
->
sk_type
;
bt_sk
(
sk
)
->
defer_setup
=
bt_sk
(
parent
)
->
defer_setup
;
pi
->
imtu
=
l2cap_pi
(
parent
)
->
imtu
;
pi
->
omtu
=
l2cap_pi
(
parent
)
->
omtu
;
pi
->
conf_state
=
l2cap_pi
(
parent
)
->
conf_state
;
pi
->
mode
=
l2cap_pi
(
parent
)
->
mode
;
pi
->
fcs
=
l2cap_pi
(
parent
)
->
fcs
;
pi
->
max_tx
=
l2cap_pi
(
parent
)
->
max_tx
;
pi
->
tx_win
=
l2cap_pi
(
parent
)
->
tx_win
;
pi
->
sec_level
=
l2cap_pi
(
parent
)
->
sec_level
;
pi
->
role_switch
=
l2cap_pi
(
parent
)
->
role_switch
;
pi
->
force_reliable
=
l2cap_pi
(
parent
)
->
force_reliable
;
pi
->
flushable
=
l2cap_pi
(
parent
)
->
flushable
;
chan
->
imtu
=
pchan
->
imtu
;
chan
->
omtu
=
pchan
->
omtu
;
chan
->
conf_state
=
pchan
->
conf_state
;
chan
->
mode
=
pchan
->
mode
;
chan
->
fcs
=
pchan
->
fcs
;
chan
->
max_tx
=
pchan
->
max_tx
;
chan
->
tx_win
=
pchan
->
tx_win
;
chan
->
sec_level
=
pchan
->
sec_level
;
chan
->
role_switch
=
pchan
->
role_switch
;
chan
->
force_reliable
=
pchan
->
force_reliable
;
chan
->
flushable
=
pchan
->
flushable
;
}
else
{
pi
->
imtu
=
L2CAP_DEFAULT_MTU
;
pi
->
omtu
=
0
;
chan
->
imtu
=
L2CAP_DEFAULT_MTU
;
chan
->
omtu
=
0
;
if
(
!
disable_ertm
&&
sk
->
sk_type
==
SOCK_STREAM
)
{
pi
->
mode
=
L2CAP_MODE_ERTM
;
pi
->
conf_state
|=
L2CAP_CONF_STATE2_DEVICE
;
chan
->
mode
=
L2CAP_MODE_ERTM
;
chan
->
conf_state
|=
L2CAP_CONF_STATE2_DEVICE
;
}
else
{
pi
->
mode
=
L2CAP_MODE_BASIC
;
chan
->
mode
=
L2CAP_MODE_BASIC
;
}
pi
->
max_tx
=
L2CAP_DEFAULT_MAX_TX
;
pi
->
fcs
=
L2CAP_FCS_CRC16
;
pi
->
tx_win
=
L2CAP_DEFAULT_TX_WINDOW
;
pi
->
sec_level
=
BT_SECURITY_LOW
;
pi
->
role_switch
=
0
;
pi
->
force_reliable
=
0
;
pi
->
flushable
=
BT_FLUSHABLE_OFF
;
chan
->
max_tx
=
L2CAP_DEFAULT_MAX_TX
;
chan
->
fcs
=
L2CAP_FCS_CRC16
;
chan
->
tx_win
=
L2CAP_DEFAULT_TX_WINDOW
;
chan
->
sec_level
=
BT_SECURITY_LOW
;
chan
->
role_switch
=
0
;
chan
->
force_reliable
=
0
;
chan
->
flushable
=
BT_FLUSHABLE_OFF
;
}
/* Default config options */
pi
->
flush_to
=
L2CAP_DEFAULT_FLUSH_TO
;
chan
->
flush_to
=
L2CAP_DEFAULT_FLUSH_TO
;
}
static
struct
proto
l2cap_proto
=
{
...
...
@@ -1054,6 +1077,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
int
kern
)
{
struct
sock
*
sk
;
struct
l2cap_chan
*
chan
;
BT_DBG
(
"sock %p"
,
sock
);
...
...
@@ -1072,11 +1096,19 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
if
(
!
sk
)
return
-
ENOMEM
;
chan
=
l2cap_chan_alloc
(
sk
);
if
(
!
chan
)
{
l2cap_sock_kill
(
sk
);
return
-
ENOMEM
;
}
l2cap_pi
(
sk
)
->
chan
=
chan
;
l2cap_sock_init
(
sk
,
NULL
);
return
0
;
}
const
struct
proto_ops
l2cap_sock_ops
=
{
static
const
struct
proto_ops
l2cap_sock_ops
=
{
.
family
=
PF_BLUETOOTH
,
.
owner
=
THIS_MODULE
,
.
release
=
l2cap_sock_release
,
...
...
net/bluetooth/mgmt.c
浏览文件 @
dee04cac
...
...
@@ -945,7 +945,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
for
(
i
=
0
;
i
<
key_count
;
i
++
)
{
struct
mgmt_key_info
*
key
=
&
cp
->
keys
[
i
];
hci_add_link_key
(
hdev
,
0
,
&
key
->
bdaddr
,
key
->
val
,
key
->
type
,
hci_add_link_key
(
hdev
,
NULL
,
0
,
&
key
->
bdaddr
,
key
->
val
,
key
->
type
,
key
->
pin_len
);
}
...
...
@@ -1569,6 +1569,75 @@ static int remove_remote_oob_data(struct sock *sk, u16 index,
return
err
;
}
static
int
start_discovery
(
struct
sock
*
sk
,
u16
index
)
{
u8
lap
[
3
]
=
{
0x33
,
0x8b
,
0x9e
};
struct
hci_cp_inquiry
cp
;
struct
pending_cmd
*
cmd
;
struct
hci_dev
*
hdev
;
int
err
;
BT_DBG
(
"hci%u"
,
index
);
hdev
=
hci_dev_get
(
index
);
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_START_DISCOVERY
,
ENODEV
);
hci_dev_lock_bh
(
hdev
);
cmd
=
mgmt_pending_add
(
sk
,
MGMT_OP_START_DISCOVERY
,
index
,
NULL
,
0
);
if
(
!
cmd
)
{
err
=
-
ENOMEM
;
goto
failed
;
}
memset
(
&
cp
,
0
,
sizeof
(
cp
));
memcpy
(
&
cp
.
lap
,
lap
,
3
);
cp
.
length
=
0x08
;
cp
.
num_rsp
=
0x00
;
err
=
hci_send_cmd
(
hdev
,
HCI_OP_INQUIRY
,
sizeof
(
cp
),
&
cp
);
if
(
err
<
0
)
mgmt_pending_remove
(
cmd
);
failed:
hci_dev_unlock_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
}
static
int
stop_discovery
(
struct
sock
*
sk
,
u16
index
)
{
struct
hci_dev
*
hdev
;
struct
pending_cmd
*
cmd
;
int
err
;
BT_DBG
(
"hci%u"
,
index
);
hdev
=
hci_dev_get
(
index
);
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_STOP_DISCOVERY
,
ENODEV
);
hci_dev_lock_bh
(
hdev
);
cmd
=
mgmt_pending_add
(
sk
,
MGMT_OP_STOP_DISCOVERY
,
index
,
NULL
,
0
);
if
(
!
cmd
)
{
err
=
-
ENOMEM
;
goto
failed
;
}
err
=
hci_send_cmd
(
hdev
,
HCI_OP_INQUIRY_CANCEL
,
0
,
NULL
);
if
(
err
<
0
)
mgmt_pending_remove
(
cmd
);
failed:
hci_dev_unlock_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
}
int
mgmt_control
(
struct
sock
*
sk
,
struct
msghdr
*
msg
,
size_t
msglen
)
{
unsigned
char
*
buf
;
...
...
@@ -1677,7 +1746,12 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
err
=
remove_remote_oob_data
(
sk
,
index
,
buf
+
sizeof
(
*
hdr
),
len
);
break
;
case
MGMT_OP_START_DISCOVERY
:
err
=
start_discovery
(
sk
,
index
);
break
;
case
MGMT_OP_STOP_DISCOVERY
:
err
=
stop_discovery
(
sk
,
index
);
break
;
default:
BT_DBG
(
"Unknown op %u"
,
opcode
);
err
=
cmd_status
(
sk
,
index
,
opcode
,
0x01
);
...
...
@@ -1784,17 +1858,17 @@ int mgmt_connectable(u16 index, u8 connectable)
return
ret
;
}
int
mgmt_new_key
(
u16
index
,
struct
link_key
*
key
,
u8
old_key_type
)
int
mgmt_new_key
(
u16
index
,
struct
link_key
*
key
,
u8
persistent
)
{
struct
mgmt_ev_new_key
ev
;
memset
(
&
ev
,
0
,
sizeof
(
ev
));
ev
.
store_hint
=
persistent
;
bacpy
(
&
ev
.
key
.
bdaddr
,
&
key
->
bdaddr
);
ev
.
key
.
type
=
key
->
type
;
memcpy
(
ev
.
key
.
val
,
key
->
val
,
16
);
ev
.
key
.
pin_len
=
key
->
pin_len
;
ev
.
old_key_type
=
old_key_type
;
return
mgmt_event
(
MGMT_EV_NEW_KEY
,
index
,
&
ev
,
sizeof
(
ev
),
NULL
);
}
...
...
@@ -1868,11 +1942,12 @@ int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status)
return
mgmt_event
(
MGMT_EV_CONNECT_FAILED
,
index
,
&
ev
,
sizeof
(
ev
),
NULL
);
}
int
mgmt_pin_code_request
(
u16
index
,
bdaddr_t
*
bdaddr
)
int
mgmt_pin_code_request
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
secure
)
{
struct
mgmt_ev_pin_code_request
ev
;
bacpy
(
&
ev
.
bdaddr
,
bdaddr
);
ev
.
secure
=
secure
;
return
mgmt_event
(
MGMT_EV_PIN_CODE_REQUEST
,
index
,
&
ev
,
sizeof
(
ev
),
NULL
);
...
...
@@ -1920,13 +1995,15 @@ int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
return
err
;
}
int
mgmt_user_confirm_request
(
u16
index
,
bdaddr_t
*
bdaddr
,
__le32
value
)
int
mgmt_user_confirm_request
(
u16
index
,
bdaddr_t
*
bdaddr
,
__le32
value
,
u8
confirm_hint
)
{
struct
mgmt_ev_user_confirm_request
ev
;
BT_DBG
(
"hci%u"
,
index
);
bacpy
(
&
ev
.
bdaddr
,
bdaddr
);
ev
.
confirm_hint
=
confirm_hint
;
put_unaligned_le32
(
value
,
&
ev
.
value
);
return
mgmt_event
(
MGMT_EV_USER_CONFIRM_REQUEST
,
index
,
&
ev
,
sizeof
(
ev
),
...
...
@@ -2075,3 +2152,9 @@ int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name)
return
mgmt_event
(
MGMT_EV_REMOTE_NAME
,
index
,
&
ev
,
sizeof
(
ev
),
NULL
);
}
int
mgmt_discovering
(
u16
index
,
u8
discovering
)
{
return
mgmt_event
(
MGMT_EV_DISCOVERING
,
index
,
&
discovering
,
sizeof
(
discovering
),
NULL
);
}
net/bluetooth/rfcomm/core.c
浏览文件 @
dee04cac
...
...
@@ -232,6 +232,8 @@ static int rfcomm_l2sock_create(struct socket **sock)
static
inline
int
rfcomm_check_security
(
struct
rfcomm_dlc
*
d
)
{
struct
sock
*
sk
=
d
->
session
->
sock
->
sk
;
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
chan
->
conn
;
__u8
auth_type
;
switch
(
d
->
sec_level
)
{
...
...
@@ -246,8 +248,7 @@ static inline int rfcomm_check_security(struct rfcomm_dlc *d)
break
;
}
return
hci_conn_security
(
l2cap_pi
(
sk
)
->
conn
->
hcon
,
d
->
sec_level
,
auth_type
);
return
hci_conn_security
(
conn
->
hcon
,
d
->
sec_level
,
auth_type
);
}
static
void
rfcomm_session_timeout
(
unsigned
long
arg
)
...
...
@@ -710,10 +711,10 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
/* Set L2CAP options */
sk
=
sock
->
sk
;
lock_sock
(
sk
);
l2cap_pi
(
sk
)
->
imtu
=
l2cap_mtu
;
l2cap_pi
(
sk
)
->
sec_level
=
sec_level
;
l2cap_pi
(
sk
)
->
chan
->
imtu
=
l2cap_mtu
;
l2cap_pi
(
sk
)
->
chan
->
sec_level
=
sec_level
;
if
(
l2cap_ertm
)
l2cap_pi
(
sk
)
->
mode
=
L2CAP_MODE_ERTM
;
l2cap_pi
(
sk
)
->
chan
->
mode
=
L2CAP_MODE_ERTM
;
release_sock
(
sk
);
s
=
rfcomm_session_add
(
sock
,
BT_BOUND
);
...
...
@@ -1241,6 +1242,7 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
void
rfcomm_dlc_accept
(
struct
rfcomm_dlc
*
d
)
{
struct
sock
*
sk
=
d
->
session
->
sock
->
sk
;
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
chan
->
conn
;
BT_DBG
(
"dlc %p"
,
d
);
...
...
@@ -1254,7 +1256,7 @@ void rfcomm_dlc_accept(struct rfcomm_dlc *d)
rfcomm_dlc_unlock
(
d
);
if
(
d
->
role_switch
)
hci_conn_switch_role
(
l2cap_pi
(
sk
)
->
conn
->
hcon
,
0x00
);
hci_conn_switch_role
(
conn
->
hcon
,
0x00
);
rfcomm_send_msc
(
d
->
session
,
1
,
d
->
dlci
,
d
->
v24_sig
);
}
...
...
@@ -1890,7 +1892,8 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s)
/* We should adjust MTU on incoming sessions.
* L2CAP MTU minus UIH header and FCS. */
s
->
mtu
=
min
(
l2cap_pi
(
nsock
->
sk
)
->
omtu
,
l2cap_pi
(
nsock
->
sk
)
->
imtu
)
-
5
;
s
->
mtu
=
min
(
l2cap_pi
(
nsock
->
sk
)
->
chan
->
omtu
,
l2cap_pi
(
nsock
->
sk
)
->
chan
->
imtu
)
-
5
;
rfcomm_schedule
();
}
else
...
...
@@ -1909,7 +1912,7 @@ static inline void rfcomm_check_connection(struct rfcomm_session *s)
/* We can adjust MTU on outgoing sessions.
* L2CAP MTU minus UIH header and FCS. */
s
->
mtu
=
min
(
l2cap_pi
(
sk
)
->
omtu
,
l2cap_pi
(
sk
)
->
imtu
)
-
5
;
s
->
mtu
=
min
(
l2cap_pi
(
sk
)
->
chan
->
omtu
,
l2cap_pi
(
sk
)
->
chan
->
imtu
)
-
5
;
rfcomm_send_sabm
(
s
,
0
);
break
;
...
...
@@ -1992,7 +1995,7 @@ static int rfcomm_add_listener(bdaddr_t *ba)
/* Set L2CAP options */
sk
=
sock
->
sk
;
lock_sock
(
sk
);
l2cap_pi
(
sk
)
->
imtu
=
l2cap_mtu
;
l2cap_pi
(
sk
)
->
chan
->
imtu
=
l2cap_mtu
;
release_sock
(
sk
);
/* Start listening on the socket */
...
...
net/bluetooth/rfcomm/sock.c
浏览文件 @
dee04cac
...
...
@@ -743,6 +743,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
struct
sock
*
sk
=
sock
->
sk
;
struct
sock
*
l2cap_sk
;
struct
rfcomm_conninfo
cinfo
;
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
chan
->
conn
;
int
len
,
err
=
0
;
u32
opt
;
...
...
@@ -787,8 +788,8 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
l2cap_sk
=
rfcomm_pi
(
sk
)
->
dlc
->
session
->
sock
->
sk
;
cinfo
.
hci_handle
=
l2cap_pi
(
l2cap_sk
)
->
conn
->
hcon
->
handle
;
memcpy
(
cinfo
.
dev_class
,
l2cap_pi
(
l2cap_sk
)
->
conn
->
hcon
->
dev_class
,
3
);
cinfo
.
hci_handle
=
conn
->
hcon
->
handle
;
memcpy
(
cinfo
.
dev_class
,
conn
->
hcon
->
dev_class
,
3
);
len
=
min_t
(
unsigned
int
,
len
,
sizeof
(
cinfo
));
if
(
copy_to_user
(
optval
,
(
char
*
)
&
cinfo
,
len
))
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录