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
nexedi
linux
Commits
15cb3096
Commit
15cb3096
authored
May 12, 2011
by
John W. Linville
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-next-2.6
parents
4daf50f2
55183d06
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
180 additions
and
124 deletions
+180
-124
drivers/bluetooth/ath3k.c
drivers/bluetooth/ath3k.c
+1
-0
drivers/bluetooth/btusb.c
drivers/bluetooth/btusb.c
+1
-0
include/net/bluetooth/hci_core.h
include/net/bluetooth/hci_core.h
+1
-0
include/net/bluetooth/l2cap.h
include/net/bluetooth/l2cap.h
+6
-3
net/bluetooth/hci_conn.c
net/bluetooth/hci_conn.c
+17
-0
net/bluetooth/hci_event.c
net/bluetooth/hci_event.c
+4
-1
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_core.c
+133
-60
net/bluetooth/l2cap_sock.c
net/bluetooth/l2cap_sock.c
+13
-59
net/bluetooth/mgmt.c
net/bluetooth/mgmt.c
+3
-0
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/core.c
+1
-1
No files found.
drivers/bluetooth/ath3k.c
View file @
15cb3096
...
...
@@ -62,6 +62,7 @@ static struct usb_device_id ath3k_table[] = {
/* Atheros AR3011 with sflash firmware*/
{
USB_DEVICE
(
0x0CF3
,
0x3002
)
},
{
USB_DEVICE
(
0x13d3
,
0x3304
)
},
/* Atheros AR9285 Malbec with sflash firmware */
{
USB_DEVICE
(
0x03F0
,
0x311D
)
},
...
...
drivers/bluetooth/btusb.c
View file @
15cb3096
...
...
@@ -104,6 +104,7 @@ static struct usb_device_id blacklist_table[] = {
/* Atheros 3011 with sflash firmware */
{
USB_DEVICE
(
0x0cf3
,
0x3002
),
.
driver_info
=
BTUSB_IGNORE
},
{
USB_DEVICE
(
0x13d3
,
0x3304
),
.
driver_info
=
BTUSB_IGNORE
},
/* Atheros AR9285 Malbec with sflash firmware */
{
USB_DEVICE
(
0x03f0
,
0x311d
),
.
driver_info
=
BTUSB_IGNORE
},
...
...
include/net/bluetooth/hci_core.h
View file @
15cb3096
...
...
@@ -422,6 +422,7 @@ void hci_conn_check_pending(struct hci_dev *hdev);
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_check_secure
(
struct
hci_conn
*
conn
,
__u8
sec_level
);
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
,
__u8
role
);
...
...
include/net/bluetooth/l2cap.h
View file @
15cb3096
...
...
@@ -350,6 +350,7 @@ struct l2cap_chan {
struct
list_head
srej_l
;
struct
list_head
list
;
struct
list_head
global_l
;
};
struct
l2cap_conn
{
...
...
@@ -441,7 +442,6 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
#define __is_sar_start(ctrl) (((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START)
extern
int
disable_ertm
;
extern
struct
bt_sock_list
l2cap_sk_list
;
int
l2cap_init_sockets
(
void
);
void
l2cap_cleanup_sockets
(
void
);
...
...
@@ -458,6 +458,9 @@ void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb);
void
l2cap_streaming_send
(
struct
l2cap_chan
*
chan
);
int
l2cap_ertm_send
(
struct
l2cap_chan
*
chan
);
int
l2cap_add_psm
(
struct
l2cap_chan
*
chan
,
bdaddr_t
*
src
,
__le16
psm
);
int
l2cap_add_scid
(
struct
l2cap_chan
*
chan
,
__u16
scid
);
void
l2cap_sock_set_timer
(
struct
sock
*
sk
,
long
timeout
);
void
l2cap_sock_clear_timer
(
struct
sock
*
sk
);
void
__l2cap_sock_close
(
struct
sock
*
sk
,
int
reason
);
...
...
@@ -466,9 +469,9 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent);
struct
sock
*
l2cap_sock_alloc
(
struct
net
*
net
,
struct
socket
*
sock
,
int
proto
,
gfp_t
prio
);
void
l2cap_send_disconn_req
(
struct
l2cap_conn
*
conn
,
struct
l2cap_chan
*
chan
,
int
err
);
struct
l2cap_chan
*
l2cap_chan_
alloc
(
struct
sock
*
sk
);
struct
l2cap_chan
*
l2cap_chan_
create
(
struct
sock
*
sk
);
void
l2cap_chan_del
(
struct
l2cap_chan
*
chan
,
int
err
);
void
l2cap_chan_
free
(
struct
l2cap_chan
*
chan
);
void
l2cap_chan_
destroy
(
struct
l2cap_chan
*
chan
);
int
l2cap_chan_connect
(
struct
l2cap_chan
*
chan
);
#endif
/* __L2CAP_H */
net/bluetooth/hci_conn.c
View file @
15cb3096
...
...
@@ -623,6 +623,23 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
}
EXPORT_SYMBOL
(
hci_conn_security
);
/* Check secure link requirement */
int
hci_conn_check_secure
(
struct
hci_conn
*
conn
,
__u8
sec_level
)
{
BT_DBG
(
"conn %p"
,
conn
);
if
(
sec_level
!=
BT_SECURITY_HIGH
)
return
1
;
/* Accept if non-secure is required */
if
(
conn
->
key_type
==
HCI_LK_AUTH_COMBINATION
||
(
conn
->
key_type
==
HCI_LK_COMBINATION
&&
conn
->
pin_length
==
16
))
return
1
;
return
0
;
/* Reject not secure link */
}
EXPORT_SYMBOL
(
hci_conn_check_secure
);
/* Change link key */
int
hci_conn_change_link_key
(
struct
hci_conn
*
conn
)
{
...
...
net/bluetooth/hci_event.c
View file @
15cb3096
...
...
@@ -1440,7 +1440,7 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff
conn
->
state
=
BT_CLOSED
;
if
(
conn
->
type
==
ACL_LINK
)
if
(
conn
->
type
==
ACL_LINK
||
conn
->
type
==
LE_LINK
)
mgmt_disconnected
(
hdev
->
id
,
&
conn
->
dst
);
hci_proto_disconn_cfm
(
conn
,
ev
->
reason
);
...
...
@@ -2659,12 +2659,15 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff
}
if
(
ev
->
status
)
{
mgmt_connect_failed
(
hdev
->
id
,
&
ev
->
bdaddr
,
ev
->
status
);
hci_proto_connect_cfm
(
conn
,
ev
->
status
);
conn
->
state
=
BT_CLOSED
;
hci_conn_del
(
conn
);
goto
unlock
;
}
mgmt_connected
(
hdev
->
id
,
&
ev
->
bdaddr
);
conn
->
handle
=
__le16_to_cpu
(
ev
->
handle
);
conn
->
state
=
BT_CONNECTED
;
...
...
net/bluetooth/l2cap_core.c
View file @
15cb3096
...
...
@@ -62,9 +62,8 @@ static u8 l2cap_fixed_chan[8] = { 0x02, };
static
struct
workqueue_struct
*
_busy_wq
;
struct
bt_sock_list
l2cap_sk_list
=
{
.
lock
=
__RW_LOCK_UNLOCKED
(
l2cap_sk_list
.
lock
)
};
LIST_HEAD
(
chan_list
);
DEFINE_RWLOCK
(
chan_list_lock
);
static
void
l2cap_busy_work
(
struct
work_struct
*
work
);
...
...
@@ -135,6 +134,64 @@ static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn
return
c
;
}
static
struct
l2cap_chan
*
__l2cap_global_chan_by_addr
(
__le16
psm
,
bdaddr_t
*
src
)
{
struct
l2cap_chan
*
c
;
list_for_each_entry
(
c
,
&
chan_list
,
global_l
)
{
if
(
c
->
sport
==
psm
&&
!
bacmp
(
&
bt_sk
(
c
->
sk
)
->
src
,
src
))
goto
found
;
}
c
=
NULL
;
found:
return
c
;
}
int
l2cap_add_psm
(
struct
l2cap_chan
*
chan
,
bdaddr_t
*
src
,
__le16
psm
)
{
int
err
;
write_lock_bh
(
&
chan_list_lock
);
if
(
psm
&&
__l2cap_global_chan_by_addr
(
psm
,
src
))
{
err
=
-
EADDRINUSE
;
goto
done
;
}
if
(
psm
)
{
chan
->
psm
=
psm
;
chan
->
sport
=
psm
;
err
=
0
;
}
else
{
u16
p
;
err
=
-
EINVAL
;
for
(
p
=
0x1001
;
p
<
0x1100
;
p
+=
2
)
if
(
!
__l2cap_global_chan_by_addr
(
cpu_to_le16
(
p
),
src
))
{
chan
->
psm
=
cpu_to_le16
(
p
);
chan
->
sport
=
cpu_to_le16
(
p
);
err
=
0
;
break
;
}
}
done:
write_unlock_bh
(
&
chan_list_lock
);
return
err
;
}
int
l2cap_add_scid
(
struct
l2cap_chan
*
chan
,
__u16
scid
)
{
write_lock_bh
(
&
chan_list_lock
);
chan
->
scid
=
scid
;
write_unlock_bh
(
&
chan_list_lock
);
return
0
;
}
static
u16
l2cap_alloc_cid
(
struct
l2cap_conn
*
conn
)
{
u16
cid
=
L2CAP_CID_DYN_START
;
...
...
@@ -147,7 +204,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
return
0
;
}
struct
l2cap_chan
*
l2cap_chan_
alloc
(
struct
sock
*
sk
)
struct
l2cap_chan
*
l2cap_chan_
create
(
struct
sock
*
sk
)
{
struct
l2cap_chan
*
chan
;
...
...
@@ -157,11 +214,19 @@ struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
chan
->
sk
=
sk
;
write_lock_bh
(
&
chan_list_lock
);
list_add
(
&
chan
->
global_l
,
&
chan_list
);
write_unlock_bh
(
&
chan_list_lock
);
return
chan
;
}
void
l2cap_chan_
free
(
struct
l2cap_chan
*
chan
)
void
l2cap_chan_
destroy
(
struct
l2cap_chan
*
chan
)
{
write_lock_bh
(
&
chan_list_lock
);
list_del
(
&
chan
->
global_l
);
write_unlock_bh
(
&
chan_list_lock
);
kfree
(
chan
);
}
...
...
@@ -591,48 +656,51 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
/* Find socket with cid and source bdaddr.
* Returns closest match, locked.
*/
static
struct
sock
*
l2cap_get_sock
_by_scid
(
int
state
,
__le16
cid
,
bdaddr_t
*
src
)
static
struct
l2cap_chan
*
l2cap_global_chan
_by_scid
(
int
state
,
__le16
cid
,
bdaddr_t
*
src
)
{
struct
sock
*
sk
=
NULL
,
*
sk1
=
NULL
;
struct
hlist_node
*
node
;
struct
l2cap_chan
*
c
,
*
c1
=
NULL
;
read_lock
(
&
l2cap_sk_list
.
lock
);
read_lock
(
&
chan_list_
lock
);
sk_for_each
(
sk
,
node
,
&
l2cap_sk_list
.
head
)
{
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
list_for_each_entry
(
c
,
&
chan_list
,
global_l
)
{
struct
sock
*
sk
=
c
->
sk
;
if
(
state
&&
sk
->
sk_state
!=
state
)
continue
;
if
(
c
han
->
scid
==
cid
)
{
if
(
c
->
scid
==
cid
)
{
/* Exact match. */
if
(
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
src
))
break
;
if
(
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
src
))
{
read_unlock
(
&
chan_list_lock
);
return
c
;
}
/* Closest match */
if
(
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
BDADDR_ANY
))
sk1
=
sk
;
c1
=
c
;
}
}
read_unlock
(
&
l2cap_sk_list
.
lock
);
read_unlock
(
&
chan_list_
lock
);
return
node
?
sk
:
sk
1
;
return
c
1
;
}
static
void
l2cap_le_conn_ready
(
struct
l2cap_conn
*
conn
)
{
struct
sock
*
parent
,
*
sk
;
struct
l2cap_chan
*
chan
;
struct
l2cap_chan
*
chan
,
*
pchan
;
BT_DBG
(
""
);
/* Check if we have socket listening on cid */
p
arent
=
l2cap_get_sock
_by_scid
(
BT_LISTEN
,
L2CAP_CID_LE_DATA
,
p
chan
=
l2cap_global_chan
_by_scid
(
BT_LISTEN
,
L2CAP_CID_LE_DATA
,
conn
->
src
);
if
(
!
p
arent
)
if
(
!
p
chan
)
return
;
parent
=
pchan
->
sk
;
bh_lock_sock
(
parent
);
/* Check for backlog size */
...
...
@@ -645,7 +713,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
if
(
!
sk
)
goto
clean
;
chan
=
l2cap_chan_
alloc
(
sk
);
chan
=
l2cap_chan_
create
(
sk
);
if
(
!
chan
)
{
l2cap_sock_kill
(
sk
);
goto
clean
;
...
...
@@ -823,33 +891,34 @@ static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *ch
/* Find socket with psm and source bdaddr.
* Returns closest match.
*/
static
struct
sock
*
l2cap_get_sock
_by_psm
(
int
state
,
__le16
psm
,
bdaddr_t
*
src
)
static
struct
l2cap_chan
*
l2cap_global_chan
_by_psm
(
int
state
,
__le16
psm
,
bdaddr_t
*
src
)
{
struct
sock
*
sk
=
NULL
,
*
sk1
=
NULL
;
struct
hlist_node
*
node
;
struct
l2cap_chan
*
c
,
*
c1
=
NULL
;
read_lock
(
&
l2cap_sk_list
.
lock
);
read_lock
(
&
chan_list_
lock
);
sk_for_each
(
sk
,
node
,
&
l2cap_sk_list
.
head
)
{
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
list_for_each_entry
(
c
,
&
chan_list
,
global_l
)
{
struct
sock
*
sk
=
c
->
sk
;
if
(
state
&&
sk
->
sk_state
!=
state
)
continue
;
if
(
c
han
->
psm
==
psm
)
{
if
(
c
->
psm
==
psm
)
{
/* Exact match. */
if
(
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
src
))
break
;
if
(
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
src
))
{
read_unlock_bh
(
&
chan_list_lock
);
return
c
;
}
/* Closest match */
if
(
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
BDADDR_ANY
))
sk1
=
sk
;
c1
=
c
;
}
}
read_unlock
(
&
l2cap_sk_list
.
lock
);
read_unlock
(
&
chan_list_
lock
);
return
node
?
sk
:
sk
1
;
return
c
1
;
}
int
l2cap_chan_connect
(
struct
l2cap_chan
*
chan
)
...
...
@@ -2019,7 +2088,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
{
struct
l2cap_conn_req
*
req
=
(
struct
l2cap_conn_req
*
)
data
;
struct
l2cap_conn_rsp
rsp
;
struct
l2cap_chan
*
chan
=
NULL
;
struct
l2cap_chan
*
chan
=
NULL
,
*
pchan
;
struct
sock
*
parent
,
*
sk
=
NULL
;
int
result
,
status
=
L2CAP_CS_NO_INFO
;
...
...
@@ -2029,12 +2098,14 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
BT_DBG
(
"psm 0x%2.2x scid 0x%4.4x"
,
psm
,
scid
);
/* Check if we have socket listening on psm */
p
arent
=
l2cap_get_sock
_by_psm
(
BT_LISTEN
,
psm
,
conn
->
src
);
if
(
!
p
arent
)
{
p
chan
=
l2cap_global_chan
_by_psm
(
BT_LISTEN
,
psm
,
conn
->
src
);
if
(
!
p
chan
)
{
result
=
L2CAP_CR_BAD_PSM
;
goto
sendresp
;
}
parent
=
pchan
->
sk
;
bh_lock_sock
(
parent
);
/* Check if the ACL is secure enough (if not SDP) */
...
...
@@ -2057,7 +2128,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
if
(
!
sk
)
goto
response
;
chan
=
l2cap_chan_
alloc
(
sk
);
chan
=
l2cap_chan_
create
(
sk
);
if
(
!
chan
)
{
l2cap_sock_kill
(
sk
);
goto
response
;
...
...
@@ -3685,11 +3756,14 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
static
inline
int
l2cap_conless_channel
(
struct
l2cap_conn
*
conn
,
__le16
psm
,
struct
sk_buff
*
skb
)
{
struct
sock
*
sk
;
struct
l2cap_chan
*
chan
;
sk
=
l2cap_get_sock
_by_psm
(
0
,
psm
,
conn
->
src
);
if
(
!
sk
)
chan
=
l2cap_global_chan
_by_psm
(
0
,
psm
,
conn
->
src
);
if
(
!
chan
)
goto
drop
;
sk
=
chan
->
sk
;
bh_lock_sock
(
sk
);
BT_DBG
(
"sk %p, len %d"
,
sk
,
skb
->
len
);
...
...
@@ -3715,11 +3789,14 @@ static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, str
static
inline
int
l2cap_att_channel
(
struct
l2cap_conn
*
conn
,
__le16
cid
,
struct
sk_buff
*
skb
)
{
struct
sock
*
sk
;
struct
l2cap_chan
*
chan
;
sk
=
l2cap_get_sock
_by_scid
(
0
,
cid
,
conn
->
src
);
if
(
!
sk
)
chan
=
l2cap_global_chan
_by_scid
(
0
,
cid
,
conn
->
src
);
if
(
!
chan
)
goto
drop
;
sk
=
chan
->
sk
;
bh_lock_sock
(
sk
);
BT_DBG
(
"sk %p, len %d"
,
sk
,
skb
->
len
);
...
...
@@ -3786,8 +3863,7 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
static
int
l2cap_connect_ind
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
,
u8
type
)
{
int
exact
=
0
,
lm1
=
0
,
lm2
=
0
;
register
struct
sock
*
sk
;
struct
hlist_node
*
node
;
struct
l2cap_chan
*
c
;
if
(
type
!=
ACL_LINK
)
return
-
EINVAL
;
...
...
@@ -3795,25 +3871,25 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
BT_DBG
(
"hdev %s, bdaddr %s"
,
hdev
->
name
,
batostr
(
bdaddr
));
/* Find listening sockets and check their link_mode */
read_lock
(
&
l2cap_sk_list
.
lock
);
sk_for_each
(
sk
,
node
,
&
l2cap_sk_list
.
head
)
{
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
read_lock
(
&
chan_list_
lock
);
list_for_each_entry
(
c
,
&
chan_list
,
global_l
)
{
struct
sock
*
sk
=
c
->
sk
;
if
(
sk
->
sk_state
!=
BT_LISTEN
)
continue
;
if
(
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
&
hdev
->
bdaddr
))
{
lm1
|=
HCI_LM_ACCEPT
;
if
(
c
han
->
role_switch
)
if
(
c
->
role_switch
)
lm1
|=
HCI_LM_MASTER
;
exact
++
;
}
else
if
(
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
BDADDR_ANY
))
{
lm2
|=
HCI_LM_ACCEPT
;
if
(
c
han
->
role_switch
)
if
(
c
->
role_switch
)
lm2
|=
HCI_LM_MASTER
;
}
}
read_unlock
(
&
l2cap_sk_list
.
lock
);
read_unlock
(
&
chan_list_
lock
);
return
exact
?
lm1
:
lm2
;
}
...
...
@@ -4066,25 +4142,22 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
static
int
l2cap_debugfs_show
(
struct
seq_file
*
f
,
void
*
p
)
{
struct
sock
*
sk
;
struct
hlist_node
*
node
;
struct
l2cap_chan
*
c
;
read_lock_bh
(
&
l2cap_sk_list
.
lock
);
read_lock_bh
(
&
chan_list_
lock
);
sk_for_each
(
sk
,
node
,
&
l2cap_sk_list
.
head
)
{
struct
l2cap_pinfo
*
pi
=
l2cap_pi
(
sk
);
struct
l2cap_chan
*
chan
=
pi
->
chan
;
list_for_each_entry
(
c
,
&
chan_list
,
global_l
)
{
struct
sock
*
sk
=
c
->
sk
;
seq_printf
(
f
,
"%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d
\n
"
,
batostr
(
&
bt_sk
(
sk
)
->
src
),
batostr
(
&
bt_sk
(
sk
)
->
dst
),
sk
->
sk_state
,
__le16_to_cpu
(
chan
->
psm
),
chan
->
scid
,
chan
->
dcid
,
chan
->
imtu
,
chan
->
omtu
,
chan
->
sec_level
,
chan
->
mode
);
sk
->
sk_state
,
__le16_to_cpu
(
c
->
psm
),
c
->
scid
,
c
->
dcid
,
c
->
imtu
,
c
->
omtu
,
c
->
sec_level
,
c
->
mode
);
}
read_unlock_bh
(
&
l2cap_sk_list
.
lock
);
read_unlock_bh
(
&
chan_list_
lock
);
return
0
;
}
...
...
net/bluetooth/l2cap_sock.c
View file @
15cb3096
...
...
@@ -78,22 +78,6 @@ void l2cap_sock_clear_timer(struct sock *sk)
sk_stop_timer
(
sk
,
&
sk
->
sk_timer
);
}
static
struct
sock
*
__l2cap_get_sock_by_addr
(
__le16
psm
,
bdaddr_t
*
src
)
{
struct
sock
*
sk
;
struct
hlist_node
*
node
;
sk_for_each
(
sk
,
node
,
&
l2cap_sk_list
.
head
)
{
struct
l2cap_chan
*
chan
=
l2cap_pi
(
sk
)
->
chan
;
if
(
chan
->
sport
==
psm
&&
!
bacmp
(
&
bt_sk
(
sk
)
->
src
,
src
))
goto
found
;
}
sk
=
NULL
;
found:
return
sk
;
}
static
int
l2cap_sock_bind
(
struct
socket
*
sock
,
struct
sockaddr
*
addr
,
int
alen
)
{
struct
sock
*
sk
=
sock
->
sk
;
...
...
@@ -136,26 +120,20 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
}
}
write_lock_bh
(
&
l2cap_sk_list
.
lock
);
if
(
la
.
l2_cid
)
err
=
l2cap_add_scid
(
chan
,
la
.
l2_cid
);
else
err
=
l2cap_add_psm
(
chan
,
&
la
.
l2_bdaddr
,
la
.
l2_psm
);
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
);
chan
->
psm
=
la
.
l2_psm
;
chan
->
sport
=
la
.
l2_psm
;
sk
->
sk_state
=
BT_BOUND
;
if
(
err
<
0
)
goto
done
;
if
(
__le16_to_cpu
(
la
.
l2_psm
)
==
0x0001
||
__le16_to_cpu
(
la
.
l2_psm
)
==
0x0003
)
chan
->
sec_level
=
BT_SECURITY_SDP
;
}
if
(
la
.
l2_cid
)
chan
->
scid
=
la
.
l2_cid
;
write_unlock_bh
(
&
l2cap_sk_list
.
lock
);
bacpy
(
&
bt_sk
(
sk
)
->
src
,
&
la
.
l2_bdaddr
);
sk
->
sk_state
=
BT_BOUND
;
done:
release_sock
(
sk
);
...
...
@@ -278,28 +256,6 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
goto
done
;
}
if
(
!
chan
->
psm
&&
!
chan
->
scid
)
{
bdaddr_t
*
src
=
&
bt_sk
(
sk
)
->
src
;
u16
psm
;
err
=
-
EINVAL
;
write_lock_bh
(
&
l2cap_sk_list
.
lock
);
for
(
psm
=
0x1001
;
psm
<
0x1100
;
psm
+=
2
)
if
(
!
__l2cap_get_sock_by_addr
(
cpu_to_le16
(
psm
),
src
))
{
chan
->
psm
=
cpu_to_le16
(
psm
);
chan
->
sport
=
cpu_to_le16
(
psm
);
err
=
0
;
break
;
}
write_unlock_bh
(
&
l2cap_sk_list
.
lock
);
if
(
err
<
0
)
goto
done
;
}
sk
->
sk_max_ack_backlog
=
backlog
;
sk
->
sk_ack_backlog
=
0
;
sk
->
sk_state
=
BT_LISTEN
;
...
...
@@ -852,8 +808,7 @@ void l2cap_sock_kill(struct sock *sk)
/* Kill poor orphan */
l2cap_chan_free
(
l2cap_pi
(
sk
)
->
chan
);
bt_sock_unlink
(
&
l2cap_sk_list
,
sk
);
l2cap_chan_destroy
(
l2cap_pi
(
sk
)
->
chan
);
sock_set_flag
(
sk
,
SOCK_DEAD
);
sock_put
(
sk
);
}
...
...
@@ -1069,7 +1024,6 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, g
setup_timer
(
&
sk
->
sk_timer
,
l2cap_sock_timeout
,
(
unsigned
long
)
sk
);
bt_sock_link
(
&
l2cap_sk_list
,
sk
);
return
sk
;
}
...
...
@@ -1096,7 +1050,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
if
(
!
sk
)
return
-
ENOMEM
;
chan
=
l2cap_chan_
alloc
(
sk
);
chan
=
l2cap_chan_
create
(
sk
);
if
(
!
chan
)
{
l2cap_sock_kill
(
sk
);
return
-
ENOMEM
;
...
...
net/bluetooth/mgmt.c
View file @
15cb3096
...
...
@@ -1033,6 +1033,9 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
}
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
cp
->
bdaddr
);
if
(
!
conn
)
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
LE_LINK
,
&
cp
->
bdaddr
);
if
(
!
conn
)
{
err
=
cmd_status
(
sk
,
index
,
MGMT_OP_DISCONNECT
,
ENOTCONN
);
goto
failed
;
...
...
net/bluetooth/rfcomm/core.c
View file @
15cb3096
...
...
@@ -2096,7 +2096,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
if
(
!
test_and_clear_bit
(
RFCOMM_AUTH_PENDING
,
&
d
->
flags
))
continue
;
if
(
!
status
)
if
(
!
status
&&
hci_conn_check_secure
(
conn
,
d
->
sec_level
)
)
set_bit
(
RFCOMM_AUTH_ACCEPT
,
&
d
->
flags
);
else
set_bit
(
RFCOMM_AUTH_REJECT
,
&
d
->
flags
);
...
...
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