Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
dee04cac
Commit
dee04cac
authored
Apr 29, 2011
by
John W. Linville
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-next-2.6
parents
ce6cac88
7cbc9bd9
Changes
15
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
907 additions
and
504 deletions
+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
No files found.
include/net/bluetooth/hci.h
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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,19 +2073,32 @@ 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
(
key
->
type
==
0x04
&&
conn
&&
conn
->
auth_type
!=
0xff
&&
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
==
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
);
memcpy
(
cp
.
link_key
,
key
->
val
,
16
);
...
...
@@ -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
View file @
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
View file @
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
View file @
dee04cac
...
...
@@ -80,8 +80,7 @@ static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16
struct
l2cap_chan
*
c
;
list_for_each_entry
(
c
,
&
conn
->
chan_l
,
list
)
{
struct
sock
*
s
=
c
->
sk
;
if
(
l2cap_pi
(
s
)
->
dcid
==
cid
)
if
(
c
->
dcid
==
cid
)
return
c
;
}
return
NULL
;
...
...
@@ -93,8 +92,7 @@ static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16
struct
l2cap_chan
*
c
;
list_for_each_entry
(
c
,
&
conn
->
chan_l
,
list
)
{
struct
sock
*
s
=
c
->
sk
;
if
(
l2cap_pi
(
s
)
->
scid
==
cid
)
if
(
c
->
scid
==
cid
)
return
c
;
}
return
NULL
;
...
...
@@ -149,7 +147,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
return
0
;
}
st
atic
st
ruct
l2cap_chan
*
l2cap_chan_alloc
(
struct
sock
*
sk
)
struct
l2cap_chan
*
l2cap_chan_alloc
(
struct
sock
*
sk
)
{
struct
l2cap_chan
*
chan
;
...
...
@@ -162,38 +160,43 @@ static struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
return
chan
;
}
void
l2cap_chan_free
(
struct
l2cap_chan
*
chan
)
{
kfree
(
chan
);
}
static
void
__l2cap_chan_add
(
struct
l2cap_conn
*
conn
,
struct
l2cap_chan
*
chan
)
{
struct
sock
*
sk
=
chan
->
sk
;
BT_DBG
(
"conn %p, psm 0x%2.2x, dcid 0x%4.4x"
,
conn
,
l2cap_pi
(
sk
)
->
psm
,
l2cap_pi
(
sk
)
->
dcid
);
chan
->
psm
,
chan
->
dcid
);
conn
->
disc_reason
=
0x13
;
l2cap_pi
(
sk
)
->
conn
=
conn
;
chan
->
conn
=
conn
;
if
(
sk
->
sk_type
==
SOCK_SEQPACKET
||
sk
->
sk_type
==
SOCK_STREAM
)
{
if
(
conn
->
hcon
->
type
==
LE_LINK
)
{
/* LE connection */
l2cap_pi
(
sk
)
->
omtu
=
L2CAP_LE_DEFAULT_MTU
;
l2cap_pi
(
sk
)
->
scid
=
L2CAP_CID_LE_DATA
;
l2cap_pi
(
sk
)
->
dcid
=
L2CAP_CID_LE_DATA
;
chan
->
omtu
=
L2CAP_LE_DEFAULT_MTU
;
chan
->
scid
=
L2CAP_CID_LE_DATA
;
chan
->
dcid
=
L2CAP_CID_LE_DATA
;
}
else
{
/* Alloc CID for connection-oriented socket */
l2cap_pi
(
sk
)
->
scid
=
l2cap_alloc_cid
(
conn
);
l2cap_pi
(
sk
)
->
omtu
=
L2CAP_DEFAULT_MTU
;
chan
->
scid
=
l2cap_alloc_cid
(
conn
);
chan
->
omtu
=
L2CAP_DEFAULT_MTU
;
}
}
else
if
(
sk
->
sk_type
==
SOCK_DGRAM
)
{
/* Connectionless socket */
l2cap_pi
(
sk
)
->
scid
=
L2CAP_CID_CONN_LESS
;
l2cap_pi
(
sk
)
->
dcid
=
L2CAP_CID_CONN_LESS
;
l2cap_pi
(
sk
)
->
omtu
=
L2CAP_DEFAULT_MTU
;
chan
->
scid
=
L2CAP_CID_CONN_LESS
;
chan
->
dcid
=
L2CAP_CID_CONN_LESS
;
chan
->
omtu
=
L2CAP_DEFAULT_MTU
;
}
else
{
/* Raw socket can send/recv signalling messages only */
l2cap_pi
(
sk
)
->
scid
=
L2CAP_CID_SIGNALING
;
l2cap_pi
(
sk
)
->
dcid
=
L2CAP_CID_SIGNALING
;
l2cap_pi
(
sk
)
->
omtu
=
L2CAP_DEFAULT_MTU
;
chan
->
scid
=
L2CAP_CID_SIGNALING
;
chan
->
dcid
=
L2CAP_CID_SIGNALING
;
chan
->
omtu
=
L2CAP_DEFAULT_MTU
;
}
sock_hold
(
sk
);
...
...
@@ -206,7 +209,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
void
l2cap_chan_del
(
struct
l2cap_chan
*
chan
,
int
err
)
{
struct
sock
*
sk
=
chan
->
sk
;
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
struct
l2cap_conn
*
conn
=
chan
->
conn
;
struct
sock
*
parent
=
bt_sk
(
sk
)
->
parent
;
l2cap_sock_clear_timer
(
sk
);
...
...
@@ -220,7 +223,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
write_unlock_bh
(
&
conn
->
chan_lock
);
__sock_put
(
sk
);
l2cap_pi
(
sk
)
->
conn
=
NULL
;
chan
->
conn
=
NULL
;
hci_conn_put
(
conn
->
hcon
);
}
...
...
@@ -236,13 +239,13 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
}
else
sk
->
sk_state_change
(
sk
);
if
(
!
(
l2cap_pi
(
sk
)
->
conf_state
&
L2CAP_CONF_OUTPUT_DONE
&&
l2cap_pi
(
sk
)
->
conf_state
&
L2CAP_CONF_INPUT_DONE
))
goto
free
;
if
(
!
(
chan
->
conf_state
&
L2CAP_CONF_OUTPUT_DONE
&&
chan
->
conf_state
&
L2CAP_CONF_INPUT_DONE
))
return
;
skb_queue_purge
(
&
chan
->
tx_q
);
if
(
l2cap_pi
(
sk
)
->
mode
==
L2CAP_MODE_ERTM
)
{
if
(
chan
->
mode
==
L2CAP_MODE_ERTM
)
{
struct
srej_list
*
l
,
*
tmp
;
del_timer
(
&
chan
->
retrans_timer
);
...
...
@@ -257,15 +260,14 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
kfree
(
l
);
}
}
free:
kfree
(
chan
);
}
static
inline
u8
l2cap_get_auth_type
(
struct
sock
*
sk
)
static
inline
u8
l2cap_get_auth_type
(
struct
l2cap_chan
*
chan
)
{
struct
sock
*
sk
=
chan
->
sk
;
if
(
sk
->
sk_type
==
SOCK_RAW
)
{
switch
(
l2cap_pi
(
sk
)
->
sec_level
)
{
switch
(
chan
->
sec_level
)
{
case
BT_SECURITY_HIGH
:
return
HCI_AT_DEDICATED_BONDING_MITM
;
case
BT_SECURITY_MEDIUM
:
...
...
@@ -273,16 +275,16 @@ static inline u8 l2cap_get_auth_type(struct sock *sk)
default:
return
HCI_AT_NO_BONDING
;
}
}
else
if
(
l2cap_pi
(
sk
)
->
psm
==
cpu_to_le16
(
0x0001
))
{
if
(
l2cap_pi
(
sk
)
->
sec_level
==
BT_SECURITY_LOW
)
l2cap_pi
(
sk
)
->
sec_level
=
BT_SECURITY_SDP
;
}
else
if
(
chan
->
psm
==
cpu_to_le16
(
0x0001
))
{
if
(
chan
->
sec_level
==
BT_SECURITY_LOW
)
chan
->
sec_level
=
BT_SECURITY_SDP
;
if
(
l2cap_pi
(
sk
)
->
sec_level
==
BT_SECURITY_HIGH
)
if
(
chan
->
sec_level
==
BT_SECURITY_HIGH
)
return
HCI_AT_NO_BONDING_MITM
;
else
return
HCI_AT_NO_BONDING
;
}
else
{
switch
(
l2cap_pi
(
sk
)
->
sec_level
)
{
switch
(
chan
->
sec_level
)
{
case
BT_SECURITY_HIGH
:
return
HCI_AT_GENERAL_BONDING_MITM
;
case
BT_SECURITY_MEDIUM
:
...
...
@@ -294,15 +296,14 @@ static inline u8 l2cap_get_auth_type(struct sock *sk)
}
/* Service level security */
static
inline
int
l2cap_check_security
(
struct
sock
*
sk
)
static
inline
int
l2cap_check_security
(
struct
l2cap_chan
*
chan
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
struct
l2cap_conn
*
conn
=
chan
->
conn
;
__u8
auth_type
;
auth_type
=
l2cap_get_auth_type
(
sk
);
auth_type
=
l2cap_get_auth_type
(
chan
);
return
hci_conn_security
(
conn
->
hcon
,
l2cap_pi
(
sk
)
->
sec_level
,
auth_type
);
return
hci_conn_security
(
conn
->
hcon
,
chan
->
sec_level
,
auth_type
);
}
u8
l2cap_get_ident
(
struct
l2cap_conn
*
conn
)
...
...
@@ -350,7 +351,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
struct
sk_buff
*
skb
;
struct
l2cap_hdr
*
lh
;
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
chan
->
sk
);
struct
l2cap_conn
*
conn
=
pi
->
conn
;
struct
l2cap_conn
*
conn
=
chan
->
conn
;
struct
sock
*
sk
=
(
struct
sock
*
)
pi
;
int
count
,
hlen
=
L2CAP_HDR_SIZE
+
2
;
u8
flags
;
...
...
@@ -358,7 +359,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
if
(
sk
->
sk_state
!=
BT_CONNECTED
)
return
;
if
(
pi
->
fcs
==
L2CAP_FCS_CRC16
)
if
(
chan
->
fcs
==
L2CAP_FCS_CRC16
)
hlen
+=
2
;
BT_DBG
(
"chan %p, control 0x%2.2x"
,
chan
,
control
);
...
...
@@ -382,10 +383,10 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
lh
=
(
struct
l2cap_hdr
*
)
skb_put
(
skb
,
L2CAP_HDR_SIZE
);
lh
->
len
=
cpu_to_le16
(
hlen
-
L2CAP_HDR_SIZE
);
lh
->
cid
=
cpu_to_le16
(
pi
->
dcid
);
lh
->
cid
=
cpu_to_le16
(
chan
->
dcid
);
put_unaligned_le16
(
control
,
skb_put
(
skb
,
2
));
if
(
pi
->
fcs
==
L2CAP_FCS_CRC16
)
{
if
(
chan
->
fcs
==
L2CAP_FCS_CRC16
)
{
u16
fcs
=
crc16
(
0
,
(
u8
*
)
lh
,
count
-
2
);
put_unaligned_le16
(
fcs
,
skb_put
(
skb
,
2
));
}
...
...
@@ -395,7 +396,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
else
flags
=
ACL_START
;
hci_send_acl
(
pi
->
conn
->
hcon
,
skb
,
flags
);
hci_send_acl
(
chan
->
conn
->
hcon
,
skb
,
flags
);
}
static
inline
void
l2cap_send_rr_or_rnr
(
struct
l2cap_chan
*
chan
,
u16
control
)
...
...
@@ -411,27 +412,27 @@ static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
l2cap_send_sframe
(
chan
,
control
);
}
static
inline
int
__l2cap_no_conn_pending
(
struct
sock
*
sk
)
static
inline
int
__l2cap_no_conn_pending
(
struct
l2cap_chan
*
chan
)
{
return
!
(
l2cap_pi
(
sk
)
->
conf_state
&
L2CAP_CONF_CONNECT_PEND
);
return
!
(
chan
->
conf_state
&
L2CAP_CONF_CONNECT_PEND
);
}
static
void
l2cap_do_start
(
struct
l2cap_chan
*
chan
)
{
struct
sock
*
sk
=
chan
->
sk
;
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
struct
l2cap_conn
*
conn
=
chan
->
conn
;
if
(
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_SENT
)
{
if
(
!
(
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_DONE
))
return
;
if
(
l2cap_check_security
(
sk
)
&&
__l2cap_no_conn_pending
(
sk
))
{
if
(
l2cap_check_security
(
chan
)
&&
__l2cap_no_conn_pending
(
chan
))
{
struct
l2cap_conn_req
req
;
req
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
req
.
psm
=
l2cap_pi
(
sk
)
->
psm
;
req
.
scid
=
cpu_to_le16
(
chan
->
scid
);
req
.
psm
=
chan
->
psm
;
chan
->
ident
=
l2cap_get_ident
(
conn
);
l2cap_pi
(
sk
)
->
conf_state
|=
L2CAP_CONF_CONNECT_PEND
;
chan
->
conf_state
|=
L2CAP_CONF_CONNECT_PEND
;
l2cap_send_cmd
(
conn
,
chan
->
ident
,
L2CAP_CONN_REQ
,
sizeof
(
req
),
&
req
);
...
...
@@ -477,14 +478,14 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, in
sk
=
chan
->
sk
;
if
(
l2cap_pi
(
sk
)
->
mode
==
L2CAP_MODE_ERTM
)
{
if
(
chan
->
mode
==
L2CAP_MODE_ERTM
)
{
del_timer
(
&
chan
->
retrans_timer
);
del_timer
(
&
chan
->
monitor_timer
);
del_timer
(
&
chan
->
ack_timer
);
}
req
.
dcid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
dcid
);
req
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
req
.
dcid
=
cpu_to_le16
(
chan
->
dcid
);
req
.
scid
=
cpu_to_le16
(
chan
->
scid
);
l2cap_send_cmd
(
conn
,
l2cap_get_ident
(
conn
),
L2CAP_DISCONN_REQ
,
sizeof
(
req
),
&
req
);
...
...
@@ -515,15 +516,15 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
if
(
sk
->
sk_state
==
BT_CONNECT
)
{
struct
l2cap_conn_req
req
;
if
(
!
l2cap_check_security
(
sk
)
||
!
__l2cap_no_conn_pending
(
sk
))
{
if
(
!
l2cap_check_security
(
chan
)
||
!
__l2cap_no_conn_pending
(
chan
))
{
bh_unlock_sock
(
sk
);
continue
;
}
if
(
!
l2cap_mode_supported
(
l2cap_pi
(
sk
)
->
mode
,
if
(
!
l2cap_mode_supported
(
chan
->
mode
,
conn
->
feat_mask
)
&&
l2cap_pi
(
sk
)
->
conf_state
&
&&
chan
->
conf_state
&
L2CAP_CONF_STATE2_DEVICE
)
{
/* __l2cap_sock_close() calls list_del(chan)
* so release the lock */
...
...
@@ -534,11 +535,11 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
continue
;
}
req
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
req
.
psm
=
l2cap_pi
(
sk
)
->
psm
;
req
.
scid
=
cpu_to_le16
(
chan
->
scid
);
req
.
psm
=
chan
->
psm
;
chan
->
ident
=
l2cap_get_ident
(
conn
);
l2cap_pi
(
sk
)
->
conf_state
|=
L2CAP_CONF_CONNECT_PEND
;
chan
->
conf_state
|=
L2CAP_CONF_CONNECT_PEND
;
l2cap_send_cmd
(
conn
,
chan
->
ident
,
L2CAP_CONN_REQ
,
sizeof
(
req
),
&
req
);
...
...
@@ -546,10 +547,10 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
}
else
if
(
sk
->
sk_state
==
BT_CONNECT2
)
{
struct
l2cap_conn_rsp
rsp
;
char
buf
[
128
];
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
);
if
(
l2cap_check_security
(
sk
))
{
if
(
l2cap_check_security
(
chan
))
{
if
(
bt_sk
(
sk
)
->
defer_setup
)
{
struct
sock
*
parent
=
bt_sk
(
sk
)
->
parent
;
rsp
.
result
=
cpu_to_le16
(
L2CAP_CR_PEND
);
...
...
@@ -569,13 +570,13 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
l2cap_send_cmd
(
conn
,
chan
->
ident
,
L2CAP_CONN_RSP
,
sizeof
(
rsp
),
&
rsp
);
if
(
l2cap_pi
(
sk
)
->
conf_state
&
L2CAP_CONF_REQ_SENT
||
if
(
chan
->
conf_state
&
L2CAP_CONF_REQ_SENT
||
rsp
.
result
!=
L2CAP_CR_SUCCESS
)
{
bh_unlock_sock
(
sk
);
continue
;
}
l2cap_pi
(
sk
)
->
conf_state
|=
L2CAP_CONF_REQ_SENT
;
chan
->
conf_state
|=
L2CAP_CONF_REQ_SENT
;
l2cap_send_cmd
(
conn
,
l2cap_get_ident
(
conn
),
L2CAP_CONF_REQ
,
l2cap_build_conf_req
(
chan
,
buf
),
buf
);
chan
->
num_conf_req
++
;
...
...
@@ -598,10 +599,12 @@ static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
read_lock
(
&
l2cap_sk_list
.
lock
);
sk_for_each
(
sk
,
node
,
&
l2cap_sk_list
.
head
)
{
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
if
(
state
&&
sk
->
sk_state
!=
state
)
continue
;
if
(
l2cap_pi
(
sk
)
->
scid
==
cid
)
{
if
(
chan
->
scid
==
cid
)
{
/* Exact match. */
if
(
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
src
))
break
;
...
...
@@ -648,6 +651,8 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
goto
clean
;
}
l2cap_pi
(
sk
)
->
chan
=
chan
;
write_lock_bh
(
&
conn
->
chan_lock
);
hci_conn_hold
(
conn
->
hcon
);
...
...
@@ -661,8 +666,6 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
__l2cap_chan_add
(
conn
,
chan
);
l2cap_pi
(
sk
)
->
chan
=
chan
;
l2cap_sock_set_timer
(
sk
,
sk
->
sk_sndtimeo
);
sk
->
sk_state
=
BT_CONNECTED
;
...
...
@@ -722,7 +725,7 @@ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
list_for_each_entry
(
chan
,
&
conn
->
chan_l
,
list
)
{
struct
sock
*
sk
=
chan
->
sk
;
if
(
l2cap_pi
(
sk
)
->
force_reliable
)
if
(
chan
->
force_reliable
)
sk
->
sk_err
=
err
;
}
...
...
@@ -828,10 +831,12 @@ static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
read_lock
(
&
l2cap_sk_list
.
lock
);
sk_for_each
(
sk
,
node
,
&
l2cap_sk_list
.
head
)
{
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
if
(
state
&&
sk
->
sk_state
!=
state
)
continue
;
if
(
l2cap_pi
(
sk
)
->
psm
==
psm
)
{
if
(
chan
->
psm
==
psm
)
{
/* Exact match. */
if
(
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
src
))
break
;
...
...
@@ -847,19 +852,19 @@ static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
return
node
?
sk
:
sk1
;
}
int
l2cap_
do_connect
(
struct
sock
*
sk
)
int
l2cap_
chan_connect
(
struct
l2cap_chan
*
chan
)
{
struct
sock
*
sk
=
chan
->
sk
;
bdaddr_t
*
src
=
&
bt_sk
(
sk
)
->
src
;
bdaddr_t
*
dst
=
&
bt_sk
(
sk
)
->
dst
;
struct
l2cap_conn
*
conn
;
struct
l2cap_chan
*
chan
;
struct
hci_conn
*
hcon
;
struct
hci_dev
*
hdev
;
__u8
auth_type
;
int
err
;
BT_DBG
(
"%s -> %s psm 0x%2.2x"
,
batostr
(
src
),
batostr
(
dst
),
l2cap_pi
(
sk
)
->
psm
);
chan
->
psm
);
hdev
=
hci_get_route
(
dst
,
src
);
if
(
!
hdev
)
...
...
@@ -867,14 +872,14 @@ int l2cap_do_connect(struct sock *sk)
hci_dev_lock_bh
(
hdev
);
auth_type
=
l2cap_get_auth_type
(
sk
);
auth_type
=
l2cap_get_auth_type
(
chan
);
if
(
l2cap_pi
(
sk
)
->
dcid
==
L2CAP_CID_LE_DATA
)
if
(
chan
->
dcid
==
L2CAP_CID_LE_DATA
)
hcon
=
hci_connect
(
hdev
,
LE_LINK
,
dst
,
l2cap_pi
(
sk
)
->
sec_level
,
auth_type
);
chan
->
sec_level
,
auth_type
);
else
hcon
=
hci_connect
(
hdev
,
ACL_LINK
,
dst
,
l2cap_pi
(
sk
)
->
sec_level
,
auth_type
);
chan
->
sec_level
,
auth_type
);
if
(
IS_ERR
(
hcon
))
{
err
=
PTR_ERR
(
hcon
);
...
...
@@ -888,20 +893,11 @@ int l2cap_do_connect(struct sock *sk)
goto
done
;
}
chan
=
l2cap_chan_alloc
(
sk
);
if
(
!
chan
)
{
hci_conn_put
(
hcon
);
err
=
-
ENOMEM
;
goto
done
;
}
/* Update source addr of the socket */
bacpy
(
src
,
conn
->
src
);
l2cap_chan_add
(
conn
,
chan
);
l2cap_pi
(
sk
)
->
chan
=
chan
;
sk
->
sk_state
=
BT_CONNECT
;
l2cap_sock_set_timer
(
sk
,
sk
->
sk_sndtimeo
);
...
...
@@ -909,7 +905,7 @@ int l2cap_do_connect(struct sock *sk)
if
(
sk
->
sk_type
!=
SOCK_SEQPACKET
&&
sk
->
sk_type
!=
SOCK_STREAM
)
{
l2cap_sock_clear_timer
(
sk
);
if
(
l2cap_check_security
(
sk
))
if
(
l2cap_check_security
(
chan
))
sk
->
sk_state
=
BT_CONNECTED
;
}
else
l2cap_do_start
(
chan
);
...
...
@@ -925,12 +921,13 @@ int l2cap_do_connect(struct sock *sk)
int
__l2cap_wait_ack
(
struct
sock
*
sk
)
{
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
DECLARE_WAITQUEUE
(
wait
,
current
);
int
err
=
0
;
int
timeo
=
HZ
/
5
;
add_wait_queue
(
sk_sleep
(
sk
),
&
wait
);
while
((
l2cap_pi
(
sk
)
->
chan
->
unacked_frames
>
0
&&
l2cap_pi
(
sk
)
->
conn
))
{
while
((
chan
->
unacked_frames
>
0
&&
chan
->
conn
))
{
set_current_state
(
TASK_INTERRUPTIBLE
);
if
(
!
timeo
)
...
...
@@ -963,7 +960,7 @@ static void l2cap_monitor_timeout(unsigned long arg)
bh_lock_sock
(
sk
);
if
(
chan
->
retry_count
>=
chan
->
remote_max_tx
)
{
l2cap_send_disconn_req
(
l2cap_pi
(
sk
)
->
conn
,
chan
,
ECONNABORTED
);
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
ECONNABORTED
);
bh_unlock_sock
(
sk
);
return
;
}
...
...
@@ -1011,15 +1008,14 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
del_timer
(
&
chan
->
retrans_timer
);
}
void
l2cap_do_send
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
)
void
l2cap_do_send
(
struct
l2cap_chan
*
chan
,
struct
sk_buff
*
skb
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
struct
hci_conn
*
hcon
=
pi
->
conn
->
hcon
;
struct
hci_conn
*
hcon
=
chan
->
conn
->
hcon
;
u16
flags
;
BT_DBG
(
"
sk %p, skb %p len %d"
,
sk
,
skb
,
skb
->
len
);
BT_DBG
(
"
chan %p, skb %p len %d"
,
chan
,
skb
,
skb
->
len
);
if
(
!
pi
->
flushable
&&
lmp_no_flush_capable
(
hcon
->
hdev
))
if
(
!
chan
->
flushable
&&
lmp_no_flush_capable
(
hcon
->
hdev
))
flags
=
ACL_START_NO_FLUSH
;
else
flags
=
ACL_START
;
...
...
@@ -1029,9 +1025,7 @@ void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
void
l2cap_streaming_send
(
struct
l2cap_chan
*
chan
)
{
struct
sock
*
sk
=
chan
->
sk
;
struct
sk_buff
*
skb
;
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
u16
control
,
fcs
;
while
((
skb
=
skb_dequeue
(
&
chan
->
tx_q
)))
{
...
...
@@ -1039,12 +1033,12 @@ void l2cap_streaming_send(struct l2cap_chan *chan)
control
|=
chan
->
next_tx_seq
<<
L2CAP_CTRL_TXSEQ_SHIFT
;
put_unaligned_le16
(
control
,
skb
->
data
+
L2CAP_HDR_SIZE
);
if
(
pi
->
fcs
==
L2CAP_FCS_CRC16
)
{
if
(
chan
->
fcs
==
L2CAP_FCS_CRC16
)
{
fcs
=
crc16
(
0
,
(
u8
*
)
skb
->
data
,
skb
->
len
-
2
);
put_unaligned_le16
(
fcs
,
skb
->
data
+
skb
->
len
-
2
);
}
l2cap_do_send
(
sk
,
skb
);
l2cap_do_send
(
chan
,
skb
);
chan
->
next_tx_seq
=
(
chan
->
next_tx_seq
+
1
)
%
64
;
}
...
...
@@ -1052,8 +1046,6 @@ void l2cap_streaming_send(struct l2cap_chan *chan)
static
void
l2cap_retransmit_one_frame
(
struct
l2cap_chan
*
chan
,
u8
tx_seq
)
{
struct
sock
*
sk
=
chan
->
sk
;
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
struct
sk_buff
*
skb
,
*
tx_skb
;
u16
control
,
fcs
;
...
...
@@ -1072,7 +1064,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
if
(
chan
->
remote_max_tx
&&
bt_cb
(
skb
)
->
retries
==
chan
->
remote_max_tx
)
{
l2cap_send_disconn_req
(
pi
->
conn
,
chan
,
ECONNABORTED
);
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
ECONNABORTED
);
return
;
}
...
...
@@ -1091,19 +1083,18 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
put_unaligned_le16
(
control
,
tx_skb
->
data
+
L2CAP_HDR_SIZE
);
if
(
pi
->
fcs
==
L2CAP_FCS_CRC16
)
{
if
(
chan
->
fcs
==
L2CAP_FCS_CRC16
)
{
fcs
=
crc16
(
0
,
(
u8
*
)
tx_skb
->
data
,
tx_skb
->
len
-
2
);
put_unaligned_le16
(
fcs
,
tx_skb
->
data
+
tx_skb
->
len
-
2
);
}
l2cap_do_send
(
sk
,
tx_skb
);
l2cap_do_send
(
chan
,
tx_skb
);
}
int
l2cap_ertm_send
(
struct
l2cap_chan
*
chan
)
{
struct
sk_buff
*
skb
,
*
tx_skb
;
struct
sock
*
sk
=
chan
->
sk
;
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
u16
control
,
fcs
;
int
nsent
=
0
;
...
...
@@ -1114,7 +1105,7 @@ int l2cap_ertm_send(struct l2cap_chan *chan)
if
(
chan
->
remote_max_tx
&&
bt_cb
(
skb
)
->
retries
==
chan
->
remote_max_tx
)
{
l2cap_send_disconn_req
(
pi
->
conn
,
chan
,
ECONNABORTED
);
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
ECONNABORTED
);
break
;
}
...
...
@@ -1134,12 +1125,12 @@ int l2cap_ertm_send(struct l2cap_chan *chan)
put_unaligned_le16
(
control
,
tx_skb
->
data
+
L2CAP_HDR_SIZE
);
if
(
pi
->
fcs
==
L2CAP_FCS_CRC16
)
{
if
(
chan
->
fcs
==
L2CAP_FCS_CRC16
)
{
fcs
=
crc16
(
0
,
(
u8
*
)
skb
->
data
,
tx_skb
->
len
-
2
);
put_unaligned_le16
(
fcs
,
skb
->
data
+
tx_skb
->
len
-
2
);
}
l2cap_do_send
(
sk
,
tx_skb
);
l2cap_do_send
(
chan
,
tx_skb
);
__mod_retrans_timer
();
...
...
@@ -1210,7 +1201,7 @@ static void l2cap_send_srejtail(struct l2cap_chan *chan)
static
inline
int
l2cap_skbuff_fromiovec
(
struct
sock
*
sk
,
struct
msghdr
*
msg
,
int
len
,
int
count
,
struct
sk_buff
*
skb
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
c
han
->
c
onn
;
struct
sk_buff
**
frag
;
int
err
,
sent
=
0
;
...
...
@@ -1240,9 +1231,10 @@ static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, in
return
sent
;
}
struct
sk_buff
*
l2cap_create_connless_pdu
(
struct
sock
*
sk
,
struct
msghdr
*
msg
,
size_t
len
)
struct
sk_buff
*
l2cap_create_connless_pdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
struct
sock
*
sk
=
chan
->
sk
;
struct
l2cap_conn
*
conn
=
chan
->
conn
;
struct
sk_buff
*
skb
;
int
err
,
count
,
hlen
=
L2CAP_HDR_SIZE
+
2
;
struct
l2cap_hdr
*
lh
;
...
...
@@ -1257,9 +1249,9 @@ struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, s
/* Create L2CAP header */
lh
=
(
struct
l2cap_hdr
*
)
skb_put
(
skb
,
L2CAP_HDR_SIZE
);
lh
->
cid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
dcid
);
lh
->
cid
=
cpu_to_le16
(
chan
->
dcid
);
lh
->
len
=
cpu_to_le16
(
len
+
(
hlen
-
L2CAP_HDR_SIZE
));
put_unaligned_le16
(
l2cap_pi
(
sk
)
->
psm
,
skb_put
(
skb
,
2
));
put_unaligned_le16
(
chan
->
psm
,
skb_put
(
skb
,
2
));
err
=
l2cap_skbuff_fromiovec
(
sk
,
msg
,
len
,
count
,
skb
);
if
(
unlikely
(
err
<
0
))
{
...
...
@@ -1269,9 +1261,10 @@ struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, s
return
skb
;
}
struct
sk_buff
*
l2cap_create_basic_pdu
(
struct
sock
*
sk
,
struct
msghdr
*
msg
,
size_t
len
)
struct
sk_buff
*
l2cap_create_basic_pdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
struct
sock
*
sk
=
chan
->
sk
;
struct
l2cap_conn
*
conn
=
chan
->
conn
;
struct
sk_buff
*
skb
;
int
err
,
count
,
hlen
=
L2CAP_HDR_SIZE
;
struct
l2cap_hdr
*
lh
;
...
...
@@ -1286,7 +1279,7 @@ struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size
/* Create L2CAP header */
lh
=
(
struct
l2cap_hdr
*
)
skb_put
(
skb
,
L2CAP_HDR_SIZE
);
lh
->
cid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
dcid
);
lh
->
cid
=
cpu_to_le16
(
chan
->
dcid
);
lh
->
len
=
cpu_to_le16
(
len
+
(
hlen
-
L2CAP_HDR_SIZE
));
err
=
l2cap_skbuff_fromiovec
(
sk
,
msg
,
len
,
count
,
skb
);
...
...
@@ -1297,9 +1290,10 @@ struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size
return
skb
;
}
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_iframe_pdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
,
u16
control
,
u16
sdulen
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
struct
sock
*
sk
=
chan
->
sk
;
struct
l2cap_conn
*
conn
=
chan
->
conn
;
struct
sk_buff
*
skb
;
int
err
,
count
,
hlen
=
L2CAP_HDR_SIZE
+
2
;
struct
l2cap_hdr
*
lh
;
...
...
@@ -1312,7 +1306,7 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, siz
if
(
sdulen
)
hlen
+=
2
;
if
(
l2cap_pi
(
sk
)
->
fcs
==
L2CAP_FCS_CRC16
)
if
(
chan
->
fcs
==
L2CAP_FCS_CRC16
)
hlen
+=
2
;
count
=
min_t
(
unsigned
int
,
(
conn
->
mtu
-
hlen
),
len
);
...
...
@@ -1323,7 +1317,7 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, siz
/* Create L2CAP header */
lh
=
(
struct
l2cap_hdr
*
)
skb_put
(
skb
,
L2CAP_HDR_SIZE
);
lh
->
cid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
dcid
);
lh
->
cid
=
cpu_to_le16
(
chan
->
dcid
);
lh
->
len
=
cpu_to_le16
(
len
+
(
hlen
-
L2CAP_HDR_SIZE
));
put_unaligned_le16
(
control
,
skb_put
(
skb
,
2
));
if
(
sdulen
)
...
...
@@ -1335,7 +1329,7 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, siz
return
ERR_PTR
(
err
);
}
if
(
l2cap_pi
(
sk
)
->
fcs
==
L2CAP_FCS_CRC16
)
if
(
chan
->
fcs
==
L2CAP_FCS_CRC16
)
put_unaligned_le16
(
0
,
skb_put
(
skb
,
2
));
bt_cb
(
skb
)
->
retries
=
0
;
...
...
@@ -1344,7 +1338,6 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, siz
int
l2cap_sar_segment_sdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
)
{
struct
sock
*
sk
=
chan
->
sk
;
struct
sk_buff
*
skb
;
struct
sk_buff_head
sar_queue
;
u16
control
;
...
...
@@ -1352,7 +1345,7 @@ int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t le
skb_queue_head_init
(
&
sar_queue
);
control
=
L2CAP_SDU_START
;
skb
=
l2cap_create_iframe_pdu
(
sk
,
msg
,
chan
->
remote_mps
,
control
,
len
);
skb
=
l2cap_create_iframe_pdu
(
chan
,
msg
,
chan
->
remote_mps
,
control
,
len
);
if
(
IS_ERR
(
skb
))
return
PTR_ERR
(
skb
);
...
...
@@ -1371,7 +1364,7 @@ int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t le
buflen
=
len
;
}
skb
=
l2cap_create_iframe_pdu
(
sk
,
msg
,
buflen
,
control
,
0
);
skb
=
l2cap_create_iframe_pdu
(
chan
,
msg
,
buflen
,
control
,
0
);
if
(
IS_ERR
(
skb
))
{
skb_queue_purge
(
&
sar_queue
);
return
PTR_ERR
(
skb
);
...
...
@@ -1391,10 +1384,11 @@ int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t le
static
void
l2cap_chan_ready
(
struct
sock
*
sk
)
{
struct
sock
*
parent
=
bt_sk
(
sk
)
->
parent
;
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
BT_DBG
(
"sk %p, parent %p"
,
sk
,
parent
);
l2cap_pi
(
sk
)
->
conf_state
=
0
;
chan
->
conf_state
=
0
;
l2cap_sock_clear_timer
(
sk
);
if
(
!
parent
)
{
...
...
@@ -1615,9 +1609,8 @@ static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
static
int
l2cap_build_conf_req
(
struct
l2cap_chan
*
chan
,
void
*
data
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
chan
->
sk
);
struct
l2cap_conf_req
*
req
=
data
;
struct
l2cap_conf_rfc
rfc
=
{
.
mode
=
pi
->
mode
};
struct
l2cap_conf_rfc
rfc
=
{
.
mode
=
chan
->
mode
};
void
*
ptr
=
req
->
data
;
BT_DBG
(
"chan %p"
,
chan
);
...
...
@@ -1625,26 +1618,26 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
if
(
chan
->
num_conf_req
||
chan
->
num_conf_rsp
)
goto
done
;
switch
(
pi
->
mode
)
{
switch
(
chan
->
mode
)
{
case
L2CAP_MODE_STREAMING
:
case
L2CAP_MODE_ERTM
:
if
(
pi
->
conf_state
&
L2CAP_CONF_STATE2_DEVICE
)
if
(
chan
->
conf_state
&
L2CAP_CONF_STATE2_DEVICE
)
break
;
/* fall through */
default:
pi
->
mode
=
l2cap_select_mode
(
rfc
.
mode
,
pi
->
conn
->
feat_mask
);
chan
->
mode
=
l2cap_select_mode
(
rfc
.
mode
,
chan
->
conn
->
feat_mask
);
break
;
}
done:
if
(
pi
->
imtu
!=
L2CAP_DEFAULT_MTU
)
l2cap_add_conf_opt
(
&
ptr
,
L2CAP_CONF_MTU
,
2
,
pi
->
imtu
);
if
(
chan
->
imtu
!=
L2CAP_DEFAULT_MTU
)
l2cap_add_conf_opt
(
&
ptr
,
L2CAP_CONF_MTU
,
2
,
chan
->
imtu
);
switch
(
pi
->
mode
)
{
switch
(
chan
->
mode
)
{
case
L2CAP_MODE_BASIC
:
if
(
!
(
pi
->
conn
->
feat_mask
&
L2CAP_FEAT_ERTM
)
&&
!
(
pi
->
conn
->
feat_mask
&
L2CAP_FEAT_STREAMING
))
if
(
!
(
chan
->
conn
->
feat_mask
&
L2CAP_FEAT_ERTM
)
&&
!
(
chan
->
conn
->
feat_mask
&
L2CAP_FEAT_STREAMING
))
break
;
rfc
.
mode
=
L2CAP_MODE_BASIC
;
...
...
@@ -1660,24 +1653,24 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
case
L2CAP_MODE_ERTM
:
rfc
.
mode
=
L2CAP_MODE_ERTM
;
rfc
.
txwin_size
=
pi
->
tx_win
;
rfc
.
max_transmit
=
pi
->
max_tx
;
rfc
.
txwin_size
=
chan
->
tx_win
;
rfc
.
max_transmit
=
chan
->
max_tx
;
rfc
.
retrans_timeout
=
0
;
rfc
.
monitor_timeout
=
0
;
rfc
.
max_pdu_size
=
cpu_to_le16
(
L2CAP_DEFAULT_MAX_PDU_SIZE
);
if
(
L2CAP_DEFAULT_MAX_PDU_SIZE
>
pi
->
conn
->
mtu
-
10
)
rfc
.
max_pdu_size
=
cpu_to_le16
(
pi
->
conn
->
mtu
-
10
);
if
(
L2CAP_DEFAULT_MAX_PDU_SIZE
>
chan
->
conn
->
mtu
-
10
)
rfc
.
max_pdu_size
=
cpu_to_le16
(
chan
->
conn
->
mtu
-
10
);
l2cap_add_conf_opt
(
&
ptr
,
L2CAP_CONF_RFC
,
sizeof
(
rfc
),
(
unsigned
long
)
&
rfc
);
if
(
!
(
pi
->
conn
->
feat_mask
&
L2CAP_FEAT_FCS
))
if
(
!
(
chan
->
conn
->
feat_mask
&
L2CAP_FEAT_FCS
))
break
;
if
(
pi
->
fcs
==
L2CAP_FCS_NONE
||
pi
->
conf_state
&
L2CAP_CONF_NO_FCS_RECV
)
{
pi
->
fcs
=
L2CAP_FCS_NONE
;
l2cap_add_conf_opt
(
&
ptr
,
L2CAP_CONF_FCS
,
1
,
pi
->
fcs
);
if
(
chan
->
fcs
==
L2CAP_FCS_NONE
||
chan
->
conf_state
&
L2CAP_CONF_NO_FCS_RECV
)
{
chan
->
fcs
=
L2CAP_FCS_NONE
;
l2cap_add_conf_opt
(
&
ptr
,
L2CAP_CONF_FCS
,
1
,
chan
->
fcs
);
}
break
;
...
...
@@ -1688,24 +1681,24 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
rfc
.
retrans_timeout
=
0
;
rfc
.
monitor_timeout
=
0
;
rfc
.
max_pdu_size
=
cpu_to_le16
(
L2CAP_DEFAULT_MAX_PDU_SIZE
);
if
(
L2CAP_DEFAULT_MAX_PDU_SIZE
>
pi
->
conn
->
mtu
-
10
)
rfc
.
max_pdu_size
=
cpu_to_le16
(
pi
->
conn
->
mtu
-
10
);
if
(
L2CAP_DEFAULT_MAX_PDU_SIZE
>
chan
->
conn
->
mtu
-
10
)
rfc
.
max_pdu_size
=
cpu_to_le16
(
chan
->
conn
->
mtu
-
10
);
l2cap_add_conf_opt
(
&
ptr
,
L2CAP_CONF_RFC
,
sizeof
(
rfc
),
(
unsigned
long
)
&
rfc
);
if
(
!
(
pi
->
conn
->
feat_mask
&
L2CAP_FEAT_FCS
))
if
(
!
(
chan
->
conn
->
feat_mask
&
L2CAP_FEAT_FCS
))
break
;
if
(
pi
->
fcs
==
L2CAP_FCS_NONE
||
pi
->
conf_state
&
L2CAP_CONF_NO_FCS_RECV
)
{
pi
->
fcs
=
L2CAP_FCS_NONE
;
l2cap_add_conf_opt
(
&
ptr
,
L2CAP_CONF_FCS
,
1
,
pi
->
fcs
);
if
(
chan
->
fcs
==
L2CAP_FCS_NONE
||
chan
->
conf_state
&
L2CAP_CONF_NO_FCS_RECV
)
{
chan
->
fcs
=
L2CAP_FCS_NONE
;
l2cap_add_conf_opt
(
&
ptr
,
L2CAP_CONF_FCS
,
1
,
chan
->
fcs
);
}
break
;
}
req
->
dcid
=
cpu_to_le16
(
pi
->
dcid
);
req
->
dcid
=
cpu_to_le16
(
chan
->
dcid
);
req
->
flags
=
cpu_to_le16
(
0
);
return
ptr
-
data
;
...
...
@@ -1713,7 +1706,6 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
static
int
l2cap_parse_conf_req
(
struct
l2cap_chan
*
chan
,
void
*
data
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
chan
->
sk
);
struct
l2cap_conf_rsp
*
rsp
=
data
;
void
*
ptr
=
rsp
->
data
;
void
*
req
=
chan
->
conf_req
;
...
...
@@ -1738,7 +1730,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
break
;
case
L2CAP_CONF_FLUSH_TO
:
pi
->
flush_to
=
val
;
chan
->
flush_to
=
val
;
break
;
case
L2CAP_CONF_QOS
:
...
...
@@ -1751,7 +1743,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
case
L2CAP_CONF_FCS
:
if
(
val
==
L2CAP_FCS_NONE
)
pi
->
conf_state
|=
L2CAP_CONF_NO_FCS_RECV
;
chan
->
conf_state
|=
L2CAP_CONF_NO_FCS_RECV
;
break
;
...
...
@@ -1768,25 +1760,25 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
if
(
chan
->
num_conf_rsp
||
chan
->
num_conf_req
>
1
)
goto
done
;
switch
(
pi
->
mode
)
{
switch
(
chan
->
mode
)
{
case
L2CAP_MODE_STREAMING
:
case
L2CAP_MODE_ERTM
:
if
(
!
(
pi
->
conf_state
&
L2CAP_CONF_STATE2_DEVICE
))
{
pi
->
mode
=
l2cap_select_mode
(
rfc
.
mode
,
pi
->
conn
->
feat_mask
);
if
(
!
(
chan
->
conf_state
&
L2CAP_CONF_STATE2_DEVICE
))
{
chan
->
mode
=
l2cap_select_mode
(
rfc
.
mode
,
chan
->
conn
->
feat_mask
);
break
;
}
if
(
pi
->
mode
!=
rfc
.
mode
)
if
(
chan
->
mode
!=
rfc
.
mode
)
return
-
ECONNREFUSED
;
break
;
}
done:
if
(
pi
->
mode
!=
rfc
.
mode
)
{
if
(
chan
->
mode
!=
rfc
.
mode
)
{
result
=
L2CAP_CONF_UNACCEPT
;
rfc
.
mode
=
pi
->
mode
;
rfc
.
mode
=
chan
->
mode
;
if
(
chan
->
num_conf_rsp
==
1
)
return
-
ECONNREFUSED
;
...
...
@@ -1803,23 +1795,23 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
if
(
mtu
<
L2CAP_DEFAULT_MIN_MTU
)
result
=
L2CAP_CONF_UNACCEPT
;
else
{
pi
->
omtu
=
mtu
;
pi
->
conf_state
|=
L2CAP_CONF_MTU_DONE
;
chan
->
omtu
=
mtu
;
chan
->
conf_state
|=
L2CAP_CONF_MTU_DONE
;
}
l2cap_add_conf_opt
(
&
ptr
,
L2CAP_CONF_MTU
,
2
,
pi
->
omtu
);
l2cap_add_conf_opt
(
&
ptr
,
L2CAP_CONF_MTU
,
2
,
chan
->
omtu
);
switch
(
rfc
.
mode
)
{
case
L2CAP_MODE_BASIC
:
pi
->
fcs
=
L2CAP_FCS_NONE
;
pi
->
conf_state
|=
L2CAP_CONF_MODE_DONE
;
chan
->
fcs
=
L2CAP_FCS_NONE
;
chan
->
conf_state
|=
L2CAP_CONF_MODE_DONE
;
break
;
case
L2CAP_MODE_ERTM
:
chan
->
remote_tx_win
=
rfc
.
txwin_size
;
chan
->
remote_max_tx
=
rfc
.
max_transmit
;
if
(
le16_to_cpu
(
rfc
.
max_pdu_size
)
>
pi
->
conn
->
mtu
-
10
)
rfc
.
max_pdu_size
=
cpu_to_le16
(
pi
->
conn
->
mtu
-
10
);
if
(
le16_to_cpu
(
rfc
.
max_pdu_size
)
>
chan
->
conn
->
mtu
-
10
)
rfc
.
max_pdu_size
=
cpu_to_le16
(
chan
->
conn
->
mtu
-
10
);
chan
->
remote_mps
=
le16_to_cpu
(
rfc
.
max_pdu_size
);
...
...
@@ -1828,7 +1820,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
rfc
.
monitor_timeout
=
le16_to_cpu
(
L2CAP_DEFAULT_MONITOR_TO
);
pi
->
conf_state
|=
L2CAP_CONF_MODE_DONE
;
chan
->
conf_state
|=
L2CAP_CONF_MODE_DONE
;
l2cap_add_conf_opt
(
&
ptr
,
L2CAP_CONF_RFC
,
sizeof
(
rfc
),
(
unsigned
long
)
&
rfc
);
...
...
@@ -1836,12 +1828,12 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
break
;
case
L2CAP_MODE_STREAMING
:
if
(
le16_to_cpu
(
rfc
.
max_pdu_size
)
>
pi
->
conn
->
mtu
-
10
)
rfc
.
max_pdu_size
=
cpu_to_le16
(
pi
->
conn
->
mtu
-
10
);
if
(
le16_to_cpu
(
rfc
.
max_pdu_size
)
>
chan
->
conn
->
mtu
-
10
)
rfc
.
max_pdu_size
=
cpu_to_le16
(
chan
->
conn
->
mtu
-
10
);
chan
->
remote_mps
=
le16_to_cpu
(
rfc
.
max_pdu_size
);
pi
->
conf_state
|=
L2CAP_CONF_MODE_DONE
;
chan
->
conf_state
|=
L2CAP_CONF_MODE_DONE
;
l2cap_add_conf_opt
(
&
ptr
,
L2CAP_CONF_RFC
,
sizeof
(
rfc
),
(
unsigned
long
)
&
rfc
);
...
...
@@ -1852,29 +1844,28 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
result
=
L2CAP_CONF_UNACCEPT
;
memset
(
&
rfc
,
0
,
sizeof
(
rfc
));
rfc
.
mode
=
pi
->
mode
;
rfc
.
mode
=
chan
->
mode
;
}
if
(
result
==
L2CAP_CONF_SUCCESS
)
pi
->
conf_state
|=
L2CAP_CONF_OUTPUT_DONE
;
chan
->
conf_state
|=
L2CAP_CONF_OUTPUT_DONE
;
}
rsp
->
scid
=
cpu_to_le16
(
pi
->
dcid
);
rsp
->
scid
=
cpu_to_le16
(
chan
->
dcid
);
rsp
->
result
=
cpu_to_le16
(
result
);
rsp
->
flags
=
cpu_to_le16
(
0x0000
);
return
ptr
-
data
;
}
static
int
l2cap_parse_conf_rsp
(
struct
sock
*
sk
,
void
*
rsp
,
int
len
,
void
*
data
,
u16
*
result
)
static
int
l2cap_parse_conf_rsp
(
struct
l2cap_chan
*
chan
,
void
*
rsp
,
int
len
,
void
*
data
,
u16
*
result
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
struct
l2cap_conf_req
*
req
=
data
;
void
*
ptr
=
req
->
data
;
int
type
,
olen
;
unsigned
long
val
;
struct
l2cap_conf_rfc
rfc
;
BT_DBG
(
"
sk %p, rsp %p, len %d, req %p"
,
sk
,
rsp
,
len
,
data
);
BT_DBG
(
"
chan %p, rsp %p, len %d, req %p"
,
chan
,
rsp
,
len
,
data
);
while
(
len
>=
L2CAP_CONF_OPT_SIZE
)
{
len
-=
l2cap_get_conf_opt
(
&
rsp
,
&
type
,
&
olen
,
&
val
);
...
...
@@ -1883,27 +1874,27 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data,
case
L2CAP_CONF_MTU
:
if
(
val
<
L2CAP_DEFAULT_MIN_MTU
)
{
*
result
=
L2CAP_CONF_UNACCEPT
;
pi
->
imtu
=
L2CAP_DEFAULT_MIN_MTU
;
chan
->
imtu
=
L2CAP_DEFAULT_MIN_MTU
;
}
else
pi
->
imtu
=
val
;
l2cap_add_conf_opt
(
&
ptr
,
L2CAP_CONF_MTU
,
2
,
pi
->
imtu
);
chan
->
imtu
=
val
;
l2cap_add_conf_opt
(
&
ptr
,
L2CAP_CONF_MTU
,
2
,
chan
->
imtu
);
break
;
case
L2CAP_CONF_FLUSH_TO
:
pi
->
flush_to
=
val
;
chan
->
flush_to
=
val
;
l2cap_add_conf_opt
(
&
ptr
,
L2CAP_CONF_FLUSH_TO
,
2
,
pi
->
flush_to
);
2
,
chan
->
flush_to
);
break
;
case
L2CAP_CONF_RFC
:
if
(
olen
==
sizeof
(
rfc
))
memcpy
(
&
rfc
,
(
void
*
)
val
,
olen
);
if
((
pi
->
conf_state
&
L2CAP_CONF_STATE2_DEVICE
)
&&
rfc
.
mode
!=
pi
->
mode
)
if
((
chan
->
conf_state
&
L2CAP_CONF_STATE2_DEVICE
)
&&
rfc
.
mode
!=
chan
->
mode
)
return
-
ECONNREFUSED
;
pi
->
fcs
=
0
;
chan
->
fcs
=
0
;
l2cap_add_conf_opt
(
&
ptr
,
L2CAP_CONF_RFC
,
sizeof
(
rfc
),
(
unsigned
long
)
&
rfc
);
...
...
@@ -1911,78 +1902,74 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data,
}
}
if
(
pi
->
mode
==
L2CAP_MODE_BASIC
&&
pi
->
mode
!=
rfc
.
mode
)
if
(
chan
->
mode
==
L2CAP_MODE_BASIC
&&
chan
->
mode
!=
rfc
.
mode
)
return
-
ECONNREFUSED
;
pi
->
mode
=
rfc
.
mode
;
chan
->
mode
=
rfc
.
mode
;
if
(
*
result
==
L2CAP_CONF_SUCCESS
)
{
switch
(
rfc
.
mode
)
{
case
L2CAP_MODE_ERTM
:
pi
->
retrans_timeout
=
le16_to_cpu
(
rfc
.
retrans_timeout
);
pi
->
monitor_timeout
=
le16_to_cpu
(
rfc
.
monitor_timeout
);
pi
->
mps
=
le16_to_cpu
(
rfc
.
max_pdu_size
);
chan
->
retrans_timeout
=
le16_to_cpu
(
rfc
.
retrans_timeout
);
chan
->
monitor_timeout
=
le16_to_cpu
(
rfc
.
monitor_timeout
);
chan
->
mps
=
le16_to_cpu
(
rfc
.
max_pdu_size
);
break
;
case
L2CAP_MODE_STREAMING
:
pi
->
mps
=
le16_to_cpu
(
rfc
.
max_pdu_size
);
chan
->
mps
=
le16_to_cpu
(
rfc
.
max_pdu_size
);
}
}
req
->
dcid
=
cpu_to_le16
(
pi
->
dcid
);
req
->
dcid
=
cpu_to_le16
(
chan
->
dcid
);
req
->
flags
=
cpu_to_le16
(
0x0000
);
return
ptr
-
data
;
}
static
int
l2cap_build_conf_rsp
(
struct
sock
*
sk
,
void
*
data
,
u16
result
,
u16
flags
)
static
int
l2cap_build_conf_rsp
(
struct
l2cap_chan
*
chan
,
void
*
data
,
u16
result
,
u16
flags
)
{
struct
l2cap_conf_rsp
*
rsp
=
data
;
void
*
ptr
=
rsp
->
data
;
BT_DBG
(
"
sk %p"
,
sk
);
BT_DBG
(
"
chan %p"
,
chan
);
rsp
->
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
dcid
);
rsp
->
scid
=
cpu_to_le16
(
chan
->
dcid
);
rsp
->
result
=
cpu_to_le16
(
result
);
rsp
->
flags
=
cpu_to_le16
(
flags
);
return
ptr
-
data
;
}
void
__l2cap_connect_rsp_defer
(
struct
sock
*
sk
)
void
__l2cap_connect_rsp_defer
(
struct
l2cap_chan
*
chan
)
{
struct
l2cap_conn_rsp
rsp
;
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
struct
l2cap_conn
*
conn
=
chan
->
conn
;
u8
buf
[
128
];
sk
->
sk_state
=
BT_CONFIG
;
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
(
L2CAP_CR_SUCCESS
);
rsp
.
status
=
cpu_to_le16
(
L2CAP_CS_NO_INFO
);
l2cap_send_cmd
(
conn
,
chan
->
ident
,
L2CAP_CONN_RSP
,
sizeof
(
rsp
),
&
rsp
);
if
(
l2cap_pi
(
sk
)
->
conf_state
&
L2CAP_CONF_REQ_SENT
)
if
(
chan
->
conf_state
&
L2CAP_CONF_REQ_SENT
)
return
;
l2cap_pi
(
sk
)
->
conf_state
|=
L2CAP_CONF_REQ_SENT
;
chan
->
conf_state
|=
L2CAP_CONF_REQ_SENT
;
l2cap_send_cmd
(
conn
,
l2cap_get_ident
(
conn
),
L2CAP_CONF_REQ
,
l2cap_build_conf_req
(
chan
,
buf
),
buf
);
chan
->
num_conf_req
++
;
}
static
void
l2cap_conf_rfc_get
(
struct
sock
*
sk
,
void
*
rsp
,
int
len
)
static
void
l2cap_conf_rfc_get
(
struct
l2cap_chan
*
chan
,
void
*
rsp
,
int
len
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
int
type
,
olen
;
unsigned
long
val
;
struct
l2cap_conf_rfc
rfc
;
BT_DBG
(
"
sk %p, rsp %p, len %d"
,
sk
,
rsp
,
len
);
BT_DBG
(
"
chan %p, rsp %p, len %d"
,
chan
,
rsp
,
len
);
if
((
pi
->
mode
!=
L2CAP_MODE_ERTM
)
&&
(
pi
->
mode
!=
L2CAP_MODE_STREAMING
))
if
((
chan
->
mode
!=
L2CAP_MODE_ERTM
)
&&
(
chan
->
mode
!=
L2CAP_MODE_STREAMING
))
return
;
while
(
len
>=
L2CAP_CONF_OPT_SIZE
)
{
...
...
@@ -1999,12 +1986,12 @@ static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
done:
switch
(
rfc
.
mode
)
{
case
L2CAP_MODE_ERTM
:
pi
->
retrans_timeout
=
le16_to_cpu
(
rfc
.
retrans_timeout
);
pi
->
monitor_timeout
=
le16_to_cpu
(
rfc
.
monitor_timeout
);
pi
->
mps
=
le16_to_cpu
(
rfc
.
max_pdu_size
);
chan
->
retrans_timeout
=
le16_to_cpu
(
rfc
.
retrans_timeout
);
chan
->
monitor_timeout
=
le16_to_cpu
(
rfc
.
monitor_timeout
);
chan
->
mps
=
le16_to_cpu
(
rfc
.
max_pdu_size
);
break
;
case
L2CAP_MODE_STREAMING
:
pi
->
mps
=
le16_to_cpu
(
rfc
.
max_pdu_size
);
chan
->
mps
=
le16_to_cpu
(
rfc
.
max_pdu_size
);
}
}
...
...
@@ -2076,6 +2063,8 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
goto
response
;
}
l2cap_pi
(
sk
)
->
chan
=
chan
;
write_lock_bh
(
&
conn
->
chan_lock
);
/* Check if we already have channel with that dcid */
...
...
@@ -2091,23 +2080,21 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
l2cap_sock_init
(
sk
,
parent
);
bacpy
(
&
bt_sk
(
sk
)
->
src
,
conn
->
src
);
bacpy
(
&
bt_sk
(
sk
)
->
dst
,
conn
->
dst
);
l2cap_pi
(
sk
)
->
psm
=
psm
;
l2cap_pi
(
sk
)
->
dcid
=
scid
;
chan
->
psm
=
psm
;
chan
->
dcid
=
scid
;
bt_accept_enqueue
(
parent
,
sk
);
__l2cap_chan_add
(
conn
,
chan
);
l2cap_pi
(
sk
)
->
chan
=
chan
;
dcid
=
l2cap_pi
(
sk
)
->
scid
;
dcid
=
chan
->
scid
;
l2cap_sock_set_timer
(
sk
,
sk
->
sk_sndtimeo
);
chan
->
ident
=
cmd
->
ident
;
if
(
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_DONE
)
{
if
(
l2cap_check_security
(
sk
))
{
if
(
l2cap_check_security
(
chan
))
{
if
(
bt_sk
(
sk
)
->
defer_setup
)
{
sk
->
sk_state
=
BT_CONNECT2
;
result
=
L2CAP_CR_PEND
;
...
...
@@ -2155,10 +2142,10 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
L2CAP_INFO_REQ
,
sizeof
(
info
),
&
info
);
}
if
(
chan
&&
!
(
l2cap_pi
(
sk
)
->
conf_state
&
L2CAP_CONF_REQ_SENT
)
&&
if
(
chan
&&
!
(
chan
->
conf_state
&
L2CAP_CONF_REQ_SENT
)
&&
result
==
L2CAP_CR_SUCCESS
)
{
u8
buf
[
128
];
l2cap_pi
(
sk
)
->
conf_state
|=
L2CAP_CONF_REQ_SENT
;
chan
->
conf_state
|=
L2CAP_CONF_REQ_SENT
;
l2cap_send_cmd
(
conn
,
l2cap_get_ident
(
conn
),
L2CAP_CONF_REQ
,
l2cap_build_conf_req
(
chan
,
buf
),
buf
);
chan
->
num_conf_req
++
;
...
...
@@ -2198,13 +2185,13 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
case
L2CAP_CR_SUCCESS
:
sk
->
sk_state
=
BT_CONFIG
;
chan
->
ident
=
0
;
l2cap_pi
(
sk
)
->
dcid
=
dcid
;
l2cap_pi
(
sk
)
->
conf_state
&=
~
L2CAP_CONF_CONNECT_PEND
;
chan
->
dcid
=
dcid
;
chan
->
conf_state
&=
~
L2CAP_CONF_CONNECT_PEND
;
if
(
l2cap_pi
(
sk
)
->
conf_state
&
L2CAP_CONF_REQ_SENT
)
if
(
chan
->
conf_state
&
L2CAP_CONF_REQ_SENT
)
break
;
l2cap_pi
(
sk
)
->
conf_state
|=
L2CAP_CONF_REQ_SENT
;
chan
->
conf_state
|=
L2CAP_CONF_REQ_SENT
;
l2cap_send_cmd
(
conn
,
l2cap_get_ident
(
conn
),
L2CAP_CONF_REQ
,
l2cap_build_conf_req
(
chan
,
req
),
req
);
...
...
@@ -2212,7 +2199,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
break
;
case
L2CAP_CR_PEND
:
l2cap_pi
(
sk
)
->
conf_state
|=
L2CAP_CONF_CONNECT_PEND
;
chan
->
conf_state
|=
L2CAP_CONF_CONNECT_PEND
;
break
;
default:
...
...
@@ -2232,15 +2219,17 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
return
0
;
}
static
inline
void
set_default_fcs
(
struct
l2cap_
pinfo
*
pi
)
static
inline
void
set_default_fcs
(
struct
l2cap_
chan
*
chan
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
chan
->
sk
);
/* FCS is enabled only in ERTM or streaming mode, if one or both
* sides request it.
*/
if
(
pi
->
mode
!=
L2CAP_MODE_ERTM
&&
pi
->
mode
!=
L2CAP_MODE_STREAMING
)
pi
->
fcs
=
L2CAP_FCS_NONE
;
else
if
(
!
(
pi
->
conf_state
&
L2CAP_CONF_NO_FCS_RECV
))
pi
->
fcs
=
L2CAP_FCS_CRC16
;
if
(
chan
->
mode
!=
L2CAP_MODE_ERTM
&&
chan
->
mode
!=
L2CAP_MODE_STREAMING
)
chan
->
fcs
=
L2CAP_FCS_NONE
;
else
if
(
!
(
pi
->
c
han
->
c
onf_state
&
L2CAP_CONF_NO_FCS_RECV
))
chan
->
fcs
=
L2CAP_FCS_CRC16
;
}
static
inline
int
l2cap_config_req
(
struct
l2cap_conn
*
conn
,
struct
l2cap_cmd_hdr
*
cmd
,
u16
cmd_len
,
u8
*
data
)
...
...
@@ -2276,7 +2265,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
len
=
cmd_len
-
sizeof
(
*
req
);
if
(
chan
->
conf_len
+
len
>
sizeof
(
chan
->
conf_req
))
{
l2cap_send_cmd
(
conn
,
cmd
->
ident
,
L2CAP_CONF_RSP
,
l2cap_build_conf_rsp
(
sk
,
rsp
,
l2cap_build_conf_rsp
(
chan
,
rsp
,
L2CAP_CONF_REJECT
,
flags
),
rsp
);
goto
unlock
;
}
...
...
@@ -2288,7 +2277,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
if
(
flags
&
0x0001
)
{
/* Incomplete config. Send empty response. */
l2cap_send_cmd
(
conn
,
cmd
->
ident
,
L2CAP_CONF_RSP
,
l2cap_build_conf_rsp
(
sk
,
rsp
,
l2cap_build_conf_rsp
(
chan
,
rsp
,
L2CAP_CONF_SUCCESS
,
0x0001
),
rsp
);
goto
unlock
;
}
...
...
@@ -2306,27 +2295,27 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
/* Reset config buffer. */
chan
->
conf_len
=
0
;
if
(
!
(
l2cap_pi
(
sk
)
->
conf_state
&
L2CAP_CONF_OUTPUT_DONE
))
if
(
!
(
chan
->
conf_state
&
L2CAP_CONF_OUTPUT_DONE
))
goto
unlock
;
if
(
l2cap_pi
(
sk
)
->
conf_state
&
L2CAP_CONF_INPUT_DONE
)
{
set_default_fcs
(
l2cap_pi
(
sk
)
);
if
(
chan
->
conf_state
&
L2CAP_CONF_INPUT_DONE
)
{
set_default_fcs
(
chan
);
sk
->
sk_state
=
BT_CONNECTED
;
chan
->
next_tx_seq
=
0
;
chan
->
expected_tx_seq
=
0
;
skb_queue_head_init
(
&
chan
->
tx_q
);
if
(
l2cap_pi
(
sk
)
->
mode
==
L2CAP_MODE_ERTM
)
if
(
chan
->
mode
==
L2CAP_MODE_ERTM
)
l2cap_ertm_init
(
chan
);
l2cap_chan_ready
(
sk
);
goto
unlock
;
}
if
(
!
(
l2cap_pi
(
sk
)
->
conf_state
&
L2CAP_CONF_REQ_SENT
))
{
if
(
!
(
chan
->
conf_state
&
L2CAP_CONF_REQ_SENT
))
{
u8
buf
[
64
];
l2cap_pi
(
sk
)
->
conf_state
|=
L2CAP_CONF_REQ_SENT
;
chan
->
conf_state
|=
L2CAP_CONF_REQ_SENT
;
l2cap_send_cmd
(
conn
,
l2cap_get_ident
(
conn
),
L2CAP_CONF_REQ
,
l2cap_build_conf_req
(
chan
,
buf
),
buf
);
chan
->
num_conf_req
++
;
...
...
@@ -2360,7 +2349,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
switch
(
result
)
{
case
L2CAP_CONF_SUCCESS
:
l2cap_conf_rfc_get
(
sk
,
rsp
->
data
,
len
);
l2cap_conf_rfc_get
(
chan
,
rsp
->
data
,
len
);
break
;
case
L2CAP_CONF_UNACCEPT
:
...
...
@@ -2374,8 +2363,8 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
/* throw out any old stored conf requests */
result
=
L2CAP_CONF_SUCCESS
;
len
=
l2cap_parse_conf_rsp
(
sk
,
rsp
->
data
,
len
,
req
,
&
result
);
len
=
l2cap_parse_conf_rsp
(
chan
,
rsp
->
data
,
len
,
req
,
&
result
);
if
(
len
<
0
)
{
l2cap_send_disconn_req
(
conn
,
chan
,
ECONNRESET
);
goto
done
;
...
...
@@ -2399,16 +2388,16 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
if
(
flags
&
0x01
)
goto
done
;
l2cap_pi
(
sk
)
->
conf_state
|=
L2CAP_CONF_INPUT_DONE
;
chan
->
conf_state
|=
L2CAP_CONF_INPUT_DONE
;
if
(
l2cap_pi
(
sk
)
->
conf_state
&
L2CAP_CONF_OUTPUT_DONE
)
{
set_default_fcs
(
l2cap_pi
(
sk
)
);
if
(
chan
->
conf_state
&
L2CAP_CONF_OUTPUT_DONE
)
{
set_default_fcs
(
chan
);
sk
->
sk_state
=
BT_CONNECTED
;
chan
->
next_tx_seq
=
0
;
chan
->
expected_tx_seq
=
0
;
skb_queue_head_init
(
&
chan
->
tx_q
);
if
(
l2cap_pi
(
sk
)
->
mode
==
L2CAP_MODE_ERTM
)
if
(
chan
->
mode
==
L2CAP_MODE_ERTM
)
l2cap_ertm_init
(
chan
);
l2cap_chan_ready
(
sk
);
...
...
@@ -2438,8 +2427,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
sk
=
chan
->
sk
;
rsp
.
dcid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
rsp
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
dcid
);
rsp
.
dcid
=
cpu_to_le16
(
chan
->
scid
);
rsp
.
scid
=
cpu_to_le16
(
chan
->
dcid
);
l2cap_send_cmd
(
conn
,
cmd
->
ident
,
L2CAP_DISCONN_RSP
,
sizeof
(
rsp
),
&
rsp
);
sk
->
sk_shutdown
=
SHUTDOWN_MASK
;
...
...
@@ -2774,12 +2763,12 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
kfree_skb
(
skb
);
}
static
int
l2cap_check_fcs
(
struct
l2cap_
pinfo
*
pi
,
struct
sk_buff
*
skb
)
static
int
l2cap_check_fcs
(
struct
l2cap_
chan
*
chan
,
struct
sk_buff
*
skb
)
{
u16
our_fcs
,
rcv_fcs
;
int
hdr_size
=
L2CAP_HDR_SIZE
+
2
;
if
(
pi
->
fcs
==
L2CAP_FCS_CRC16
)
{
if
(
chan
->
fcs
==
L2CAP_FCS_CRC16
)
{
skb_trim
(
skb
,
skb
->
len
-
2
);
rcv_fcs
=
get_unaligned_le16
(
skb
->
data
+
skb
->
len
);
our_fcs
=
crc16
(
0
,
skb
->
data
-
hdr_size
,
skb
->
len
+
hdr_size
);
...
...
@@ -2860,7 +2849,6 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb,
static
int
l2cap_ertm_reassembly_sdu
(
struct
l2cap_chan
*
chan
,
struct
sk_buff
*
skb
,
u16
control
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
chan
->
sk
);
struct
sk_buff
*
_skb
;
int
err
;
...
...
@@ -2881,7 +2869,7 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk
chan
->
sdu_len
=
get_unaligned_le16
(
skb
->
data
);
if
(
chan
->
sdu_len
>
pi
->
imtu
)
if
(
chan
->
sdu_len
>
chan
->
imtu
)
goto
disconnect
;
chan
->
sdu
=
bt_skb_alloc
(
chan
->
sdu_len
,
GFP_ATOMIC
);
...
...
@@ -2924,7 +2912,7 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk
if
(
!
(
chan
->
conn_state
&
L2CAP_CONN_SAR_RETRY
))
{
chan
->
partial_sdu_len
+=
skb
->
len
;
if
(
chan
->
partial_sdu_len
>
pi
->
imtu
)
if
(
chan
->
partial_sdu_len
>
chan
->
imtu
)
goto
drop
;
if
(
chan
->
partial_sdu_len
!=
chan
->
sdu_len
)
...
...
@@ -2961,7 +2949,7 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk
chan
->
sdu
=
NULL
;
disconnect:
l2cap_send_disconn_req
(
pi
->
conn
,
chan
,
ECONNRESET
);
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
ECONNRESET
);
kfree_skb
(
skb
);
return
0
;
}
...
...
@@ -3022,7 +3010,7 @@ static void l2cap_busy_work(struct work_struct *work)
if
(
n_tries
++
>
L2CAP_LOCAL_BUSY_TRIES
)
{
err
=
-
EBUSY
;
l2cap_send_disconn_req
(
l2cap_pi
(
sk
)
->
conn
,
chan
,
EBUSY
);
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
EBUSY
);
break
;
}
...
...
@@ -3092,7 +3080,6 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c
static
int
l2cap_streaming_reassembly_sdu
(
struct
l2cap_chan
*
chan
,
struct
sk_buff
*
skb
,
u16
control
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
chan
->
sk
);
struct
sk_buff
*
_skb
;
int
err
=
-
EINVAL
;
...
...
@@ -3123,7 +3110,7 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf
chan
->
sdu_len
=
get_unaligned_le16
(
skb
->
data
);
skb_pull
(
skb
,
2
);
if
(
chan
->
sdu_len
>
pi
->
imtu
)
{
if
(
chan
->
sdu_len
>
chan
->
imtu
)
{
err
=
-
EMSGSIZE
;
break
;
}
...
...
@@ -3164,7 +3151,7 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf
chan
->
conn_state
&=
~
L2CAP_CONN_SAR_SDU
;
chan
->
partial_sdu_len
+=
skb
->
len
;
if
(
chan
->
partial_sdu_len
>
pi
->
imtu
)
if
(
chan
->
partial_sdu_len
>
chan
->
imtu
)
goto
drop
;
if
(
chan
->
partial_sdu_len
==
chan
->
sdu_len
)
{
...
...
@@ -3241,12 +3228,11 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
static
inline
int
l2cap_data_channel_iframe
(
struct
l2cap_chan
*
chan
,
u16
rx_control
,
struct
sk_buff
*
skb
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
chan
->
sk
);
u8
tx_seq
=
__get_txseq
(
rx_control
);
u8
req_seq
=
__get_reqseq
(
rx_control
);
u8
sar
=
rx_control
>>
L2CAP_CTRL_SAR_SHIFT
;
int
tx_seq_offset
,
expected_tx_seq_offset
;
int
num_to_ack
=
(
pi
->
tx_win
/
6
)
+
1
;
int
num_to_ack
=
(
chan
->
tx_win
/
6
)
+
1
;
int
err
=
0
;
BT_DBG
(
"chan %p len %d tx_seq %d rx_control 0x%4.4x"
,
chan
,
skb
->
len
,
...
...
@@ -3271,8 +3257,8 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
tx_seq_offset
+=
64
;
/* invalid tx_seq */
if
(
tx_seq_offset
>=
pi
->
tx_win
)
{
l2cap_send_disconn_req
(
pi
->
conn
,
chan
,
ECONNRESET
);
if
(
tx_seq_offset
>=
chan
->
tx_win
)
{
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
ECONNRESET
);
goto
drop
;
}
...
...
@@ -3539,7 +3525,6 @@ static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_cont
static
int
l2cap_ertm_data_rcv
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
)
{
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
u16
control
;
u8
req_seq
;
int
len
,
next_tx_seq_offset
,
req_seq_offset
;
...
...
@@ -3553,17 +3538,17 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
* Receiver will miss it and start proper recovery
* procedures and ask retransmission.
*/
if
(
l2cap_check_fcs
(
pi
,
skb
))
if
(
l2cap_check_fcs
(
chan
,
skb
))
goto
drop
;
if
(
__is_sar_start
(
control
)
&&
__is_iframe
(
control
))
len
-=
2
;
if
(
pi
->
fcs
==
L2CAP_FCS_CRC16
)
if
(
chan
->
fcs
==
L2CAP_FCS_CRC16
)
len
-=
2
;
if
(
len
>
pi
->
mps
)
{
l2cap_send_disconn_req
(
pi
->
conn
,
chan
,
ECONNRESET
);
if
(
len
>
chan
->
mps
)
{
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
ECONNRESET
);
goto
drop
;
}
...
...
@@ -3579,13 +3564,13 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
/* check for invalid req-seq */
if
(
req_seq_offset
>
next_tx_seq_offset
)
{
l2cap_send_disconn_req
(
pi
->
conn
,
chan
,
ECONNRESET
);
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
ECONNRESET
);
goto
drop
;
}
if
(
__is_iframe
(
control
))
{
if
(
len
<
0
)
{
l2cap_send_disconn_req
(
pi
->
conn
,
chan
,
ECONNRESET
);
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
ECONNRESET
);
goto
drop
;
}
...
...
@@ -3593,7 +3578,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
}
else
{
if
(
len
!=
0
)
{
BT_ERR
(
"%d"
,
len
);
l2cap_send_disconn_req
(
pi
->
conn
,
chan
,
ECONNRESET
);
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
ECONNRESET
);
goto
drop
;
}
...
...
@@ -3630,14 +3615,14 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
if
(
sk
->
sk_state
!=
BT_CONNECTED
)
goto
drop
;
switch
(
pi
->
mode
)
{
switch
(
chan
->
mode
)
{
case
L2CAP_MODE_BASIC
:
/* If socket recv buffers overflows we drop data here
* which is *bad* because L2CAP has to be reliable.
* But we don't have any other choice. L2CAP doesn't
* provide flow control mechanism. */
if
(
pi
->
imtu
<
skb
->
len
)
if
(
chan
->
imtu
<
skb
->
len
)
goto
drop
;
if
(
!
sock_queue_rcv_skb
(
sk
,
skb
))
...
...
@@ -3659,16 +3644,16 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
skb_pull
(
skb
,
2
);
len
=
skb
->
len
;
if
(
l2cap_check_fcs
(
pi
,
skb
))
if
(
l2cap_check_fcs
(
chan
,
skb
))
goto
drop
;
if
(
__is_sar_start
(
control
))
len
-=
2
;
if
(
pi
->
fcs
==
L2CAP_FCS_CRC16
)
if
(
chan
->
fcs
==
L2CAP_FCS_CRC16
)
len
-=
2
;
if
(
len
>
pi
->
mps
||
len
<
0
||
__is_sframe
(
control
))
if
(
len
>
chan
->
mps
||
len
<
0
||
__is_sframe
(
control
))
goto
drop
;
tx_seq
=
__get_txseq
(
control
);
...
...
@@ -3683,7 +3668,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
goto
done
;
default:
BT_DBG
(
"chan %p: bad mode 0x%2.2x"
,
chan
,
pi
->
mode
);
BT_DBG
(
"chan %p: bad mode 0x%2.2x"
,
chan
,
chan
->
mode
);
break
;
}
...
...
@@ -3712,7 +3697,7 @@ static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, str
if
(
sk
->
sk_state
!=
BT_BOUND
&&
sk
->
sk_state
!=
BT_CONNECTED
)
goto
drop
;
if
(
l2cap_pi
(
sk
)
->
imtu
<
skb
->
len
)
if
(
l2cap_pi
(
sk
)
->
chan
->
imtu
<
skb
->
len
)
goto
drop
;
if
(
!
sock_queue_rcv_skb
(
sk
,
skb
))
...
...
@@ -3742,7 +3727,7 @@ static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct
if
(
sk
->
sk_state
!=
BT_BOUND
&&
sk
->
sk_state
!=
BT_CONNECTED
)
goto
drop
;
if
(
l2cap_pi
(
sk
)
->
imtu
<
skb
->
len
)
if
(
l2cap_pi
(
sk
)
->
chan
->
imtu
<
skb
->
len
)
goto
drop
;
if
(
!
sock_queue_rcv_skb
(
sk
,
skb
))
...
...
@@ -3812,17 +3797,19 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
/* Find listening sockets and check their link_mode */
read_lock
(
&
l2cap_sk_list
.
lock
);
sk_for_each
(
sk
,
node
,
&
l2cap_sk_list
.
head
)
{
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
if
(
sk
->
sk_state
!=
BT_LISTEN
)
continue
;
if
(
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
&
hdev
->
bdaddr
))
{
lm1
|=
HCI_LM_ACCEPT
;
if
(
l2cap_pi
(
sk
)
->
role_switch
)
if
(
chan
->
role_switch
)
lm1
|=
HCI_LM_MASTER
;
exact
++
;
}
else
if
(
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
BDADDR_ANY
))
{
lm2
|=
HCI_LM_ACCEPT
;
if
(
l2cap_pi
(
sk
)
->
role_switch
)
if
(
chan
->
role_switch
)
lm2
|=
HCI_LM_MASTER
;
}
}
...
...
@@ -3874,19 +3861,21 @@ static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
return
0
;
}
static
inline
void
l2cap_check_encryption
(
struct
sock
*
sk
,
u8
encrypt
)
static
inline
void
l2cap_check_encryption
(
struct
l2cap_chan
*
chan
,
u8
encrypt
)
{
struct
sock
*
sk
=
chan
->
sk
;
if
(
sk
->
sk_type
!=
SOCK_SEQPACKET
&&
sk
->
sk_type
!=
SOCK_STREAM
)
return
;
if
(
encrypt
==
0x00
)
{
if
(
l2cap_pi
(
sk
)
->
sec_level
==
BT_SECURITY_MEDIUM
)
{
if
(
chan
->
sec_level
==
BT_SECURITY_MEDIUM
)
{
l2cap_sock_clear_timer
(
sk
);
l2cap_sock_set_timer
(
sk
,
HZ
*
5
);
}
else
if
(
l2cap_pi
(
sk
)
->
sec_level
==
BT_SECURITY_HIGH
)
}
else
if
(
chan
->
sec_level
==
BT_SECURITY_HIGH
)
__l2cap_sock_close
(
sk
,
ECONNREFUSED
);
}
else
{
if
(
l2cap_pi
(
sk
)
->
sec_level
==
BT_SECURITY_MEDIUM
)
if
(
chan
->
sec_level
==
BT_SECURITY_MEDIUM
)
l2cap_sock_clear_timer
(
sk
);
}
}
...
...
@@ -3908,14 +3897,14 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
bh_lock_sock
(
sk
);
if
(
l2cap_pi
(
sk
)
->
conf_state
&
L2CAP_CONF_CONNECT_PEND
)
{
if
(
chan
->
conf_state
&
L2CAP_CONF_CONNECT_PEND
)
{
bh_unlock_sock
(
sk
);
continue
;
}
if
(
!
status
&&
(
sk
->
sk_state
==
BT_CONNECTED
||
sk
->
sk_state
==
BT_CONFIG
))
{
l2cap_check_encryption
(
sk
,
encrypt
);
l2cap_check_encryption
(
chan
,
encrypt
);
bh_unlock_sock
(
sk
);
continue
;
}
...
...
@@ -3923,11 +3912,11 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
if
(
sk
->
sk_state
==
BT_CONNECT
)
{
if
(
!
status
)
{
struct
l2cap_conn_req
req
;
req
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
req
.
psm
=
l2cap_pi
(
sk
)
->
psm
;
req
.
scid
=
cpu_to_le16
(
chan
->
scid
);
req
.
psm
=
chan
->
psm
;
chan
->
ident
=
l2cap_get_ident
(
conn
);
l2cap_pi
(
sk
)
->
conf_state
|=
L2CAP_CONF_CONNECT_PEND
;
chan
->
conf_state
|=
L2CAP_CONF_CONNECT_PEND
;
l2cap_send_cmd
(
conn
,
chan
->
ident
,
L2CAP_CONN_REQ
,
sizeof
(
req
),
&
req
);
...
...
@@ -3948,8 +3937,8 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
result
=
L2CAP_CR_SEC_BLOCK
;
}
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
,
...
...
@@ -4021,10 +4010,10 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
if
(
chan
&&
chan
->
sk
)
{
struct
sock
*
sk
=
chan
->
sk
;
if
(
l2cap_pi
(
sk
)
->
imtu
<
len
-
L2CAP_HDR_SIZE
)
{
if
(
chan
->
imtu
<
len
-
L2CAP_HDR_SIZE
)
{
BT_ERR
(
"Frame exceeding recv MTU (len %d, "
"MTU %d)"
,
len
,
l2cap_pi
(
sk
)
->
imtu
);
chan
->
imtu
);
bh_unlock_sock
(
sk
);
l2cap_conn_unreliable
(
conn
,
ECOMM
);
goto
drop
;
...
...
@@ -4084,14 +4073,15 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p)
sk_for_each
(
sk
,
node
,
&
l2cap_sk_list
.
head
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
struct
l2cap_chan
*
chan
=
pi
->
chan
;
seq_printf
(
f
,
"%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d
\n
"
,
batostr
(
&
bt_sk
(
sk
)
->
src
),
batostr
(
&
bt_sk
(
sk
)
->
dst
),
sk
->
sk_state
,
__le16_to_cpu
(
pi
->
psm
),
pi
->
scid
,
pi
->
dcid
,
pi
->
imtu
,
pi
->
omtu
,
pi
->
sec_level
,
pi
->
mode
);
sk
->
sk_state
,
__le16_to_cpu
(
chan
->
psm
),
chan
->
scid
,
chan
->
dcid
,
chan
->
imtu
,
chan
->
omtu
,
chan
->
sec_level
,
chan
->
mode
);
}
read_unlock_bh
(
&
l2cap_sk_list
.
lock
);
...
...
net/bluetooth/l2cap_sock.c
View file @
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
View file @
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
View file @
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
View file @
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
))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment