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
63748aa8
Commit
63748aa8
authored
Feb 26, 2009
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-next-2.6
parents
43be6366
b1fb0683
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
968 additions
and
362 deletions
+968
-362
drivers/bluetooth/bfusb.c
drivers/bluetooth/bfusb.c
+1
-2
drivers/bluetooth/bt3c_cs.c
drivers/bluetooth/bt3c_cs.c
+2
-2
drivers/bluetooth/btusb.c
drivers/bluetooth/btusb.c
+23
-17
drivers/bluetooth/hci_h4.c
drivers/bluetooth/hci_h4.c
+1
-2
drivers/bluetooth/hci_ll.c
drivers/bluetooth/hci_ll.c
+1
-2
include/net/bluetooth/bluetooth.h
include/net/bluetooth/bluetooth.h
+12
-0
include/net/bluetooth/hci.h
include/net/bluetooth/hci.h
+8
-0
include/net/bluetooth/hci_core.h
include/net/bluetooth/hci_core.h
+57
-27
include/net/bluetooth/l2cap.h
include/net/bluetooth/l2cap.h
+10
-3
include/net/bluetooth/rfcomm.h
include/net/bluetooth/rfcomm.h
+12
-8
net/bluetooth/af_bluetooth.c
net/bluetooth/af_bluetooth.c
+7
-10
net/bluetooth/cmtp/core.c
net/bluetooth/cmtp/core.c
+1
-2
net/bluetooth/hci_conn.c
net/bluetooth/hci_conn.c
+41
-23
net/bluetooth/hci_core.c
net/bluetooth/hci_core.c
+1
-2
net/bluetooth/hci_event.c
net/bluetooth/hci_event.c
+21
-5
net/bluetooth/l2cap.c
net/bluetooth/l2cap.c
+440
-162
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/core.c
+100
-79
net/bluetooth/rfcomm/sock.c
net/bluetooth/rfcomm/sock.c
+179
-10
net/bluetooth/sco.c
net/bluetooth/sco.c
+51
-6
No files found.
drivers/bluetooth/bfusb.c
View file @
63748aa8
...
...
@@ -257,8 +257,7 @@ static inline int bfusb_recv_block(struct bfusb_data *data, int hdr, unsigned ch
if
(
hdr
&
0x10
)
{
BT_ERR
(
"%s error in block"
,
data
->
hdev
->
name
);
if
(
data
->
reassembly
)
kfree_skb
(
data
->
reassembly
);
kfree_skb
(
data
->
reassembly
);
data
->
reassembly
=
NULL
;
return
-
EIO
;
}
...
...
drivers/bluetooth/bt3c_cs.c
View file @
63748aa8
...
...
@@ -359,9 +359,9 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst)
BT_ERR
(
"Very strange (stat=0x%04x)"
,
stat
);
}
else
if
((
stat
&
0xff
)
!=
0xff
)
{
if
(
stat
&
0x0020
)
{
int
stat
=
bt3c_read
(
iobase
,
0x7002
)
&
0x10
;
int
stat
us
=
bt3c_read
(
iobase
,
0x7002
)
&
0x10
;
BT_INFO
(
"%s: Antenna %s"
,
info
->
hdev
->
name
,
stat
?
"out"
:
"in"
);
stat
us
?
"out"
:
"in"
);
}
if
(
stat
&
0x0001
)
bt3c_receive
(
info
);
...
...
drivers/bluetooth/btusb.c
View file @
63748aa8
...
...
@@ -35,7 +35,7 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#define VERSION "0.
4
"
#define VERSION "0.
5
"
static
int
ignore_dga
;
static
int
ignore_csr
;
...
...
@@ -171,6 +171,7 @@ struct btusb_data {
__u8
cmdreq_type
;
unsigned
int
sco_num
;
int
isoc_altsetting
;
int
suspend_count
;
};
...
...
@@ -496,11 +497,23 @@ static int btusb_open(struct hci_dev *hdev)
return
0
;
err
=
btusb_submit_intr_urb
(
hdev
,
GFP_KERNEL
);
if
(
err
<
0
)
goto
failed
;
err
=
btusb_submit_bulk_urb
(
hdev
,
GFP_KERNEL
);
if
(
err
<
0
)
{
clear_bit
(
BTUSB_INTR_RUNNING
,
&
data
->
flags
);
clear_bit
(
HCI_RUNNING
,
&
hdev
->
flags
)
;
usb_kill_anchored_urbs
(
&
data
->
intr_anchor
);
goto
failed
;
}
set_bit
(
BTUSB_BULK_RUNNING
,
&
data
->
flags
);
btusb_submit_bulk_urb
(
hdev
,
GFP_KERNEL
);
return
0
;
failed:
clear_bit
(
BTUSB_INTR_RUNNING
,
&
data
->
flags
);
clear_bit
(
HCI_RUNNING
,
&
hdev
->
flags
);
return
err
;
}
...
...
@@ -655,19 +668,10 @@ static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
BT_DBG
(
"%s evt %d"
,
hdev
->
name
,
evt
);
if
(
hdev
->
conn_hash
.
acl_num
>
0
)
{
if
(
!
test_and_set_bit
(
BTUSB_BULK_RUNNING
,
&
data
->
flags
))
{
if
(
btusb_submit_bulk_urb
(
hdev
,
GFP_ATOMIC
)
<
0
)
clear_bit
(
BTUSB_BULK_RUNNING
,
&
data
->
flags
);
else
btusb_submit_bulk_urb
(
hdev
,
GFP_ATOMIC
);
}
}
else
{
clear_bit
(
BTUSB_BULK_RUNNING
,
&
data
->
flags
);
usb_unlink_anchored_urbs
(
&
data
->
bulk_anchor
);
if
(
hdev
->
conn_hash
.
sco_num
!=
data
->
sco_num
)
{
data
->
sco_num
=
hdev
->
conn_hash
.
sco_num
;
schedule_work
(
&
data
->
work
);
}
schedule_work
(
&
data
->
work
);
}
static
int
inline
__set_isoc_interface
(
struct
hci_dev
*
hdev
,
int
altsetting
)
...
...
@@ -982,9 +986,11 @@ static int btusb_resume(struct usb_interface *intf)
}
if
(
test_bit
(
BTUSB_BULK_RUNNING
,
&
data
->
flags
))
{
if
(
btusb_submit_bulk_urb
(
hdev
,
GFP_NOIO
)
<
0
)
err
=
btusb_submit_bulk_urb
(
hdev
,
GFP_NOIO
);
if
(
err
<
0
)
{
clear_bit
(
BTUSB_BULK_RUNNING
,
&
data
->
flags
);
else
return
err
;
}
else
btusb_submit_bulk_urb
(
hdev
,
GFP_NOIO
);
}
...
...
drivers/bluetooth/hci_h4.c
View file @
63748aa8
...
...
@@ -102,8 +102,7 @@ static int h4_close(struct hci_uart *hu)
skb_queue_purge
(
&
h4
->
txq
);
if
(
h4
->
rx_skb
)
kfree_skb
(
h4
->
rx_skb
);
kfree_skb
(
h4
->
rx_skb
);
hu
->
priv
=
NULL
;
kfree
(
h4
);
...
...
drivers/bluetooth/hci_ll.c
View file @
63748aa8
...
...
@@ -163,8 +163,7 @@ static int ll_close(struct hci_uart *hu)
skb_queue_purge
(
&
ll
->
tx_wait_q
);
skb_queue_purge
(
&
ll
->
txq
);
if
(
ll
->
rx_skb
)
kfree_skb
(
ll
->
rx_skb
);
kfree_skb
(
ll
->
rx_skb
);
hu
->
priv
=
NULL
;
...
...
include/net/bluetooth/bluetooth.h
View file @
63748aa8
...
...
@@ -53,6 +53,17 @@
#define SOL_SCO 17
#define SOL_RFCOMM 18
#define BT_SECURITY 4
struct
bt_security
{
__u8
level
;
};
#define BT_SECURITY_SDP 0
#define BT_SECURITY_LOW 1
#define BT_SECURITY_MEDIUM 2
#define BT_SECURITY_HIGH 3
#define BT_DEFER_SETUP 7
#define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg)
#define BT_ERR(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg)
#define BT_DBG(fmt, arg...) pr_debug("%s: " fmt "\n" , __func__ , ## arg)
...
...
@@ -108,6 +119,7 @@ struct bt_sock {
bdaddr_t
dst
;
struct
list_head
accept_q
;
struct
sock
*
parent
;
u32
defer_setup
;
};
struct
bt_sock_list
{
...
...
include/net/bluetooth/hci.h
View file @
63748aa8
...
...
@@ -133,8 +133,13 @@ enum {
#define ESCO_EV3 0x0008
#define ESCO_EV4 0x0010
#define ESCO_EV5 0x0020
#define ESCO_2EV3 0x0040
#define ESCO_3EV3 0x0080
#define ESCO_2EV5 0x0100
#define ESCO_3EV5 0x0200
#define SCO_ESCO_MASK (ESCO_HV1 | ESCO_HV2 | ESCO_HV3)
#define EDR_ESCO_MASK (ESCO_2EV3 | ESCO_3EV3 | ESCO_2EV5 | ESCO_3EV5)
/* ACL flags */
#define ACL_CONT 0x01
...
...
@@ -176,6 +181,9 @@ enum {
#define LMP_EV5 0x02
#define LMP_SNIFF_SUBR 0x02
#define LMP_EDR_ESCO_2M 0x20
#define LMP_EDR_ESCO_3M 0x40
#define LMP_EDR_3S_ESCO 0x80
#define LMP_SIMPLE_PAIR 0x08
...
...
include/net/bluetooth/hci_core.h
View file @
63748aa8
...
...
@@ -169,6 +169,7 @@ struct hci_conn {
__u16
link_policy
;
__u32
link_mode
;
__u8
auth_type
;
__u8
sec_level
;
__u8
power_save
;
unsigned
long
pend
;
...
...
@@ -325,12 +326,11 @@ int hci_conn_del(struct hci_conn *conn);
void
hci_conn_hash_flush
(
struct
hci_dev
*
hdev
);
void
hci_conn_check_pending
(
struct
hci_dev
*
hdev
);
struct
hci_conn
*
hci_connect
(
struct
hci_dev
*
hdev
,
int
type
,
bdaddr_t
*
dst
,
__u8
auth_type
);
struct
hci_conn
*
hci_connect
(
struct
hci_dev
*
hdev
,
int
type
,
bdaddr_t
*
dst
,
__u8
sec_level
,
__u8
auth_type
);
int
hci_conn_check_link_mode
(
struct
hci_conn
*
conn
);
int
hci_conn_auth
(
struct
hci_conn
*
conn
);
int
hci_conn_encrypt
(
struct
hci_conn
*
conn
);
int
hci_conn_security
(
struct
hci_conn
*
conn
,
__u8
sec_level
,
__u8
auth_type
);
int
hci_conn_change_link_key
(
struct
hci_conn
*
conn
);
int
hci_conn_switch_role
(
struct
hci_conn
*
conn
,
uint8_t
role
);
int
hci_conn_switch_role
(
struct
hci_conn
*
conn
,
__u8
role
);
void
hci_conn_enter_active_mode
(
struct
hci_conn
*
conn
);
void
hci_conn_enter_sniff_mode
(
struct
hci_conn
*
conn
);
...
...
@@ -470,26 +470,26 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
/* ----- HCI protocols ----- */
struct
hci_proto
{
char
*
name
;
char
*
name
;
unsigned
int
id
;
unsigned
long
flags
;
void
*
priv
;
int
(
*
connect_ind
)
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
__u8
type
);
int
(
*
connect_ind
)
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
__u8
type
);
int
(
*
connect_cfm
)
(
struct
hci_conn
*
conn
,
__u8
status
);
int
(
*
disconn_ind
)
(
struct
hci_conn
*
conn
,
__u8
reason
);
int
(
*
disconn_ind
)
(
struct
hci_conn
*
conn
);
int
(
*
disconn_cfm
)
(
struct
hci_conn
*
conn
,
__u8
reason
);
int
(
*
recv_acldata
)
(
struct
hci_conn
*
conn
,
struct
sk_buff
*
skb
,
__u16
flags
);
int
(
*
recv_scodata
)
(
struct
hci_conn
*
conn
,
struct
sk_buff
*
skb
);
int
(
*
auth_cfm
)
(
struct
hci_conn
*
conn
,
__u8
status
);
int
(
*
encrypt_cfm
)
(
struct
hci_conn
*
conn
,
__u8
status
,
__u8
encrypt
);
int
(
*
security_cfm
)
(
struct
hci_conn
*
conn
,
__u8
status
,
__u8
encrypt
);
};
static
inline
int
hci_proto_connect_ind
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
__u8
type
)
{
register
struct
hci_proto
*
hp
;
int
mask
=
0
;
hp
=
hci_proto
[
HCI_PROTO_L2CAP
];
if
(
hp
&&
hp
->
connect_ind
)
mask
|=
hp
->
connect_ind
(
hdev
,
bdaddr
,
type
);
...
...
@@ -514,30 +514,52 @@ static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status)
hp
->
connect_cfm
(
conn
,
status
);
}
static
inline
void
hci_proto_disconn_ind
(
struct
hci_conn
*
conn
,
__u8
reaso
n
)
static
inline
int
hci_proto_disconn_ind
(
struct
hci_conn
*
con
n
)
{
register
struct
hci_proto
*
hp
;
int
reason
=
0x13
;
hp
=
hci_proto
[
HCI_PROTO_L2CAP
];
if
(
hp
&&
hp
->
disconn_ind
)
hp
->
disconn_ind
(
conn
,
reaso
n
);
reason
=
hp
->
disconn_ind
(
con
n
);
hp
=
hci_proto
[
HCI_PROTO_SCO
];
if
(
hp
&&
hp
->
disconn_ind
)
hp
->
disconn_ind
(
conn
,
reason
);
reason
=
hp
->
disconn_ind
(
conn
);
return
reason
;
}
static
inline
void
hci_proto_disconn_cfm
(
struct
hci_conn
*
conn
,
__u8
reason
)
{
register
struct
hci_proto
*
hp
;
hp
=
hci_proto
[
HCI_PROTO_L2CAP
];
if
(
hp
&&
hp
->
disconn_cfm
)
hp
->
disconn_cfm
(
conn
,
reason
);
hp
=
hci_proto
[
HCI_PROTO_SCO
];
if
(
hp
&&
hp
->
disconn_cfm
)
hp
->
disconn_cfm
(
conn
,
reason
);
}
static
inline
void
hci_proto_auth_cfm
(
struct
hci_conn
*
conn
,
__u8
status
)
{
register
struct
hci_proto
*
hp
;
__u8
encrypt
;
if
(
test_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
conn
->
pend
))
return
;
encrypt
=
(
conn
->
link_mode
&
HCI_LM_ENCRYPT
)
?
0x01
:
0x00
;
hp
=
hci_proto
[
HCI_PROTO_L2CAP
];
if
(
hp
&&
hp
->
auth
_cfm
)
hp
->
auth_cfm
(
conn
,
status
);
if
(
hp
&&
hp
->
security
_cfm
)
hp
->
security_cfm
(
conn
,
status
,
encrypt
);
hp
=
hci_proto
[
HCI_PROTO_SCO
];
if
(
hp
&&
hp
->
auth
_cfm
)
hp
->
auth_cfm
(
conn
,
status
);
if
(
hp
&&
hp
->
security
_cfm
)
hp
->
security_cfm
(
conn
,
status
,
encrypt
);
}
static
inline
void
hci_proto_encrypt_cfm
(
struct
hci_conn
*
conn
,
__u8
status
,
__u8
encrypt
)
...
...
@@ -545,12 +567,12 @@ static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u
register
struct
hci_proto
*
hp
;
hp
=
hci_proto
[
HCI_PROTO_L2CAP
];
if
(
hp
&&
hp
->
encrypt
_cfm
)
hp
->
encrypt
_cfm
(
conn
,
status
,
encrypt
);
if
(
hp
&&
hp
->
security
_cfm
)
hp
->
security
_cfm
(
conn
,
status
,
encrypt
);
hp
=
hci_proto
[
HCI_PROTO_SCO
];
if
(
hp
&&
hp
->
encrypt
_cfm
)
hp
->
encrypt
_cfm
(
conn
,
status
,
encrypt
);
if
(
hp
&&
hp
->
security
_cfm
)
hp
->
security
_cfm
(
conn
,
status
,
encrypt
);
}
int
hci_register_proto
(
struct
hci_proto
*
hproto
);
...
...
@@ -562,8 +584,7 @@ struct hci_cb {
char
*
name
;
void
(
*
auth_cfm
)
(
struct
hci_conn
*
conn
,
__u8
status
);
void
(
*
encrypt_cfm
)
(
struct
hci_conn
*
conn
,
__u8
status
,
__u8
encrypt
);
void
(
*
security_cfm
)
(
struct
hci_conn
*
conn
,
__u8
status
,
__u8
encrypt
);
void
(
*
key_change_cfm
)
(
struct
hci_conn
*
conn
,
__u8
status
);
void
(
*
role_switch_cfm
)
(
struct
hci_conn
*
conn
,
__u8
status
,
__u8
role
);
};
...
...
@@ -571,14 +592,20 @@ struct hci_cb {
static
inline
void
hci_auth_cfm
(
struct
hci_conn
*
conn
,
__u8
status
)
{
struct
list_head
*
p
;
__u8
encrypt
;
hci_proto_auth_cfm
(
conn
,
status
);
if
(
test_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
conn
->
pend
))
return
;
encrypt
=
(
conn
->
link_mode
&
HCI_LM_ENCRYPT
)
?
0x01
:
0x00
;
read_lock_bh
(
&
hci_cb_list_lock
);
list_for_each
(
p
,
&
hci_cb_list
)
{
struct
hci_cb
*
cb
=
list_entry
(
p
,
struct
hci_cb
,
list
);
if
(
cb
->
auth
_cfm
)
cb
->
auth_cfm
(
conn
,
status
);
if
(
cb
->
security
_cfm
)
cb
->
security_cfm
(
conn
,
status
,
encrypt
);
}
read_unlock_bh
(
&
hci_cb_list_lock
);
}
...
...
@@ -587,13 +614,16 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encr
{
struct
list_head
*
p
;
if
(
conn
->
sec_level
==
BT_SECURITY_SDP
)
conn
->
sec_level
=
BT_SECURITY_LOW
;
hci_proto_encrypt_cfm
(
conn
,
status
,
encrypt
);
read_lock_bh
(
&
hci_cb_list_lock
);
list_for_each
(
p
,
&
hci_cb_list
)
{
struct
hci_cb
*
cb
=
list_entry
(
p
,
struct
hci_cb
,
list
);
if
(
cb
->
encrypt
_cfm
)
cb
->
encrypt
_cfm
(
conn
,
status
,
encrypt
);
if
(
cb
->
security
_cfm
)
cb
->
security
_cfm
(
conn
,
status
,
encrypt
);
}
read_unlock_bh
(
&
hci_cb_list_lock
);
}
...
...
include/net/bluetooth/l2cap.h
View file @
63748aa8
...
...
@@ -37,6 +37,7 @@ struct sockaddr_l2 {
sa_family_t
l2_family
;
__le16
l2_psm
;
bdaddr_t
l2_bdaddr
;
__le16
l2_cid
;
};
/* L2CAP socket options */
...
...
@@ -185,6 +186,7 @@ struct l2cap_info_rsp {
/* info type */
#define L2CAP_IT_CL_MTU 0x0001
#define L2CAP_IT_FEAT_MASK 0x0002
#define L2CAP_IT_FIXED_CHAN 0x0003
/* info result */
#define L2CAP_IR_SUCCESS 0x0000
...
...
@@ -219,11 +221,14 @@ struct l2cap_conn {
__u8
rx_ident
;
__u8
tx_ident
;
__u8
disc_reason
;
struct
l2cap_chan_list
chan_list
;
};
#define L2CAP_INFO_CL_MTU_REQ_SENT 0x01
#define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x02
#define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x04
#define L2CAP_INFO_FEAT_MASK_REQ_DONE 0x08
/* ----- L2CAP channel and socket info ----- */
#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
...
...
@@ -237,8 +242,9 @@ struct l2cap_pinfo {
__u16
imtu
;
__u16
omtu
;
__u16
flush_to
;
__u32
link_mode
;
__u8
sec_level
;
__u8
role_switch
;
__u8
force_reliable
;
__u8
conf_req
[
64
];
__u8
conf_len
;
...
...
@@ -257,6 +263,7 @@ struct l2cap_pinfo {
#define L2CAP_CONF_REQ_SENT 0x01
#define L2CAP_CONF_INPUT_DONE 0x02
#define L2CAP_CONF_OUTPUT_DONE 0x04
#define L2CAP_CONF_CONNECT_PEND 0x80
#define L2CAP_CONF_MAX_RETRIES 2
...
...
include/net/bluetooth/rfcomm.h
View file @
63748aa8
...
...
@@ -183,8 +183,9 @@ struct rfcomm_dlc {
u8
remote_v24_sig
;
u8
mscex
;
u8
out
;
u32
link_mode
;
u8
sec_level
;
u8
role_switch
;
u32
defer_setup
;
uint
mtu
;
uint
cfc
;
...
...
@@ -202,10 +203,12 @@ struct rfcomm_dlc {
#define RFCOMM_RX_THROTTLED 0
#define RFCOMM_TX_THROTTLED 1
#define RFCOMM_TIMED_OUT 2
#define RFCOMM_MSC_PENDING 3
#define RFCOMM_AUTH_PENDING 4
#define RFCOMM_AUTH_ACCEPT 5
#define RFCOMM_AUTH_REJECT 6
#define RFCOMM_MSC_PENDING 3
#define RFCOMM_SEC_PENDING 4
#define RFCOMM_AUTH_PENDING 5
#define RFCOMM_AUTH_ACCEPT 6
#define RFCOMM_AUTH_REJECT 7
#define RFCOMM_DEFER_SETUP 8
/* Scheduling flags and events */
#define RFCOMM_SCHED_STATE 0
...
...
@@ -239,6 +242,7 @@ int rfcomm_dlc_close(struct rfcomm_dlc *d, int reason);
int
rfcomm_dlc_send
(
struct
rfcomm_dlc
*
d
,
struct
sk_buff
*
skb
);
int
rfcomm_dlc_set_modem_status
(
struct
rfcomm_dlc
*
d
,
u8
v24_sig
);
int
rfcomm_dlc_get_modem_status
(
struct
rfcomm_dlc
*
d
,
u8
*
v24_sig
);
void
rfcomm_dlc_accept
(
struct
rfcomm_dlc
*
d
);
#define rfcomm_dlc_lock(d) spin_lock(&d->lock)
#define rfcomm_dlc_unlock(d) spin_unlock(&d->lock)
...
...
@@ -304,7 +308,8 @@ struct rfcomm_pinfo {
struct
bt_sock
bt
;
struct
rfcomm_dlc
*
dlc
;
u8
channel
;
u32
link_mode
;
u8
sec_level
;
u8
role_switch
;
};
int
rfcomm_init_sockets
(
void
);
...
...
@@ -333,7 +338,6 @@ struct rfcomm_dev_req {
bdaddr_t
src
;
bdaddr_t
dst
;
u8
channel
;
};
struct
rfcomm_dev_info
{
...
...
net/bluetooth/af_bluetooth.c
View file @
63748aa8
...
...
@@ -41,14 +41,13 @@
#include <net/bluetooth/bluetooth.h>
#define VERSION "2.1
4
"
#define VERSION "2.1
5
"
/* Bluetooth sockets */
#define BT_MAX_PROTO 8
static
struct
net_proto_family
*
bt_proto
[
BT_MAX_PROTO
];
static
DEFINE_RWLOCK
(
bt_proto_lock
);
#ifdef CONFIG_DEBUG_LOCK_ALLOC
static
struct
lock_class_key
bt_lock_key
[
BT_MAX_PROTO
];
static
const
char
*
bt_key_strings
[
BT_MAX_PROTO
]
=
{
"sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP"
,
...
...
@@ -86,11 +85,6 @@ static inline void bt_sock_reclassify_lock(struct socket *sock, int proto)
bt_slock_key_strings
[
proto
],
&
bt_slock_key
[
proto
],
bt_key_strings
[
proto
],
&
bt_lock_key
[
proto
]);
}
#else
static
inline
void
bt_sock_reclassify_lock
(
struct
socket
*
sock
,
int
proto
)
{
}
#endif
int
bt_sock_register
(
int
proto
,
struct
net_proto_family
*
ops
)
{
...
...
@@ -217,7 +211,8 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
continue
;
}
if
(
sk
->
sk_state
==
BT_CONNECTED
||
!
newsock
)
{
if
(
sk
->
sk_state
==
BT_CONNECTED
||
!
newsock
||
bt_sk
(
parent
)
->
defer_setup
)
{
bt_accept_unlink
(
sk
);
if
(
newsock
)
sock_graft
(
sk
,
newsock
);
...
...
@@ -232,7 +227,7 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
EXPORT_SYMBOL
(
bt_accept_dequeue
);
int
bt_sock_recvmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
msg
,
size_t
len
,
int
flags
)
struct
msghdr
*
msg
,
size_t
len
,
int
flags
)
{
int
noblock
=
flags
&
MSG_DONTWAIT
;
struct
sock
*
sk
=
sock
->
sk
;
...
...
@@ -277,7 +272,9 @@ static inline unsigned int bt_accept_poll(struct sock *parent)
list_for_each_safe
(
p
,
n
,
&
bt_sk
(
parent
)
->
accept_q
)
{
sk
=
(
struct
sock
*
)
list_entry
(
p
,
struct
bt_sock
,
accept_q
);
if
(
sk
->
sk_state
==
BT_CONNECTED
)
if
(
sk
->
sk_state
==
BT_CONNECTED
||
(
bt_sk
(
parent
)
->
defer_setup
&&
sk
->
sk_state
==
BT_CONNECT2
))
return
POLLIN
|
POLLRDNORM
;
}
...
...
net/bluetooth/cmtp/core.c
View file @
63748aa8
...
...
@@ -126,8 +126,7 @@ static inline void cmtp_add_msgpart(struct cmtp_session *session, int id, const
session
->
reassembly
[
id
]
=
nskb
;
if
(
skb
)
kfree_skb
(
skb
);
kfree_skb
(
skb
);
}
static
inline
int
cmtp_recv_frame
(
struct
cmtp_session
*
session
,
struct
sk_buff
*
skb
)
...
...
net/bluetooth/hci_conn.c
View file @
63748aa8
...
...
@@ -123,6 +123,8 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle)
conn
->
state
=
BT_CONNECT
;
conn
->
out
=
1
;
conn
->
attempt
++
;
cp
.
handle
=
cpu_to_le16
(
handle
);
cp
.
pkt_type
=
cpu_to_le16
(
conn
->
pkt_type
);
...
...
@@ -139,6 +141,8 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
conn
->
state
=
BT_CONNECT
;
conn
->
out
=
1
;
conn
->
attempt
++
;
cp
.
handle
=
cpu_to_le16
(
handle
);
cp
.
pkt_type
=
cpu_to_le16
(
conn
->
pkt_type
);
...
...
@@ -155,6 +159,7 @@ static void hci_conn_timeout(unsigned long arg)
{
struct
hci_conn
*
conn
=
(
void
*
)
arg
;
struct
hci_dev
*
hdev
=
conn
->
hdev
;
__u8
reason
;
BT_DBG
(
"conn %p state %d"
,
conn
,
conn
->
state
);
...
...
@@ -173,7 +178,8 @@ static void hci_conn_timeout(unsigned long arg)
break
;
case
BT_CONFIG
:
case
BT_CONNECTED
:
hci_acl_disconn
(
conn
,
0x13
);
reason
=
hci_proto_disconn_ind
(
conn
);
hci_acl_disconn
(
conn
,
reason
);
break
;
default:
conn
->
state
=
BT_CLOSED
;
...
...
@@ -216,12 +222,13 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
break
;
case
SCO_LINK
:
if
(
lmp_esco_capable
(
hdev
))
conn
->
pkt_type
=
hdev
->
esco_type
&
SCO_ESCO_MASK
;
conn
->
pkt_type
=
(
hdev
->
esco_type
&
SCO_ESCO_MASK
)
|
(
hdev
->
esco_type
&
EDR_ESCO_MASK
);
else
conn
->
pkt_type
=
hdev
->
pkt_type
&
SCO_PTYPE_MASK
;
break
;
case
ESCO_LINK
:
conn
->
pkt_type
=
hdev
->
esco_type
;
conn
->
pkt_type
=
hdev
->
esco_type
&
~
EDR_ESCO_MASK
;
break
;
}
...
...
@@ -280,6 +287,8 @@ int hci_conn_del(struct hci_conn *conn)
skb_queue_purge
(
&
conn
->
data_q
);
hci_conn_del_sysfs
(
conn
);
return
0
;
}
...
...
@@ -325,7 +334,7 @@ EXPORT_SYMBOL(hci_get_route);
/* Create SCO or ACL connection.
* Device _must_ be locked */
struct
hci_conn
*
hci_connect
(
struct
hci_dev
*
hdev
,
int
type
,
bdaddr_t
*
dst
,
__u8
auth_type
)
struct
hci_conn
*
hci_connect
(
struct
hci_dev
*
hdev
,
int
type
,
bdaddr_t
*
dst
,
__u8
sec_level
,
__u8
auth_type
)
{
struct
hci_conn
*
acl
;
struct
hci_conn
*
sco
;
...
...
@@ -340,6 +349,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
hci_conn_hold
(
acl
);
if
(
acl
->
state
==
BT_OPEN
||
acl
->
state
==
BT_CLOSED
)
{
acl
->
sec_level
=
sec_level
;
acl
->
auth_type
=
auth_type
;
hci_acl_connect
(
acl
);
}
...
...
@@ -385,51 +395,59 @@ int hci_conn_check_link_mode(struct hci_conn *conn)
EXPORT_SYMBOL
(
hci_conn_check_link_mode
);
/* Authenticate remote device */
int
hci_conn_auth
(
struct
hci_conn
*
conn
)
static
int
hci_conn_auth
(
struct
hci_conn
*
conn
,
__u8
sec_level
,
__u8
auth_type
)
{
BT_DBG
(
"conn %p"
,
conn
);
if
(
conn
->
ssp_mode
>
0
&&
conn
->
hdev
->
ssp_mode
>
0
)
{
if
(
!
(
conn
->
auth_type
&
0x01
))
{
conn
->
auth_type
|=
0x01
;
conn
->
link_mode
&=
~
HCI_LM_AUTH
;
}
}
if
(
conn
->
link_mode
&
HCI_LM_AUTH
)
if
(
sec_level
>
conn
->
sec_level
)
conn
->
sec_level
=
sec_level
;
else
if
(
conn
->
link_mode
&
HCI_LM_AUTH
)
return
1
;
conn
->
auth_type
=
auth_type
;
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
(
conn
->
hdev
,
HCI_OP_AUTH_REQUESTED
,
sizeof
(
cp
),
&
cp
);
}
return
0
;
}
EXPORT_SYMBOL
(
hci_conn_auth
);
/* Enable
encryption
*/
int
hci_conn_
encrypt
(
struct
hci_conn
*
conn
)
/* Enable
security
*/
int
hci_conn_
security
(
struct
hci_conn
*
conn
,
__u8
sec_level
,
__u8
auth_type
)
{
BT_DBG
(
"conn %p"
,
conn
);
if
(
sec_level
==
BT_SECURITY_SDP
)
return
1
;
if
(
sec_level
==
BT_SECURITY_LOW
)
{
if
(
conn
->
ssp_mode
>
0
&&
conn
->
hdev
->
ssp_mode
>
0
)
return
hci_conn_auth
(
conn
,
sec_level
,
auth_type
);
else
return
1
;
}
if
(
conn
->
link_mode
&
HCI_LM_ENCRYPT
)
return
hci_conn_auth
(
conn
);
return
hci_conn_auth
(
conn
,
sec_level
,
auth_type
);
if
(
test_and_set_bit
(
HCI_CONN_ENCRYPT_PEND
,
&
conn
->
pend
))
return
0
;
if
(
hci_conn_auth
(
conn
))
{
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
);
}
return
0
;
}
EXPORT_SYMBOL
(
hci_conn_
encrypt
);
EXPORT_SYMBOL
(
hci_conn_
security
);
/* Change link key */
int
hci_conn_change_link_key
(
struct
hci_conn
*
conn
)
...
...
@@ -442,12 +460,13 @@ int hci_conn_change_link_key(struct hci_conn *conn)
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_CHANGE_CONN_LINK_KEY
,
sizeof
(
cp
),
&
cp
);
}
return
0
;
}
EXPORT_SYMBOL
(
hci_conn_change_link_key
);
/* Switch role */
int
hci_conn_switch_role
(
struct
hci_conn
*
conn
,
uint8_t
role
)
int
hci_conn_switch_role
(
struct
hci_conn
*
conn
,
__u8
role
)
{
BT_DBG
(
"conn %p"
,
conn
);
...
...
@@ -460,6 +479,7 @@ int hci_conn_switch_role(struct hci_conn *conn, uint8_t role)
cp
.
role
=
role
;
hci_send_cmd
(
conn
->
hdev
,
HCI_OP_SWITCH_ROLE
,
sizeof
(
cp
),
&
cp
);
}
return
0
;
}
EXPORT_SYMBOL
(
hci_conn_switch_role
);
...
...
@@ -542,9 +562,7 @@ void hci_conn_hash_flush(struct hci_dev *hdev)
c
->
state
=
BT_CLOSED
;
hci_conn_del_sysfs
(
c
);
hci_proto_disconn_ind
(
c
,
0x16
);
hci_proto_disconn_cfm
(
c
,
0x16
);
hci_conn_del
(
c
);
}
}
...
...
net/bluetooth/hci_core.c
View file @
63748aa8
...
...
@@ -1565,8 +1565,7 @@ static void hci_cmd_task(unsigned long arg)
/* Send queued commands */
if
(
atomic_read
(
&
hdev
->
cmd_cnt
)
&&
(
skb
=
skb_dequeue
(
&
hdev
->
cmd_q
)))
{
if
(
hdev
->
sent_cmd
)
kfree_skb
(
hdev
->
sent_cmd
);
kfree_skb
(
hdev
->
sent_cmd
);
if
((
hdev
->
sent_cmd
=
skb_clone
(
skb
,
GFP_ATOMIC
)))
{
atomic_dec
(
&
hdev
->
cmd_cnt
);
...
...
net/bluetooth/hci_event.c
View file @
63748aa8
...
...
@@ -484,6 +484,15 @@ static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb
if
(
hdev
->
features
[
4
]
&
LMP_EV5
)
hdev
->
esco_type
|=
(
ESCO_EV5
);
if
(
hdev
->
features
[
5
]
&
LMP_EDR_ESCO_2M
)
hdev
->
esco_type
|=
(
ESCO_2EV3
);
if
(
hdev
->
features
[
5
]
&
LMP_EDR_ESCO_3M
)
hdev
->
esco_type
|=
(
ESCO_3EV3
);
if
(
hdev
->
features
[
5
]
&
LMP_EDR_3S_ESCO
)
hdev
->
esco_type
|=
(
ESCO_2EV5
|
ESCO_3EV5
);
BT_DBG
(
"%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x"
,
hdev
->
name
,
hdev
->
features
[
0
],
hdev
->
features
[
1
],
hdev
->
features
[
2
],
hdev
->
features
[
3
],
...
...
@@ -914,7 +923,8 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
if
(
ev
->
status
)
{
hci_proto_connect_cfm
(
conn
,
ev
->
status
);
hci_conn_del
(
conn
);
}
}
else
if
(
ev
->
link_type
!=
ACL_LINK
)
hci_proto_connect_cfm
(
conn
,
ev
->
status
);
unlock:
hci_dev_unlock
(
hdev
);
...
...
@@ -1009,9 +1019,7 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff
if
(
conn
)
{
conn
->
state
=
BT_CLOSED
;
hci_conn_del_sysfs
(
conn
);
hci_proto_disconn_ind
(
conn
,
ev
->
reason
);
hci_proto_disconn_cfm
(
conn
,
ev
->
reason
);
hci_conn_del
(
conn
);
}
...
...
@@ -1600,7 +1608,8 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
if
(
conn
->
state
==
BT_CONFIG
)
{
if
(
!
ev
->
status
&&
hdev
->
ssp_mode
>
0
&&
conn
->
ssp_mode
>
0
&&
conn
->
out
)
{
conn
->
ssp_mode
>
0
&&
conn
->
out
&&
conn
->
sec_level
!=
BT_SECURITY_SDP
)
{
struct
hci_cp_auth_requested
cp
;
cp
.
handle
=
ev
->
handle
;
hci_send_cmd
(
hdev
,
HCI_OP_AUTH_REQUESTED
,
...
...
@@ -1637,6 +1646,13 @@ static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_bu
conn
->
type
=
SCO_LINK
;
}
if
(
conn
->
out
&&
ev
->
status
==
0x1c
&&
conn
->
attempt
<
2
)
{
conn
->
pkt_type
=
(
hdev
->
esco_type
&
SCO_ESCO_MASK
)
|
(
hdev
->
esco_type
&
EDR_ESCO_MASK
);
hci_setup_sync
(
conn
,
conn
->
link
->
handle
);
goto
unlock
;
}
if
(
!
ev
->
status
)
{
conn
->
handle
=
__le16_to_cpu
(
ev
->
handle
);
conn
->
state
=
BT_CONNECTED
;
...
...
net/bluetooth/l2cap.c
View file @
63748aa8
...
...
@@ -50,9 +50,10 @@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
#define VERSION "2.1
1
"
#define VERSION "2.1
3
"
static
u32
l2cap_feat_mask
=
0x0000
;
static
u32
l2cap_feat_mask
=
0x0080
;
static
u8
l2cap_fixed_chan
[
8
]
=
{
0x02
,
};
static
const
struct
proto_ops
l2cap_sock_ops
;
...
...
@@ -77,9 +78,10 @@ static void l2cap_sock_timeout(unsigned long arg)
bh_lock_sock
(
sk
);
if
(
sk
->
sk_state
==
BT_CONNECT
&&
(
l2cap_pi
(
sk
)
->
link_mode
&
(
L2CAP_LM_AUTH
|
L2CAP_LM_ENCRYPT
|
L2CAP_LM_SECURE
)))
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
)
reason
=
ECONNREFUSED
;
else
reason
=
ETIMEDOUT
;
...
...
@@ -204,6 +206,8 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct so
BT_DBG
(
"conn %p, psm 0x%2.2x, dcid 0x%4.4x"
,
conn
,
l2cap_pi
(
sk
)
->
psm
,
l2cap_pi
(
sk
)
->
dcid
);
conn
->
disc_reason
=
0x13
;
l2cap_pi
(
sk
)
->
conn
=
conn
;
if
(
sk
->
sk_type
==
SOCK_SEQPACKET
)
{
...
...
@@ -259,18 +263,35 @@ static void l2cap_chan_del(struct sock *sk, int err)
}
/* Service level security */
static
inline
int
l2cap_check_
link_mode
(
struct
sock
*
sk
)
static
inline
int
l2cap_check_
security
(
struct
sock
*
sk
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
__u8
auth_type
;
if
((
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_ENCRYPT
)
||
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_SECURE
))
return
hci_conn_encrypt
(
conn
->
hcon
);
if
(
l2cap_pi
(
sk
)
->
psm
==
cpu_to_le16
(
0x0001
))
{
if
(
l2cap_pi
(
sk
)
->
sec_level
==
BT_SECURITY_HIGH
)
auth_type
=
HCI_AT_NO_BONDING_MITM
;
else
auth_type
=
HCI_AT_NO_BONDING
;
if
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_AUTH
)
return
hci_conn_auth
(
conn
->
hcon
);
if
(
l2cap_pi
(
sk
)
->
sec_level
==
BT_SECURITY_LOW
)
l2cap_pi
(
sk
)
->
sec_level
=
BT_SECURITY_SDP
;
}
else
{
switch
(
l2cap_pi
(
sk
)
->
sec_level
)
{
case
BT_SECURITY_HIGH
:
auth_type
=
HCI_AT_GENERAL_BONDING_MITM
;
break
;
case
BT_SECURITY_MEDIUM
:
auth_type
=
HCI_AT_GENERAL_BONDING
;
break
;
default:
auth_type
=
HCI_AT_NO_BONDING
;
break
;
}
}
return
1
;
return
hci_conn_security
(
conn
->
hcon
,
l2cap_pi
(
sk
)
->
sec_level
,
auth_type
);
}
static
inline
u8
l2cap_get_ident
(
struct
l2cap_conn
*
conn
)
...
...
@@ -312,7 +333,10 @@ static void l2cap_do_start(struct sock *sk)
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
if
(
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_SENT
)
{
if
(
l2cap_check_link_mode
(
sk
))
{
if
(
!
(
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_DONE
))
return
;
if
(
l2cap_check_security
(
sk
))
{
struct
l2cap_conn_req
req
;
req
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
req
.
psm
=
l2cap_pi
(
sk
)
->
psm
;
...
...
@@ -356,7 +380,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
}
if
(
sk
->
sk_state
==
BT_CONNECT
)
{
if
(
l2cap_check_
link_mode
(
sk
))
{
if
(
l2cap_check_
security
(
sk
))
{
struct
l2cap_conn_req
req
;
req
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
req
.
psm
=
l2cap_pi
(
sk
)
->
psm
;
...
...
@@ -371,10 +395,18 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
rsp
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
dcid
);
rsp
.
dcid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
if
(
l2cap_check_link_mode
(
sk
))
{
sk
->
sk_state
=
BT_CONFIG
;
rsp
.
result
=
cpu_to_le16
(
L2CAP_CR_SUCCESS
);
rsp
.
status
=
cpu_to_le16
(
L2CAP_CS_NO_INFO
);
if
(
l2cap_check_security
(
sk
))
{
if
(
bt_sk
(
sk
)
->
defer_setup
)
{
struct
sock
*
parent
=
bt_sk
(
sk
)
->
parent
;
rsp
.
result
=
cpu_to_le16
(
L2CAP_CR_PEND
);
rsp
.
status
=
cpu_to_le16
(
L2CAP_CS_AUTHOR_PEND
);
parent
->
sk_data_ready
(
parent
,
0
);
}
else
{
sk
->
sk_state
=
BT_CONFIG
;
rsp
.
result
=
cpu_to_le16
(
L2CAP_CR_SUCCESS
);
rsp
.
status
=
cpu_to_le16
(
L2CAP_CS_NO_INFO
);
}
}
else
{
rsp
.
result
=
cpu_to_le16
(
L2CAP_CR_PEND
);
rsp
.
status
=
cpu_to_le16
(
L2CAP_CS_AUTHEN_PEND
);
...
...
@@ -426,7 +458,7 @@ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
read_lock
(
&
l
->
lock
);
for
(
sk
=
l
->
head
;
sk
;
sk
=
l2cap_pi
(
sk
)
->
next_c
)
{
if
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_RELIABLE
)
if
(
l2cap_pi
(
sk
)
->
force_reliable
)
sk
->
sk_err
=
err
;
}
...
...
@@ -437,6 +469,7 @@ static void l2cap_info_timeout(unsigned long arg)
{
struct
l2cap_conn
*
conn
=
(
void
*
)
arg
;
conn
->
info_state
|=
L2CAP_INFO_FEAT_MASK_REQ_DONE
;
conn
->
info_ident
=
0
;
l2cap_conn_start
(
conn
);
...
...
@@ -470,6 +503,8 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
spin_lock_init
(
&
conn
->
lock
);
rwlock_init
(
&
conn
->
chan_list
.
lock
);
conn
->
disc_reason
=
0x13
;
return
conn
;
}
...
...
@@ -483,8 +518,7 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
BT_DBG
(
"hcon %p conn %p, err %d"
,
hcon
,
conn
,
err
);
if
(
conn
->
rx_skb
)
kfree_skb
(
conn
->
rx_skb
);
kfree_skb
(
conn
->
rx_skb
);
/* Kill channels */
while
((
sk
=
conn
->
chan_list
.
head
))
{
...
...
@@ -608,7 +642,6 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
case
BT_CONNECTED
:
case
BT_CONFIG
:
case
BT_CONNECT2
:
if
(
sk
->
sk_type
==
SOCK_SEQPACKET
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
struct
l2cap_disconn_req
req
;
...
...
@@ -624,6 +657,27 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
l2cap_chan_del
(
sk
,
reason
);
break
;
case
BT_CONNECT2
:
if
(
sk
->
sk_type
==
SOCK_SEQPACKET
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
struct
l2cap_conn_rsp
rsp
;
__u16
result
;
if
(
bt_sk
(
sk
)
->
defer_setup
)
result
=
L2CAP_CR_SEC_BLOCK
;
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
.
result
=
cpu_to_le16
(
result
);
rsp
.
status
=
cpu_to_le16
(
L2CAP_CS_NO_INFO
);
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_RSP
,
sizeof
(
rsp
),
&
rsp
);
}
else
l2cap_chan_del
(
sk
,
reason
);
break
;
case
BT_CONNECT
:
case
BT_DISCONN
:
l2cap_chan_del
(
sk
,
reason
);
...
...
@@ -653,13 +707,19 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
if
(
parent
)
{
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
->
link_mode
=
l2cap_pi
(
parent
)
->
link_mode
;
pi
->
sec_level
=
l2cap_pi
(
parent
)
->
sec_level
;
pi
->
role_switch
=
l2cap_pi
(
parent
)
->
role_switch
;
pi
->
force_reliable
=
l2cap_pi
(
parent
)
->
force_reliable
;
}
else
{
pi
->
imtu
=
L2CAP_DEFAULT_MTU
;
pi
->
omtu
=
0
;
pi
->
link_mode
=
0
;
pi
->
sec_level
=
BT_SECURITY_LOW
;
pi
->
role_switch
=
0
;
pi
->
force_reliable
=
0
;
}
/* Default config options */
...
...
@@ -723,17 +783,24 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol)
return
0
;
}
static
int
l2cap_sock_bind
(
struct
socket
*
sock
,
struct
sockaddr
*
addr
,
int
a
ddr_
len
)
static
int
l2cap_sock_bind
(
struct
socket
*
sock
,
struct
sockaddr
*
addr
,
int
alen
)
{
struct
sockaddr_l2
*
la
=
(
struct
sockaddr_l2
*
)
addr
;
struct
sock
*
sk
=
sock
->
sk
;
int
err
=
0
;
struct
sockaddr_l2
la
;
int
len
,
err
=
0
;
BT_DBG
(
"sk %p
, %s %d"
,
sk
,
batostr
(
&
la
->
l2_bdaddr
),
la
->
l2_psm
);
BT_DBG
(
"sk %p
"
,
sk
);
if
(
!
addr
||
addr
->
sa_family
!=
AF_BLUETOOTH
)
return
-
EINVAL
;
memset
(
&
la
,
0
,
sizeof
(
la
));
len
=
min_t
(
unsigned
int
,
sizeof
(
la
),
alen
);
memcpy
(
&
la
,
addr
,
len
);
if
(
la
.
l2_cid
)
return
-
EINVAL
;
lock_sock
(
sk
);
if
(
sk
->
sk_state
!=
BT_OPEN
)
{
...
...
@@ -741,7 +808,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_
goto
done
;
}
if
(
la
->
l2_psm
&&
btohs
(
la
->
l2_psm
)
<
0x1001
&&
if
(
la
.
l2_psm
&&
btohs
(
la
.
l2_psm
)
<
0x1001
&&
!
capable
(
CAP_NET_BIND_SERVICE
))
{
err
=
-
EACCES
;
goto
done
;
...
...
@@ -749,14 +816,17 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_
write_lock_bh
(
&
l2cap_sk_list
.
lock
);
if
(
la
->
l2_psm
&&
__l2cap_get_sock_by_addr
(
la
->
l2_psm
,
&
la
->
l2_bdaddr
))
{
if
(
la
.
l2_psm
&&
__l2cap_get_sock_by_addr
(
la
.
l2_psm
,
&
la
.
l2_bdaddr
))
{
err
=
-
EADDRINUSE
;
}
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
;
bacpy
(
&
bt_sk
(
sk
)
->
src
,
&
la
.
l2_bdaddr
);
l2cap_pi
(
sk
)
->
psm
=
la
.
l2_psm
;
l2cap_pi
(
sk
)
->
sport
=
la
.
l2_psm
;
sk
->
sk_state
=
BT_BOUND
;
if
(
btohs
(
la
.
l2_psm
)
==
0x0001
||
btohs
(
la
.
l2_psm
)
==
0x0003
)
l2cap_pi
(
sk
)
->
sec_level
=
BT_SECURITY_SDP
;
}
write_unlock_bh
(
&
l2cap_sk_list
.
lock
);
...
...
@@ -776,7 +846,8 @@ static int l2cap_do_connect(struct sock *sk)
__u8
auth_type
;
int
err
=
0
;
BT_DBG
(
"%s -> %s psm 0x%2.2x"
,
batostr
(
src
),
batostr
(
dst
),
l2cap_pi
(
sk
)
->
psm
);
BT_DBG
(
"%s -> %s psm 0x%2.2x"
,
batostr
(
src
),
batostr
(
dst
),
l2cap_pi
(
sk
)
->
psm
);
if
(
!
(
hdev
=
hci_get_route
(
dst
,
src
)))
return
-
EHOSTUNREACH
;
...
...
@@ -785,21 +856,42 @@ static int l2cap_do_connect(struct sock *sk)
err
=
-
ENOMEM
;
if
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_AUTH
||
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_ENCRYPT
||
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_SECURE
)
{
if
(
l2cap_pi
(
sk
)
->
psm
==
cpu_to_le16
(
0x0001
))
if
(
sk
->
sk_type
==
SOCK_RAW
)
{
switch
(
l2cap_pi
(
sk
)
->
sec_level
)
{
case
BT_SECURITY_HIGH
:
auth_type
=
HCI_AT_DEDICATED_BONDING_MITM
;
break
;
case
BT_SECURITY_MEDIUM
:
auth_type
=
HCI_AT_DEDICATED_BONDING
;
break
;
default:
auth_type
=
HCI_AT_NO_BONDING
;
break
;
}
}
else
if
(
l2cap_pi
(
sk
)
->
psm
==
cpu_to_le16
(
0x0001
))
{
if
(
l2cap_pi
(
sk
)
->
sec_level
==
BT_SECURITY_HIGH
)
auth_type
=
HCI_AT_NO_BONDING_MITM
;
else
auth_type
=
HCI_AT_GENERAL_BONDING_MITM
;
}
else
{
if
(
l2cap_pi
(
sk
)
->
psm
==
cpu_to_le16
(
0x0001
))
auth_type
=
HCI_AT_NO_BONDING
;
else
if
(
l2cap_pi
(
sk
)
->
sec_level
==
BT_SECURITY_LOW
)
l2cap_pi
(
sk
)
->
sec_level
=
BT_SECURITY_SDP
;
}
else
{
switch
(
l2cap_pi
(
sk
)
->
sec_level
)
{
case
BT_SECURITY_HIGH
:
auth_type
=
HCI_AT_GENERAL_BONDING_MITM
;
break
;
case
BT_SECURITY_MEDIUM
:
auth_type
=
HCI_AT_GENERAL_BONDING
;
break
;
default:
auth_type
=
HCI_AT_NO_BONDING
;
break
;
}
}
hcon
=
hci_connect
(
hdev
,
ACL_LINK
,
dst
,
auth_type
);
hcon
=
hci_connect
(
hdev
,
ACL_LINK
,
dst
,
l2cap_pi
(
sk
)
->
sec_level
,
auth_type
);
if
(
!
hcon
)
goto
done
;
...
...
@@ -835,20 +927,25 @@ static int l2cap_do_connect(struct sock *sk)
static
int
l2cap_sock_connect
(
struct
socket
*
sock
,
struct
sockaddr
*
addr
,
int
alen
,
int
flags
)
{
struct
sockaddr_l2
*
la
=
(
struct
sockaddr_l2
*
)
addr
;
struct
sock
*
sk
=
sock
->
sk
;
int
err
=
0
;
lock_sock
(
sk
);
struct
sockaddr_l2
la
;
int
len
,
err
=
0
;
BT_DBG
(
"sk %p"
,
sk
);
if
(
addr
->
sa_family
!=
AF_BLUETOOTH
||
alen
<
sizeof
(
struct
sockaddr_l2
))
{
err
=
-
EINVAL
;
goto
done
;
}
if
(
!
addr
||
addr
->
sa_family
!=
AF_BLUETOOTH
)
return
-
EINVAL
;
memset
(
&
la
,
0
,
sizeof
(
la
));
len
=
min_t
(
unsigned
int
,
sizeof
(
la
),
alen
);
memcpy
(
&
la
,
addr
,
len
);
if
(
la
.
l2_cid
)
return
-
EINVAL
;
lock_sock
(
sk
);
if
(
sk
->
sk_type
==
SOCK_SEQPACKET
&&
!
la
->
l2_psm
)
{
if
(
sk
->
sk_type
==
SOCK_SEQPACKET
&&
!
la
.
l2_psm
)
{
err
=
-
EINVAL
;
goto
done
;
}
...
...
@@ -875,8 +972,8 @@ 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
;
bacpy
(
&
bt_sk
(
sk
)
->
dst
,
&
la
.
l2_bdaddr
);
l2cap_pi
(
sk
)
->
psm
=
la
.
l2_psm
;
if
((
err
=
l2cap_do_connect
(
sk
)))
goto
done
;
...
...
@@ -1000,12 +1097,16 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
addr
->
sa_family
=
AF_BLUETOOTH
;
*
len
=
sizeof
(
struct
sockaddr_l2
);
if
(
peer
)
if
(
peer
)
{
la
->
l2_psm
=
l2cap_pi
(
sk
)
->
psm
;
bacpy
(
&
la
->
l2_bdaddr
,
&
bt_sk
(
sk
)
->
dst
);
else
la
->
l2_cid
=
htobs
(
l2cap_pi
(
sk
)
->
dcid
);
}
else
{
la
->
l2_psm
=
l2cap_pi
(
sk
)
->
sport
;
bacpy
(
&
la
->
l2_bdaddr
,
&
bt_sk
(
sk
)
->
src
);
la
->
l2_cid
=
htobs
(
l2cap_pi
(
sk
)
->
scid
);
}
la
->
l2_psm
=
l2cap_pi
(
sk
)
->
psm
;
return
0
;
}
...
...
@@ -1106,11 +1207,38 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
return
err
;
}
static
int
l2cap_sock_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
__user
*
optval
,
int
optlen
)
static
int
l2cap_sock_recvmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
msg
,
size_t
len
,
int
flags
)
{
struct
sock
*
sk
=
sock
->
sk
;
lock_sock
(
sk
);
if
(
sk
->
sk_state
==
BT_CONNECT2
&&
bt_sk
(
sk
)
->
defer_setup
)
{
struct
l2cap_conn_rsp
rsp
;
sk
->
sk_state
=
BT_CONFIG
;
rsp
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
dcid
);
rsp
.
dcid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
rsp
.
result
=
cpu_to_le16
(
L2CAP_CR_SUCCESS
);
rsp
.
status
=
cpu_to_le16
(
L2CAP_CS_NO_INFO
);
l2cap_send_cmd
(
l2cap_pi
(
sk
)
->
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_RSP
,
sizeof
(
rsp
),
&
rsp
);
release_sock
(
sk
);
return
0
;
}
release_sock
(
sk
);
return
bt_sock_recvmsg
(
iocb
,
sock
,
msg
,
len
,
flags
);
}
static
int
l2cap_sock_setsockopt_old
(
struct
socket
*
sock
,
int
optname
,
char
__user
*
optval
,
int
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
l2cap_options
opts
;
int
err
=
0
,
len
;
int
len
,
err
=
0
;
u32
opt
;
BT_DBG
(
"sk %p"
,
sk
);
...
...
@@ -1140,7 +1268,15 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
break
;
}
l2cap_pi
(
sk
)
->
link_mode
=
opt
;
if
(
opt
&
L2CAP_LM_AUTH
)
l2cap_pi
(
sk
)
->
sec_level
=
BT_SECURITY_LOW
;
if
(
opt
&
L2CAP_LM_ENCRYPT
)
l2cap_pi
(
sk
)
->
sec_level
=
BT_SECURITY_MEDIUM
;
if
(
opt
&
L2CAP_LM_SECURE
)
l2cap_pi
(
sk
)
->
sec_level
=
BT_SECURITY_HIGH
;
l2cap_pi
(
sk
)
->
role_switch
=
(
opt
&
L2CAP_LM_MASTER
);
l2cap_pi
(
sk
)
->
force_reliable
=
(
opt
&
L2CAP_LM_RELIABLE
);
break
;
default:
...
...
@@ -1152,12 +1288,77 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
return
err
;
}
static
int
l2cap_sock_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
__user
*
optval
,
int
__user
*
optlen
)
static
int
l2cap_sock_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
__user
*
optval
,
int
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
bt_security
sec
;
int
len
,
err
=
0
;
u32
opt
;
BT_DBG
(
"sk %p"
,
sk
);
if
(
level
==
SOL_L2CAP
)
return
l2cap_sock_setsockopt_old
(
sock
,
optname
,
optval
,
optlen
);
if
(
level
!=
SOL_BLUETOOTH
)
return
-
ENOPROTOOPT
;
lock_sock
(
sk
);
switch
(
optname
)
{
case
BT_SECURITY
:
if
(
sk
->
sk_type
!=
SOCK_SEQPACKET
&&
sk
->
sk_type
!=
SOCK_RAW
)
{
err
=
-
EINVAL
;
break
;
}
sec
.
level
=
BT_SECURITY_LOW
;
len
=
min_t
(
unsigned
int
,
sizeof
(
sec
),
optlen
);
if
(
copy_from_user
((
char
*
)
&
sec
,
optval
,
len
))
{
err
=
-
EFAULT
;
break
;
}
if
(
sec
.
level
<
BT_SECURITY_LOW
||
sec
.
level
>
BT_SECURITY_HIGH
)
{
err
=
-
EINVAL
;
break
;
}
l2cap_pi
(
sk
)
->
sec_level
=
sec
.
level
;
break
;
case
BT_DEFER_SETUP
:
if
(
sk
->
sk_state
!=
BT_BOUND
&&
sk
->
sk_state
!=
BT_LISTEN
)
{
err
=
-
EINVAL
;
break
;
}
if
(
get_user
(
opt
,
(
u32
__user
*
)
optval
))
{
err
=
-
EFAULT
;
break
;
}
bt_sk
(
sk
)
->
defer_setup
=
opt
;
break
;
default:
err
=
-
ENOPROTOOPT
;
break
;
}
release_sock
(
sk
);
return
err
;
}
static
int
l2cap_sock_getsockopt_old
(
struct
socket
*
sock
,
int
optname
,
char
__user
*
optval
,
int
__user
*
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
l2cap_options
opts
;
struct
l2cap_conninfo
cinfo
;
int
len
,
err
=
0
;
u32
opt
;
BT_DBG
(
"sk %p"
,
sk
);
...
...
@@ -1180,12 +1381,36 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
break
;
case
L2CAP_LM
:
if
(
put_user
(
l2cap_pi
(
sk
)
->
link_mode
,
(
u32
__user
*
)
optval
))
switch
(
l2cap_pi
(
sk
)
->
sec_level
)
{
case
BT_SECURITY_LOW
:
opt
=
L2CAP_LM_AUTH
;
break
;
case
BT_SECURITY_MEDIUM
:
opt
=
L2CAP_LM_AUTH
|
L2CAP_LM_ENCRYPT
;
break
;
case
BT_SECURITY_HIGH
:
opt
=
L2CAP_LM_AUTH
|
L2CAP_LM_ENCRYPT
|
L2CAP_LM_SECURE
;
break
;
default:
opt
=
0
;
break
;
}
if
(
l2cap_pi
(
sk
)
->
role_switch
)
opt
|=
L2CAP_LM_MASTER
;
if
(
l2cap_pi
(
sk
)
->
force_reliable
)
opt
|=
L2CAP_LM_RELIABLE
;
if
(
put_user
(
opt
,
(
u32
__user
*
)
optval
))
err
=
-
EFAULT
;
break
;
case
L2CAP_CONNINFO
:
if
(
sk
->
sk_state
!=
BT_CONNECTED
)
{
if
(
sk
->
sk_state
!=
BT_CONNECTED
&&
!
(
sk
->
sk_state
==
BT_CONNECT2
&&
bt_sk
(
sk
)
->
defer_setup
))
{
err
=
-
ENOTCONN
;
break
;
}
...
...
@@ -1208,6 +1433,60 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
return
err
;
}
static
int
l2cap_sock_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
__user
*
optval
,
int
__user
*
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
bt_security
sec
;
int
len
,
err
=
0
;
BT_DBG
(
"sk %p"
,
sk
);
if
(
level
==
SOL_L2CAP
)
return
l2cap_sock_getsockopt_old
(
sock
,
optname
,
optval
,
optlen
);
if
(
level
!=
SOL_BLUETOOTH
)
return
-
ENOPROTOOPT
;
if
(
get_user
(
len
,
optlen
))
return
-
EFAULT
;
lock_sock
(
sk
);
switch
(
optname
)
{
case
BT_SECURITY
:
if
(
sk
->
sk_type
!=
SOCK_SEQPACKET
&&
sk
->
sk_type
!=
SOCK_RAW
)
{
err
=
-
EINVAL
;
break
;
}
sec
.
level
=
l2cap_pi
(
sk
)
->
sec_level
;
len
=
min_t
(
unsigned
int
,
len
,
sizeof
(
sec
));
if
(
copy_to_user
(
optval
,
(
char
*
)
&
sec
,
len
))
err
=
-
EFAULT
;
break
;
case
BT_DEFER_SETUP
:
if
(
sk
->
sk_state
!=
BT_BOUND
&&
sk
->
sk_state
!=
BT_LISTEN
)
{
err
=
-
EINVAL
;
break
;
}
if
(
put_user
(
bt_sk
(
sk
)
->
defer_setup
,
(
u32
__user
*
)
optval
))
err
=
-
EFAULT
;
break
;
default:
err
=
-
ENOPROTOOPT
;
break
;
}
release_sock
(
sk
);
return
err
;
}
static
int
l2cap_sock_shutdown
(
struct
socket
*
sock
,
int
how
)
{
struct
sock
*
sk
=
sock
->
sk
;
...
...
@@ -1270,11 +1549,6 @@ static void l2cap_chan_ready(struct sock *sk)
*/
parent
->
sk_data_ready
(
parent
,
0
);
}
if
(
l2cap_pi
(
sk
)
->
link_mode
&
L2CAP_LM_SECURE
)
{
struct
l2cap_conn
*
conn
=
l2cap_pi
(
sk
)
->
conn
;
hci_conn_change_link_key
(
conn
->
hcon
);
}
}
/* Copy frame to all raw sockets on that connection */
...
...
@@ -1549,8 +1823,11 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd
if
((
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_SENT
)
&&
cmd
->
ident
==
conn
->
info_ident
)
{
conn
->
info_ident
=
0
;
del_timer
(
&
conn
->
info_timer
);
conn
->
info_state
|=
L2CAP_INFO_FEAT_MASK_REQ_DONE
;
conn
->
info_ident
=
0
;
l2cap_conn_start
(
conn
);
}
...
...
@@ -1580,6 +1857,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
/* Check if the ACL is secure enough (if not SDP) */
if
(
psm
!=
cpu_to_le16
(
0x0001
)
&&
!
hci_conn_check_link_mode
(
conn
->
hcon
))
{
conn
->
disc_reason
=
0x05
;
result
=
L2CAP_CR_SEC_BLOCK
;
goto
response
;
}
...
...
@@ -1621,11 +1899,18 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
l2cap_pi
(
sk
)
->
ident
=
cmd
->
ident
;
if
(
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_SENT
)
{
if
(
l2cap_check_link_mode
(
sk
))
{
sk
->
sk_state
=
BT_CONFIG
;
result
=
L2CAP_CR_SUCCESS
;
status
=
L2CAP_CS_NO_INFO
;
if
(
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_DONE
)
{
if
(
l2cap_check_security
(
sk
))
{
if
(
bt_sk
(
sk
)
->
defer_setup
)
{
sk
->
sk_state
=
BT_CONNECT2
;
result
=
L2CAP_CR_PEND
;
status
=
L2CAP_CS_AUTHOR_PEND
;
parent
->
sk_data_ready
(
parent
,
0
);
}
else
{
sk
->
sk_state
=
BT_CONFIG
;
result
=
L2CAP_CR_SUCCESS
;
status
=
L2CAP_CS_NO_INFO
;
}
}
else
{
sk
->
sk_state
=
BT_CONNECT2
;
result
=
L2CAP_CR_PEND
;
...
...
@@ -1695,11 +1980,14 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
l2cap_pi
(
sk
)
->
dcid
=
dcid
;
l2cap_pi
(
sk
)
->
conf_state
|=
L2CAP_CONF_REQ_SENT
;
l2cap_pi
(
sk
)
->
conf_state
&=
~
L2CAP_CONF_CONNECT_PEND
;
l2cap_send_cmd
(
conn
,
l2cap_get_ident
(
conn
),
L2CAP_CONF_REQ
,
l2cap_build_conf_req
(
sk
,
req
),
req
);
break
;
case
L2CAP_CR_PEND
:
l2cap_pi
(
sk
)
->
conf_state
|=
L2CAP_CONF_CONNECT_PEND
;
break
;
default:
...
...
@@ -1908,6 +2196,14 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm
put_unaligned
(
cpu_to_le32
(
l2cap_feat_mask
),
(
__le32
*
)
rsp
->
data
);
l2cap_send_cmd
(
conn
,
cmd
->
ident
,
L2CAP_INFO_RSP
,
sizeof
(
buf
),
buf
);
}
else
if
(
type
==
L2CAP_IT_FIXED_CHAN
)
{
u8
buf
[
12
];
struct
l2cap_info_rsp
*
rsp
=
(
struct
l2cap_info_rsp
*
)
buf
;
rsp
->
type
=
cpu_to_le16
(
L2CAP_IT_FIXED_CHAN
);
rsp
->
result
=
cpu_to_le16
(
L2CAP_IR_SUCCESS
);
memcpy
(
buf
+
4
,
l2cap_fixed_chan
,
8
);
l2cap_send_cmd
(
conn
,
cmd
->
ident
,
L2CAP_INFO_RSP
,
sizeof
(
buf
),
buf
);
}
else
{
struct
l2cap_info_rsp
rsp
;
rsp
.
type
=
cpu_to_le16
(
type
);
...
...
@@ -1929,14 +2225,31 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm
BT_DBG
(
"type 0x%4.4x result 0x%2.2x"
,
type
,
result
);
conn
->
info_ident
=
0
;
del_timer
(
&
conn
->
info_timer
);
if
(
type
==
L2CAP_IT_FEAT_MASK
)
if
(
type
==
L2CAP_IT_FEAT_MASK
)
{
conn
->
feat_mask
=
get_unaligned_le32
(
rsp
->
data
);
l2cap_conn_start
(
conn
);
if
(
conn
->
feat_mask
&
0x0080
)
{
struct
l2cap_info_req
req
;
req
.
type
=
cpu_to_le16
(
L2CAP_IT_FIXED_CHAN
);
conn
->
info_ident
=
l2cap_get_ident
(
conn
);
l2cap_send_cmd
(
conn
,
conn
->
info_ident
,
L2CAP_INFO_REQ
,
sizeof
(
req
),
&
req
);
}
else
{
conn
->
info_state
|=
L2CAP_INFO_FEAT_MASK_REQ_DONE
;
conn
->
info_ident
=
0
;
l2cap_conn_start
(
conn
);
}
}
else
if
(
type
==
L2CAP_IT_FIXED_CHAN
)
{
conn
->
info_state
|=
L2CAP_INFO_FEAT_MASK_REQ_DONE
;
conn
->
info_ident
=
0
;
l2cap_conn_start
(
conn
);
}
return
0
;
}
...
...
@@ -2143,10 +2456,15 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
continue
;
if
(
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
&
hdev
->
bdaddr
))
{
lm1
|=
(
HCI_LM_ACCEPT
|
l2cap_pi
(
sk
)
->
link_mode
);
lm1
|=
HCI_LM_ACCEPT
;
if
(
l2cap_pi
(
sk
)
->
role_switch
)
lm1
|=
HCI_LM_MASTER
;
exact
++
;
}
else
if
(
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
BDADDR_ANY
))
lm2
|=
(
HCI_LM_ACCEPT
|
l2cap_pi
(
sk
)
->
link_mode
);
}
else
if
(
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
BDADDR_ANY
))
{
lm2
|=
HCI_LM_ACCEPT
;
if
(
l2cap_pi
(
sk
)
->
role_switch
)
lm2
|=
HCI_LM_MASTER
;
}
}
read_unlock
(
&
l2cap_sk_list
.
lock
);
...
...
@@ -2172,89 +2490,48 @@ static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
return
0
;
}
static
int
l2cap_disconn_ind
(
struct
hci_conn
*
hcon
,
u8
reason
)
static
int
l2cap_disconn_ind
(
struct
hci_conn
*
hcon
)
{
BT_DBG
(
"hcon %p reason %d"
,
hcon
,
reason
)
;
struct
l2cap_conn
*
conn
=
hcon
->
l2cap_data
;
if
(
hcon
->
type
!=
ACL_LINK
)
return
0
;
BT_DBG
(
"hcon %p"
,
hcon
);
l2cap_conn_del
(
hcon
,
bt_err
(
reason
));
if
(
hcon
->
type
!=
ACL_LINK
||
!
conn
)
return
0x13
;
return
0
;
return
conn
->
disc_reason
;
}
static
int
l2cap_
auth_cfm
(
struct
hci_conn
*
hcon
,
u8
status
)
static
int
l2cap_
disconn_cfm
(
struct
hci_conn
*
hcon
,
u8
reason
)
{
struct
l2cap_chan_list
*
l
;
struct
l2cap_conn
*
conn
=
hcon
->
l2cap_data
;
struct
sock
*
sk
;
BT_DBG
(
"hcon %p reason %d"
,
hcon
,
reason
);
if
(
!
conn
)
if
(
hcon
->
type
!=
ACL_LINK
)
return
0
;
l
=
&
conn
->
chan_list
;
BT_DBG
(
"conn %p"
,
conn
);
read_lock
(
&
l
->
lock
);
for
(
sk
=
l
->
head
;
sk
;
sk
=
l2cap_pi
(
sk
)
->
next_c
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
bh_lock_sock
(
sk
);
if
((
pi
->
link_mode
&
(
L2CAP_LM_ENCRYPT
|
L2CAP_LM_SECURE
))
&&
!
(
hcon
->
link_mode
&
HCI_LM_ENCRYPT
)
&&
!
status
)
{
bh_unlock_sock
(
sk
);
continue
;
}
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
;
l2cap_pi
(
sk
)
->
ident
=
l2cap_get_ident
(
conn
);
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_REQ
,
sizeof
(
req
),
&
req
);
}
else
{
l2cap_sock_clear_timer
(
sk
);
l2cap_sock_set_timer
(
sk
,
HZ
/
10
);
}
}
else
if
(
sk
->
sk_state
==
BT_CONNECT2
)
{
struct
l2cap_conn_rsp
rsp
;
__u16
result
;
l2cap_conn_del
(
hcon
,
bt_err
(
reason
));
if
(
!
status
)
{
sk
->
sk_state
=
BT_CONFIG
;
result
=
L2CAP_CR_SUCCESS
;
}
else
{
sk
->
sk_state
=
BT_DISCONN
;
l2cap_sock_set_timer
(
sk
,
HZ
/
10
);
result
=
L2CAP_CR_SEC_BLOCK
;
}
return
0
;
}
rsp
.
scid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
dcid
);
rsp
.
dcid
=
cpu_to_le16
(
l2cap_pi
(
sk
)
->
scid
);
rsp
.
result
=
cpu_to_le16
(
result
);
rsp
.
status
=
cpu_to_le16
(
L2CAP_CS_NO_INFO
);
l2cap_send_cmd
(
conn
,
l2cap_pi
(
sk
)
->
ident
,
L2CAP_CONN_RSP
,
sizeof
(
rsp
),
&
rsp
);
}
static
inline
void
l2cap_check_encryption
(
struct
sock
*
sk
,
u8
encrypt
)
{
if
(
sk
->
sk_type
!=
SOCK_SEQPACKET
)
return
;
bh_unlock_sock
(
sk
);
if
(
encrypt
==
0x00
)
{
if
(
l2cap_pi
(
sk
)
->
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
)
__l2cap_sock_close
(
sk
,
ECONNREFUSED
);
}
else
{
if
(
l2cap_pi
(
sk
)
->
sec_level
==
BT_SECURITY_MEDIUM
)
l2cap_sock_clear_timer
(
sk
);
}
read_unlock
(
&
l
->
lock
);
return
0
;
}
static
int
l2cap_
encrypt
_cfm
(
struct
hci_conn
*
hcon
,
u8
status
,
u8
encrypt
)
static
int
l2cap_
security
_cfm
(
struct
hci_conn
*
hcon
,
u8
status
,
u8
encrypt
)
{
struct
l2cap_chan_list
*
l
;
struct
l2cap_conn
*
conn
=
hcon
->
l2cap_data
;
...
...
@@ -2270,15 +2547,16 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
read_lock
(
&
l
->
lock
);
for
(
sk
=
l
->
head
;
sk
;
sk
=
l2cap_pi
(
sk
)
->
next_c
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
bh_lock_sock
(
sk
);
if
((
pi
->
link_mode
&
(
L2CAP_LM_ENCRYPT
|
L2CAP_LM_SECURE
))
&&
(
sk
->
sk_state
==
BT_CONNECTED
||
sk
->
sk_state
==
BT_CONFIG
)
&&
!
status
&&
encrypt
==
0x00
)
{
__l2cap_sock_close
(
sk
,
ECONNREFUSED
);
if
(
l2cap_pi
(
sk
)
->
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
);
bh_unlock_sock
(
sk
);
continue
;
}
...
...
@@ -2376,7 +2654,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
goto
drop
;
skb_copy_from_linear_data
(
skb
,
skb_put
(
conn
->
rx_skb
,
skb
->
len
),
skb
->
len
);
skb
->
len
);
conn
->
rx_len
=
len
-
skb
->
len
;
}
else
{
BT_DBG
(
"Cont: frag len %d (expecting %d)"
,
skb
->
len
,
conn
->
rx_len
);
...
...
@@ -2398,7 +2676,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
}
skb_copy_from_linear_data
(
skb
,
skb_put
(
conn
->
rx_skb
,
skb
->
len
),
skb
->
len
);
skb
->
len
);
conn
->
rx_len
-=
skb
->
len
;
if
(
!
conn
->
rx_len
)
{
...
...
@@ -2424,10 +2702,10 @@ static ssize_t l2cap_sysfs_show(struct class *dev, char *buf)
sk_for_each
(
sk
,
node
,
&
l2cap_sk_list
.
head
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
str
+=
sprintf
(
str
,
"%s %s %d %d 0x%4.4x 0x%4.4x %d %d
0x%x
\n
"
,
str
+=
sprintf
(
str
,
"%s %s %d %d 0x%4.4x 0x%4.4x %d %d
%d
\n
"
,
batostr
(
&
bt_sk
(
sk
)
->
src
),
batostr
(
&
bt_sk
(
sk
)
->
dst
),
sk
->
sk_state
,
btohs
(
pi
->
psm
),
pi
->
scid
,
pi
->
dcid
,
pi
->
imtu
,
pi
->
omtu
,
pi
->
link_mode
);
pi
->
imtu
,
pi
->
omtu
,
pi
->
sec_level
);
}
read_unlock_bh
(
&
l2cap_sk_list
.
lock
);
...
...
@@ -2447,7 +2725,7 @@ static const struct proto_ops l2cap_sock_ops = {
.
accept
=
l2cap_sock_accept
,
.
getname
=
l2cap_sock_getname
,
.
sendmsg
=
l2cap_sock_sendmsg
,
.
recvmsg
=
bt
_sock_recvmsg
,
.
recvmsg
=
l2cap
_sock_recvmsg
,
.
poll
=
bt_sock_poll
,
.
ioctl
=
bt_sock_ioctl
,
.
mmap
=
sock_no_mmap
,
...
...
@@ -2469,8 +2747,8 @@ static struct hci_proto l2cap_hci_proto = {
.
connect_ind
=
l2cap_connect_ind
,
.
connect_cfm
=
l2cap_connect_cfm
,
.
disconn_ind
=
l2cap_disconn_ind
,
.
auth_cfm
=
l2cap_auth
_cfm
,
.
encrypt_cfm
=
l2cap_encrypt
_cfm
,
.
disconn_cfm
=
l2cap_disconn
_cfm
,
.
security_cfm
=
l2cap_security
_cfm
,
.
recv_acldata
=
l2cap_recv_acldata
};
...
...
net/bluetooth/rfcomm/core.c
View file @
63748aa8
...
...
@@ -46,7 +46,7 @@
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/rfcomm.h>
#define VERSION "1.1
0
"
#define VERSION "1.1
1
"
static
int
disable_cfc
=
0
;
static
int
channel_mtu
=
-
1
;
...
...
@@ -223,19 +223,25 @@ static int rfcomm_l2sock_create(struct socket **sock)
return
err
;
}
static
inline
int
rfcomm_check_
link_mode
(
struct
rfcomm_dlc
*
d
)
static
inline
int
rfcomm_check_
security
(
struct
rfcomm_dlc
*
d
)
{
struct
sock
*
sk
=
d
->
session
->
sock
->
sk
;
__u8
auth_type
;
if
(
d
->
link_mode
&
(
RFCOMM_LM_ENCRYPT
|
RFCOMM_LM_SECURE
))
{
if
(
!
hci_conn_encrypt
(
l2cap_pi
(
sk
)
->
conn
->
hcon
))
return
1
;
}
else
if
(
d
->
link_mode
&
RFCOMM_LM_AUTH
)
{
if
(
!
hci_conn_auth
(
l2cap_pi
(
sk
)
->
conn
->
hcon
))
return
1
;
switch
(
d
->
sec_level
)
{
case
BT_SECURITY_HIGH
:
auth_type
=
HCI_AT_GENERAL_BONDING_MITM
;
break
;
case
BT_SECURITY_MEDIUM
:
auth_type
=
HCI_AT_GENERAL_BONDING
;
break
;
default:
auth_type
=
HCI_AT_NO_BONDING
;
break
;
}
return
0
;
return
hci_conn_security
(
l2cap_pi
(
sk
)
->
conn
->
hcon
,
d
->
sec_level
,
auth_type
);
}
/* ---- RFCOMM DLCs ---- */
...
...
@@ -388,10 +394,10 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
d
->
cfc
=
(
s
->
cfc
==
RFCOMM_CFC_UNKNOWN
)
?
0
:
s
->
cfc
;
if
(
s
->
state
==
BT_CONNECTED
)
{
if
(
rfcomm_check_link_mode
(
d
))
set_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
);
else
if
(
rfcomm_check_security
(
d
))
rfcomm_send_pn
(
s
,
1
,
d
);
else
set_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
);
}
rfcomm_dlc_set_timer
(
d
,
RFCOMM_CONN_TIMEOUT
);
...
...
@@ -421,9 +427,16 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
d
,
d
->
state
,
d
->
dlci
,
err
,
s
);
switch
(
d
->
state
)
{
case
BT_CONNECTED
:
case
BT_CONFIG
:
case
BT_CONNECT
:
case
BT_CONFIG
:
if
(
test_and_clear_bit
(
RFCOMM_DEFER_SETUP
,
&
d
->
flags
))
{
set_bit
(
RFCOMM_AUTH_REJECT
,
&
d
->
flags
);
rfcomm_schedule
(
RFCOMM_SCHED_AUTH
);
break
;
}
/* Fall through */
case
BT_CONNECTED
:
d
->
state
=
BT_DISCONN
;
if
(
skb_queue_empty
(
&
d
->
tx_queue
))
{
rfcomm_send_disc
(
s
,
d
->
dlci
);
...
...
@@ -434,6 +447,15 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
}
break
;
case
BT_OPEN
:
case
BT_CONNECT2
:
if
(
test_and_clear_bit
(
RFCOMM_DEFER_SETUP
,
&
d
->
flags
))
{
set_bit
(
RFCOMM_AUTH_REJECT
,
&
d
->
flags
);
rfcomm_schedule
(
RFCOMM_SCHED_AUTH
);
break
;
}
/* Fall through */
default:
rfcomm_dlc_clear_timer
(
d
);
...
...
@@ -636,6 +658,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst
bacpy
(
&
addr
.
l2_bdaddr
,
src
);
addr
.
l2_family
=
AF_BLUETOOTH
;
addr
.
l2_psm
=
0
;
addr
.
l2_cid
=
0
;
*
err
=
kernel_bind
(
sock
,
(
struct
sockaddr
*
)
&
addr
,
sizeof
(
addr
));
if
(
*
err
<
0
)
goto
failed
;
...
...
@@ -657,6 +680,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst
bacpy
(
&
addr
.
l2_bdaddr
,
dst
);
addr
.
l2_family
=
AF_BLUETOOTH
;
addr
.
l2_psm
=
htobs
(
RFCOMM_PSM
);
addr
.
l2_cid
=
0
;
*
err
=
kernel_connect
(
sock
,
(
struct
sockaddr
*
)
&
addr
,
sizeof
(
addr
),
O_NONBLOCK
);
if
(
*
err
==
0
||
*
err
==
-
EINPROGRESS
)
return
s
;
...
...
@@ -1162,7 +1186,7 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
return
0
;
}
static
void
rfcomm_dlc_accept
(
struct
rfcomm_dlc
*
d
)
void
rfcomm_dlc_accept
(
struct
rfcomm_dlc
*
d
)
{
struct
sock
*
sk
=
d
->
session
->
sock
->
sk
;
...
...
@@ -1175,12 +1199,31 @@ static void rfcomm_dlc_accept(struct rfcomm_dlc *d)
d
->
state_change
(
d
,
0
);
rfcomm_dlc_unlock
(
d
);
if
(
d
->
link_mode
&
RFCOMM_LM_MASTER
)
if
(
d
->
role_switch
)
hci_conn_switch_role
(
l2cap_pi
(
sk
)
->
conn
->
hcon
,
0x00
);
rfcomm_send_msc
(
d
->
session
,
1
,
d
->
dlci
,
d
->
v24_sig
);
}
static
void
rfcomm_check_accept
(
struct
rfcomm_dlc
*
d
)
{
if
(
rfcomm_check_security
(
d
))
{
if
(
d
->
defer_setup
)
{
set_bit
(
RFCOMM_DEFER_SETUP
,
&
d
->
flags
);
rfcomm_dlc_set_timer
(
d
,
RFCOMM_AUTH_TIMEOUT
);
rfcomm_dlc_lock
(
d
);
d
->
state
=
BT_CONNECT2
;
d
->
state_change
(
d
,
0
);
rfcomm_dlc_unlock
(
d
);
}
else
rfcomm_dlc_accept
(
d
);
}
else
{
set_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
);
rfcomm_dlc_set_timer
(
d
,
RFCOMM_AUTH_TIMEOUT
);
}
}
static
int
rfcomm_recv_sabm
(
struct
rfcomm_session
*
s
,
u8
dlci
)
{
struct
rfcomm_dlc
*
d
;
...
...
@@ -1203,11 +1246,7 @@ static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
if
(
d
)
{
if
(
d
->
state
==
BT_OPEN
)
{
/* DLC was previously opened by PN request */
if
(
rfcomm_check_link_mode
(
d
))
{
set_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
);
rfcomm_dlc_set_timer
(
d
,
RFCOMM_AUTH_TIMEOUT
);
}
else
rfcomm_dlc_accept
(
d
);
rfcomm_check_accept
(
d
);
}
return
0
;
}
...
...
@@ -1219,11 +1258,7 @@ static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
d
->
addr
=
__addr
(
s
->
initiator
,
dlci
);
rfcomm_dlc_link
(
s
,
d
);
if
(
rfcomm_check_link_mode
(
d
))
{
set_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
);
rfcomm_dlc_set_timer
(
d
,
RFCOMM_AUTH_TIMEOUT
);
}
else
rfcomm_dlc_accept
(
d
);
rfcomm_check_accept
(
d
);
}
else
{
rfcomm_send_dm
(
s
,
dlci
);
}
...
...
@@ -1637,11 +1672,12 @@ static void rfcomm_process_connect(struct rfcomm_session *s)
d
=
list_entry
(
p
,
struct
rfcomm_dlc
,
list
);
if
(
d
->
state
==
BT_CONFIG
)
{
d
->
mtu
=
s
->
mtu
;
if
(
rfcomm_check_link_mode
(
d
))
{
if
(
rfcomm_check_security
(
d
))
{
rfcomm_send_pn
(
s
,
1
,
d
);
}
else
{
set_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
);
rfcomm_dlc_set_timer
(
d
,
RFCOMM_AUTH_TIMEOUT
);
}
else
rfcomm_send_pn
(
s
,
1
,
d
);
}
}
}
}
...
...
@@ -1717,11 +1753,17 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
if
(
d
->
out
)
{
rfcomm_send_pn
(
s
,
1
,
d
);
rfcomm_dlc_set_timer
(
d
,
RFCOMM_CONN_TIMEOUT
);
}
else
rfcomm_dlc_accept
(
d
);
if
(
d
->
link_mode
&
RFCOMM_LM_SECURE
)
{
struct
sock
*
sk
=
s
->
sock
->
sk
;
hci_conn_change_link_key
(
l2cap_pi
(
sk
)
->
conn
->
hcon
);
}
else
{
if
(
d
->
defer_setup
)
{
set_bit
(
RFCOMM_DEFER_SETUP
,
&
d
->
flags
);
rfcomm_dlc_set_timer
(
d
,
RFCOMM_AUTH_TIMEOUT
);
rfcomm_dlc_lock
(
d
);
d
->
state
=
BT_CONNECT2
;
d
->
state_change
(
d
,
0
);
rfcomm_dlc_unlock
(
d
);
}
else
rfcomm_dlc_accept
(
d
);
}
continue
;
}
else
if
(
test_and_clear_bit
(
RFCOMM_AUTH_REJECT
,
&
d
->
flags
))
{
...
...
@@ -1734,6 +1776,9 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
continue
;
}
if
(
test_bit
(
RFCOMM_SEC_PENDING
,
&
d
->
flags
))
continue
;
if
(
test_bit
(
RFCOMM_TX_THROTTLED
,
&
s
->
flags
))
continue
;
...
...
@@ -1876,6 +1921,7 @@ static int rfcomm_add_listener(bdaddr_t *ba)
bacpy
(
&
addr
.
l2_bdaddr
,
ba
);
addr
.
l2_family
=
AF_BLUETOOTH
;
addr
.
l2_psm
=
htobs
(
RFCOMM_PSM
);
addr
.
l2_cid
=
0
;
err
=
kernel_bind
(
sock
,
(
struct
sockaddr
*
)
&
addr
,
sizeof
(
addr
));
if
(
err
<
0
)
{
BT_ERR
(
"Bind failed %d"
,
err
);
...
...
@@ -1947,42 +1993,7 @@ static int rfcomm_run(void *unused)
return
0
;
}
static
void
rfcomm_auth_cfm
(
struct
hci_conn
*
conn
,
u8
status
)
{
struct
rfcomm_session
*
s
;
struct
rfcomm_dlc
*
d
;
struct
list_head
*
p
,
*
n
;
BT_DBG
(
"conn %p status 0x%02x"
,
conn
,
status
);
s
=
rfcomm_session_get
(
&
conn
->
hdev
->
bdaddr
,
&
conn
->
dst
);
if
(
!
s
)
return
;
rfcomm_session_hold
(
s
);
list_for_each_safe
(
p
,
n
,
&
s
->
dlcs
)
{
d
=
list_entry
(
p
,
struct
rfcomm_dlc
,
list
);
if
((
d
->
link_mode
&
(
RFCOMM_LM_ENCRYPT
|
RFCOMM_LM_SECURE
))
&&
!
(
conn
->
link_mode
&
HCI_LM_ENCRYPT
)
&&
!
status
)
continue
;
if
(
!
test_and_clear_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
))
continue
;
if
(
!
status
)
set_bit
(
RFCOMM_AUTH_ACCEPT
,
&
d
->
flags
);
else
set_bit
(
RFCOMM_AUTH_REJECT
,
&
d
->
flags
);
}
rfcomm_session_put
(
s
);
rfcomm_schedule
(
RFCOMM_SCHED_AUTH
);
}
static
void
rfcomm_encrypt_cfm
(
struct
hci_conn
*
conn
,
u8
status
,
u8
encrypt
)
static
void
rfcomm_security_cfm
(
struct
hci_conn
*
conn
,
u8
status
,
u8
encrypt
)
{
struct
rfcomm_session
*
s
;
struct
rfcomm_dlc
*
d
;
...
...
@@ -1999,18 +2010,29 @@ static void rfcomm_encrypt_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
list_for_each_safe
(
p
,
n
,
&
s
->
dlcs
)
{
d
=
list_entry
(
p
,
struct
rfcomm_dlc
,
list
);
if
((
d
->
link_mode
&
(
RFCOMM_LM_ENCRYPT
|
RFCOMM_LM_SECURE
))
&&
(
d
->
state
==
BT_CONNECTED
||
d
->
state
==
BT_CONFIG
)
&&
!
status
&&
encrypt
==
0x00
)
{
__rfcomm_dlc_close
(
d
,
ECONNREFUSED
);
continue
;
if
(
test_and_clear_bit
(
RFCOMM_SEC_PENDING
,
&
d
->
flags
))
{
rfcomm_dlc_clear_timer
(
d
);
if
(
status
||
encrypt
==
0x00
)
{
__rfcomm_dlc_close
(
d
,
ECONNREFUSED
);
continue
;
}
}
if
(
d
->
state
==
BT_CONNECTED
&&
!
status
&&
encrypt
==
0x00
)
{
if
(
d
->
sec_level
==
BT_SECURITY_MEDIUM
)
{
set_bit
(
RFCOMM_SEC_PENDING
,
&
d
->
flags
);
rfcomm_dlc_set_timer
(
d
,
RFCOMM_AUTH_TIMEOUT
);
continue
;
}
else
if
(
d
->
sec_level
==
BT_SECURITY_HIGH
)
{
__rfcomm_dlc_close
(
d
,
ECONNREFUSED
);
continue
;
}
}
if
(
!
test_and_clear_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
))
continue
;
if
(
!
status
&&
encrypt
)
if
(
!
status
)
set_bit
(
RFCOMM_AUTH_ACCEPT
,
&
d
->
flags
);
else
set_bit
(
RFCOMM_AUTH_REJECT
,
&
d
->
flags
);
...
...
@@ -2023,8 +2045,7 @@ static void rfcomm_encrypt_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
static
struct
hci_cb
rfcomm_cb
=
{
.
name
=
"RFCOMM"
,
.
auth_cfm
=
rfcomm_auth_cfm
,
.
encrypt_cfm
=
rfcomm_encrypt_cfm
.
security_cfm
=
rfcomm_security_cfm
};
static
ssize_t
rfcomm_dlc_sysfs_show
(
struct
class
*
dev
,
char
*
buf
)
...
...
net/bluetooth/rfcomm/sock.c
View file @
63748aa8
...
...
@@ -261,12 +261,19 @@ static void rfcomm_sock_init(struct sock *sk, struct sock *parent)
if
(
parent
)
{
sk
->
sk_type
=
parent
->
sk_type
;
pi
->
link_mode
=
rfcomm_pi
(
parent
)
->
link_mode
;
pi
->
dlc
->
defer_setup
=
bt_sk
(
parent
)
->
defer_setup
;
pi
->
sec_level
=
rfcomm_pi
(
parent
)
->
sec_level
;
pi
->
role_switch
=
rfcomm_pi
(
parent
)
->
role_switch
;
}
else
{
pi
->
link_mode
=
0
;
pi
->
dlc
->
defer_setup
=
0
;
pi
->
sec_level
=
BT_SECURITY_LOW
;
pi
->
role_switch
=
0
;
}
pi
->
dlc
->
link_mode
=
pi
->
link_mode
;
pi
->
dlc
->
sec_level
=
pi
->
sec_level
;
pi
->
dlc
->
role_switch
=
pi
->
role_switch
;
}
static
struct
proto
rfcomm_proto
=
{
...
...
@@ -406,7 +413,8 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
bacpy
(
&
bt_sk
(
sk
)
->
dst
,
&
sa
->
rc_bdaddr
);
rfcomm_pi
(
sk
)
->
channel
=
sa
->
rc_channel
;
d
->
link_mode
=
rfcomm_pi
(
sk
)
->
link_mode
;
d
->
sec_level
=
rfcomm_pi
(
sk
)
->
sec_level
;
d
->
role_switch
=
rfcomm_pi
(
sk
)
->
role_switch
;
err
=
rfcomm_dlc_open
(
d
,
&
bt_sk
(
sk
)
->
src
,
&
sa
->
rc_bdaddr
,
sa
->
rc_channel
);
if
(
!
err
)
...
...
@@ -554,6 +562,9 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
struct
sk_buff
*
skb
;
int
sent
=
0
;
if
(
test_bit
(
RFCOMM_DEFER_SETUP
,
&
d
->
flags
))
return
-
ENOTCONN
;
if
(
msg
->
msg_flags
&
MSG_OOB
)
return
-
EOPNOTSUPP
;
...
...
@@ -570,8 +581,11 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
skb
=
sock_alloc_send_skb
(
sk
,
size
+
RFCOMM_SKB_RESERVE
,
msg
->
msg_flags
&
MSG_DONTWAIT
,
&
err
);
if
(
!
skb
)
if
(
!
skb
)
{
if
(
sent
==
0
)
sent
=
err
;
break
;
}
skb_reserve
(
skb
,
RFCOMM_SKB_HEAD_RESERVE
);
err
=
memcpy_fromiovec
(
skb_put
(
skb
,
size
),
msg
->
msg_iov
,
size
);
...
...
@@ -630,10 +644,16 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
struct
msghdr
*
msg
,
size_t
size
,
int
flags
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
rfcomm_dlc
*
d
=
rfcomm_pi
(
sk
)
->
dlc
;
int
err
=
0
;
size_t
target
,
copied
=
0
;
long
timeo
;
if
(
test_and_clear_bit
(
RFCOMM_DEFER_SETUP
,
&
d
->
flags
))
{
rfcomm_dlc_accept
(
d
);
return
0
;
}
if
(
flags
&
MSG_OOB
)
return
-
EOPNOTSUPP
;
...
...
@@ -710,7 +730,7 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
return
copied
?
:
err
;
}
static
int
rfcomm_sock_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
__user
*
optval
,
int
optlen
)
static
int
rfcomm_sock_setsockopt
_old
(
struct
socket
*
sock
,
int
optname
,
char
__user
*
optval
,
int
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
int
err
=
0
;
...
...
@@ -727,7 +747,14 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
break
;
}
rfcomm_pi
(
sk
)
->
link_mode
=
opt
;
if
(
opt
&
RFCOMM_LM_AUTH
)
rfcomm_pi
(
sk
)
->
sec_level
=
BT_SECURITY_LOW
;
if
(
opt
&
RFCOMM_LM_ENCRYPT
)
rfcomm_pi
(
sk
)
->
sec_level
=
BT_SECURITY_MEDIUM
;
if
(
opt
&
RFCOMM_LM_SECURE
)
rfcomm_pi
(
sk
)
->
sec_level
=
BT_SECURITY_HIGH
;
rfcomm_pi
(
sk
)
->
role_switch
=
(
opt
&
RFCOMM_LM_MASTER
);
break
;
default:
...
...
@@ -739,12 +766,76 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
return
err
;
}
static
int
rfcomm_sock_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
__user
*
optval
,
int
__user
*
optlen
)
static
int
rfcomm_sock_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
__user
*
optval
,
int
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
bt_security
sec
;
int
len
,
err
=
0
;
u32
opt
;
BT_DBG
(
"sk %p"
,
sk
);
if
(
level
==
SOL_RFCOMM
)
return
rfcomm_sock_setsockopt_old
(
sock
,
optname
,
optval
,
optlen
);
if
(
level
!=
SOL_BLUETOOTH
)
return
-
ENOPROTOOPT
;
lock_sock
(
sk
);
switch
(
optname
)
{
case
BT_SECURITY
:
if
(
sk
->
sk_type
!=
SOCK_STREAM
)
{
err
=
-
EINVAL
;
break
;
}
sec
.
level
=
BT_SECURITY_LOW
;
len
=
min_t
(
unsigned
int
,
sizeof
(
sec
),
optlen
);
if
(
copy_from_user
((
char
*
)
&
sec
,
optval
,
len
))
{
err
=
-
EFAULT
;
break
;
}
if
(
sec
.
level
>
BT_SECURITY_HIGH
)
{
err
=
-
EINVAL
;
break
;
}
rfcomm_pi
(
sk
)
->
sec_level
=
sec
.
level
;
break
;
case
BT_DEFER_SETUP
:
if
(
sk
->
sk_state
!=
BT_BOUND
&&
sk
->
sk_state
!=
BT_LISTEN
)
{
err
=
-
EINVAL
;
break
;
}
if
(
get_user
(
opt
,
(
u32
__user
*
)
optval
))
{
err
=
-
EFAULT
;
break
;
}
bt_sk
(
sk
)
->
defer_setup
=
opt
;
break
;
default:
err
=
-
ENOPROTOOPT
;
break
;
}
release_sock
(
sk
);
return
err
;
}
static
int
rfcomm_sock_getsockopt_old
(
struct
socket
*
sock
,
int
optname
,
char
__user
*
optval
,
int
__user
*
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sock
*
l2cap_sk
;
struct
rfcomm_conninfo
cinfo
;
int
len
,
err
=
0
;
u32
opt
;
BT_DBG
(
"sk %p"
,
sk
);
...
...
@@ -755,12 +846,32 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c
switch
(
optname
)
{
case
RFCOMM_LM
:
if
(
put_user
(
rfcomm_pi
(
sk
)
->
link_mode
,
(
u32
__user
*
)
optval
))
switch
(
rfcomm_pi
(
sk
)
->
sec_level
)
{
case
BT_SECURITY_LOW
:
opt
=
RFCOMM_LM_AUTH
;
break
;
case
BT_SECURITY_MEDIUM
:
opt
=
RFCOMM_LM_AUTH
|
RFCOMM_LM_ENCRYPT
;
break
;
case
BT_SECURITY_HIGH
:
opt
=
RFCOMM_LM_AUTH
|
RFCOMM_LM_ENCRYPT
|
RFCOMM_LM_SECURE
;
break
;
default:
opt
=
0
;
break
;
}
if
(
rfcomm_pi
(
sk
)
->
role_switch
)
opt
|=
RFCOMM_LM_MASTER
;
if
(
put_user
(
opt
,
(
u32
__user
*
)
optval
))
err
=
-
EFAULT
;
break
;
case
RFCOMM_CONNINFO
:
if
(
sk
->
sk_state
!=
BT_CONNECTED
)
{
if
(
sk
->
sk_state
!=
BT_CONNECTED
&&
!
rfcomm_pi
(
sk
)
->
dlc
->
defer_setup
)
{
err
=
-
ENOTCONN
;
break
;
}
...
...
@@ -785,6 +896,60 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c
return
err
;
}
static
int
rfcomm_sock_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
__user
*
optval
,
int
__user
*
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
bt_security
sec
;
int
len
,
err
=
0
;
BT_DBG
(
"sk %p"
,
sk
);
if
(
level
==
SOL_RFCOMM
)
return
rfcomm_sock_getsockopt_old
(
sock
,
optname
,
optval
,
optlen
);
if
(
level
!=
SOL_BLUETOOTH
)
return
-
ENOPROTOOPT
;
if
(
get_user
(
len
,
optlen
))
return
-
EFAULT
;
lock_sock
(
sk
);
switch
(
optname
)
{
case
BT_SECURITY
:
if
(
sk
->
sk_type
!=
SOCK_STREAM
)
{
err
=
-
EINVAL
;
break
;
}
sec
.
level
=
rfcomm_pi
(
sk
)
->
sec_level
;
len
=
min_t
(
unsigned
int
,
len
,
sizeof
(
sec
));
if
(
copy_to_user
(
optval
,
(
char
*
)
&
sec
,
len
))
err
=
-
EFAULT
;
break
;
case
BT_DEFER_SETUP
:
if
(
sk
->
sk_state
!=
BT_BOUND
&&
sk
->
sk_state
!=
BT_LISTEN
)
{
err
=
-
EINVAL
;
break
;
}
if
(
put_user
(
bt_sk
(
sk
)
->
defer_setup
,
(
u32
__user
*
)
optval
))
err
=
-
EFAULT
;
break
;
default:
err
=
-
ENOPROTOOPT
;
break
;
}
release_sock
(
sk
);
return
err
;
}
static
int
rfcomm_sock_ioctl
(
struct
socket
*
sock
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
sock
*
sk
__maybe_unused
=
sock
->
sk
;
...
...
@@ -888,6 +1053,10 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
done:
bh_unlock_sock
(
parent
);
if
(
bt_sk
(
parent
)
->
defer_setup
)
parent
->
sk_state_change
(
parent
);
return
result
;
}
...
...
net/bluetooth/sco.c
View file @
63748aa8
...
...
@@ -195,7 +195,7 @@ static int sco_connect(struct sock *sk)
else
type
=
SCO_LINK
;
hcon
=
hci_connect
(
hdev
,
type
,
dst
,
HCI_AT_NO_BONDING
);
hcon
=
hci_connect
(
hdev
,
type
,
dst
,
BT_SECURITY_LOW
,
HCI_AT_NO_BONDING
);
if
(
!
hcon
)
goto
done
;
...
...
@@ -668,7 +668,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char
return
err
;
}
static
int
sco_sock_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
__user
*
optval
,
int
__user
*
optlen
)
static
int
sco_sock_getsockopt
_old
(
struct
socket
*
sock
,
int
optname
,
char
__user
*
optval
,
int
__user
*
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sco_options
opts
;
...
...
@@ -723,6 +723,31 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char
return
err
;
}
static
int
sco_sock_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
__user
*
optval
,
int
__user
*
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
int
len
,
err
=
0
;
BT_DBG
(
"sk %p"
,
sk
);
if
(
level
==
SOL_SCO
)
return
sco_sock_getsockopt_old
(
sock
,
optname
,
optval
,
optlen
);
if
(
get_user
(
len
,
optlen
))
return
-
EFAULT
;
lock_sock
(
sk
);
switch
(
optname
)
{
default:
err
=
-
ENOPROTOOPT
;
break
;
}
release_sock
(
sk
);
return
err
;
}
static
int
sco_sock_release
(
struct
socket
*
sock
)
{
struct
sock
*
sk
=
sock
->
sk
;
...
...
@@ -832,10 +857,30 @@ static void sco_conn_ready(struct sco_conn *conn)
/* ----- SCO interface with lower layer (HCI) ----- */
static
int
sco_connect_ind
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
__u8
type
)
{
register
struct
sock
*
sk
;
struct
hlist_node
*
node
;
int
lm
=
0
;
if
(
type
!=
SCO_LINK
&&
type
!=
ESCO_LINK
)
return
0
;
BT_DBG
(
"hdev %s, bdaddr %s"
,
hdev
->
name
,
batostr
(
bdaddr
));
/* Always accept connection */
return
HCI_LM_ACCEPT
;
/* Find listening sockets */
read_lock
(
&
sco_sk_list
.
lock
);
sk_for_each
(
sk
,
node
,
&
sco_sk_list
.
head
)
{
if
(
sk
->
sk_state
!=
BT_LISTEN
)
continue
;
if
(
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
&
hdev
->
bdaddr
)
||
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
BDADDR_ANY
))
{
lm
|=
HCI_LM_ACCEPT
;
break
;
}
}
read_unlock
(
&
sco_sk_list
.
lock
);
return
lm
;
}
static
int
sco_connect_cfm
(
struct
hci_conn
*
hcon
,
__u8
status
)
...
...
@@ -857,7 +902,7 @@ static int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
return
0
;
}
static
int
sco_disconn_
ind
(
struct
hci_conn
*
hcon
,
__u8
reason
)
static
int
sco_disconn_
cfm
(
struct
hci_conn
*
hcon
,
__u8
reason
)
{
BT_DBG
(
"hcon %p reason %d"
,
hcon
,
reason
);
...
...
@@ -940,7 +985,7 @@ static struct hci_proto sco_hci_proto = {
.
id
=
HCI_PROTO_SCO
,
.
connect_ind
=
sco_connect_ind
,
.
connect_cfm
=
sco_connect_cfm
,
.
disconn_
ind
=
sco_disconn_ind
,
.
disconn_
cfm
=
sco_disconn_cfm
,
.
recv_scodata
=
sco_recv_scodata
};
...
...
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