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
Expand all
Show 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,7 +257,6 @@ 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
);
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
);
}
}
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,7 +102,6 @@ static int h4_close(struct hci_uart *hu)
skb_queue_purge
(
&
h4
->
txq
);
if
(
h4
->
rx_skb
)
kfree_skb
(
h4
->
rx_skb
);
hu
->
priv
=
NULL
;
...
...
drivers/bluetooth/hci_ll.c
View file @
63748aa8
...
...
@@ -163,7 +163,6 @@ 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
);
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
);
...
...
@@ -478,11 +478,11 @@ struct hci_proto {
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
)
...
...
@@ -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
;
...
...
@@ -203,9 +204,11 @@ struct rfcomm_dlc {
#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_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
);
...
...
@@ -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,7 +126,6 @@ static inline void cmtp_add_msgpart(struct cmtp_session *session, int id, const
session
->
reassembly
[
id
]
=
nskb
;
if
(
skb
)
kfree_skb
(
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,7 +1565,6 @@ 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
);
if
((
hdev
->
sent_cmd
=
skb_clone
(
skb
,
GFP_ATOMIC
)))
{
...
...
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
This diff is collapsed.
Click to expand it.
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
{
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
);
if
(
d
->
link_mode
&
RFCOMM_LM_SECURE
)
{
struct
sock
*
sk
=
s
->
sock
->
sk
;
hci_conn_change_link_key
(
l2cap_pi
(
sk
)
->
conn
->
hcon
);
}
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,13 +1993,13 @@ static int rfcomm_run(void *unused)
return
0
;
}
static
void
rfcomm_
auth_cfm
(
struct
hci_conn
*
conn
,
u8
status
)
static
void
rfcomm_
security_cfm
(
struct
hci_conn
*
conn
,
u8
status
,
u8
encrypt
)
{
struct
rfcomm_session
*
s
;
struct
rfcomm_dlc
*
d
;
struct
list_head
*
p
,
*
n
;
BT_DBG
(
"conn %p status 0x%02x
"
,
conn
,
status
);
BT_DBG
(
"conn %p status 0x%02x
encrypt 0x%02x"
,
conn
,
status
,
encrypt
);
s
=
rfcomm_session_get
(
&
conn
->
hdev
->
bdaddr
,
&
conn
->
dst
);
if
(
!
s
)
...
...
@@ -1964,53 +2010,29 @@ static void rfcomm_auth_cfm(struct hci_conn *conn, u8 status)
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
))
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
(
!
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
)
{
struct
rfcomm_session
*
s
;
struct
rfcomm_dlc
*
d
;
struct
list_head
*
p
,
*
n
;
BT_DBG
(
"conn %p status 0x%02x encrypt 0x%02x"
,
conn
,
status
,
encrypt
);
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
))
&&
(
d
->
state
==
BT_CONNECTED
||
d
->
state
==
BT_CONFIG
)
&&
!
status
&&
encrypt
==
0x00
)
{
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