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
bb8f2cb2
Commit
bb8f2cb2
authored
Sep 27, 2011
by
John W. Linville
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
git://github.com/padovan/bluetooth-next
parents
ed46fdfc
ab0ff76d
Changes
14
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
538 additions
and
287 deletions
+538
-287
include/net/bluetooth/hci.h
include/net/bluetooth/hci.h
+10
-0
include/net/bluetooth/hci_core.h
include/net/bluetooth/hci_core.h
+21
-4
include/net/bluetooth/l2cap.h
include/net/bluetooth/l2cap.h
+1
-7
include/net/bluetooth/mgmt.h
include/net/bluetooth/mgmt.h
+16
-0
include/net/bluetooth/smp.h
include/net/bluetooth/smp.h
+17
-0
net/bluetooth/hci_conn.c
net/bluetooth/hci_conn.c
+1
-1
net/bluetooth/hci_core.c
net/bluetooth/hci_core.c
+23
-34
net/bluetooth/hci_event.c
net/bluetooth/hci_event.c
+8
-8
net/bluetooth/hci_sock.c
net/bluetooth/hci_sock.c
+16
-2
net/bluetooth/hci_sysfs.c
net/bluetooth/hci_sysfs.c
+2
-0
net/bluetooth/hidp/core.c
net/bluetooth/hidp/core.c
+3
-0
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_core.c
+14
-4
net/bluetooth/mgmt.c
net/bluetooth/mgmt.c
+152
-60
net/bluetooth/smp.c
net/bluetooth/smp.c
+254
-167
No files found.
include/net/bluetooth/hci.h
View file @
bb8f2cb2
...
...
@@ -716,6 +716,16 @@ struct hci_rp_read_bd_addr {
bdaddr_t
bdaddr
;
}
__packed
;
#define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY 0x0c1c
struct
hci_cp_write_page_scan_activity
{
__le16
interval
;
__le16
window
;
}
__packed
;
#define HCI_OP_WRITE_PAGE_SCAN_TYPE 0x0c47
#define PAGE_SCAN_TYPE_STANDARD 0x00
#define PAGE_SCAN_TYPE_INTERLACED 0x01
#define HCI_OP_LE_SET_EVENT_MASK 0x2001
struct
hci_cp_le_set_event_mask
{
__u8
mask
[
8
];
...
...
include/net/bluetooth/hci_core.h
View file @
bb8f2cb2
...
...
@@ -195,8 +195,6 @@ struct hci_dev {
__u16
init_last_cmd
;
struct
crypto_blkcipher
*
tfm
;
struct
inquiry_cache
inq_cache
;
struct
hci_conn_hash
conn_hash
;
struct
list_head
blacklist
;
...
...
@@ -348,6 +346,7 @@ enum {
HCI_CONN_RSWITCH_PEND
,
HCI_CONN_MODE_CHANGE_PEND
,
HCI_CONN_SCO_SETUP_PEND
,
HCI_CONN_LE_SMP_PEND
,
};
static
inline
void
hci_conn_hash_init
(
struct
hci_dev
*
hdev
)
...
...
@@ -395,6 +394,22 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
}
}
static
inline
unsigned
int
hci_conn_num
(
struct
hci_dev
*
hdev
,
__u8
type
)
{
struct
hci_conn_hash
*
h
=
&
hdev
->
conn_hash
;
switch
(
type
)
{
case
ACL_LINK
:
return
h
->
acl_num
;
case
LE_LINK
:
return
h
->
le_num
;
case
SCO_LINK
:
case
ESCO_LINK
:
return
h
->
sco_num
;
default:
return
0
;
}
}
static
inline
struct
hci_conn
*
hci_conn_hash_lookup_handle
(
struct
hci_dev
*
hdev
,
__u16
handle
)
{
...
...
@@ -475,7 +490,7 @@ static inline void hci_conn_put(struct hci_conn *conn)
{
if
(
atomic_dec_and_test
(
&
conn
->
refcnt
))
{
unsigned
long
timeo
;
if
(
conn
->
type
==
ACL_LINK
)
{
if
(
conn
->
type
==
ACL_LINK
||
conn
->
type
==
LE_LINK
)
{
del_timer
(
&
conn
->
idle_timer
);
if
(
conn
->
state
==
BT_CONNECTED
)
{
timeo
=
msecs_to_jiffies
(
conn
->
disc_timeout
);
...
...
@@ -838,7 +853,7 @@ int mgmt_powered(u16 index, u8 powered);
int
mgmt_discoverable
(
u16
index
,
u8
discoverable
);
int
mgmt_connectable
(
u16
index
,
u8
connectable
);
int
mgmt_new_key
(
u16
index
,
struct
link_key
*
key
,
u8
persistent
);
int
mgmt_connected
(
u16
index
,
bdaddr_t
*
bdaddr
);
int
mgmt_connected
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
link_type
);
int
mgmt_disconnected
(
u16
index
,
bdaddr_t
*
bdaddr
);
int
mgmt_disconnect_failed
(
u16
index
);
int
mgmt_connect_failed
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
status
);
...
...
@@ -858,6 +873,8 @@ int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
u8
*
eir
);
int
mgmt_remote_name
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
*
name
);
int
mgmt_discovering
(
u16
index
,
u8
discovering
);
int
mgmt_device_blocked
(
u16
index
,
bdaddr_t
*
bdaddr
);
int
mgmt_device_unblocked
(
u16
index
,
bdaddr_t
*
bdaddr
);
/* HCI info for socket */
#define hci_pi(sk) ((struct hci_pinfo *) sk)
...
...
include/net/bluetooth/l2cap.h
View file @
bb8f2cb2
...
...
@@ -409,14 +409,8 @@ struct l2cap_conn {
__u8
disc_reason
;
__u8
preq
[
7
];
/* SMP Pairing Request */
__u8
prsp
[
7
];
/* SMP Pairing Response */
__u8
prnd
[
16
];
/* SMP Pairing Random */
__u8
pcnf
[
16
];
/* SMP Pairing Confirm */
__u8
tk
[
16
];
/* SMP Temporary Key */
__u8
smp_key_size
;
struct
timer_list
security_timer
;
struct
smp_chan
*
smp_chan
;
struct
list_head
chan_l
;
rwlock_t
chan_lock
;
...
...
include/net/bluetooth/mgmt.h
View file @
bb8f2cb2
...
...
@@ -211,6 +211,11 @@ struct mgmt_cp_unblock_device {
bdaddr_t
bdaddr
;
}
__packed
;
#define MGMT_OP_SET_FAST_CONNECTABLE 0x001F
struct
mgmt_cp_set_fast_connectable
{
__u8
enable
;
}
__packed
;
#define MGMT_EV_CMD_COMPLETE 0x0001
struct
mgmt_ev_cmd_complete
{
__le16
opcode
;
...
...
@@ -249,6 +254,7 @@ struct mgmt_ev_new_key {
#define MGMT_EV_CONNECTED 0x000B
struct
mgmt_ev_connected
{
bdaddr_t
bdaddr
;
__u8
link_type
;
}
__packed
;
#define MGMT_EV_DISCONNECTED 0x000C
...
...
@@ -301,3 +307,13 @@ struct mgmt_ev_remote_name {
}
__packed
;
#define MGMT_EV_DISCOVERING 0x0014
#define MGMT_EV_DEVICE_BLOCKED 0x0015
struct
mgmt_ev_device_blocked
{
bdaddr_t
bdaddr
;
}
__packed
;
#define MGMT_EV_DEVICE_UNBLOCKED 0x0016
struct
mgmt_ev_device_unblocked
{
bdaddr_t
bdaddr
;
}
__packed
;
include/net/bluetooth/smp.h
View file @
bb8f2cb2
...
...
@@ -115,9 +115,26 @@ struct smp_cmd_security_req {
#define SMP_MIN_ENC_KEY_SIZE 7
#define SMP_MAX_ENC_KEY_SIZE 16
struct
smp_chan
{
struct
l2cap_conn
*
conn
;
u8
preq
[
7
];
/* SMP Pairing Request */
u8
prsp
[
7
];
/* SMP Pairing Response */
u8
prnd
[
16
];
/* SMP Pairing Random (local) */
u8
rrnd
[
16
];
/* SMP Pairing Random (remote) */
u8
pcnf
[
16
];
/* SMP Pairing Confirm */
u8
tk
[
16
];
/* SMP Temporary Key */
u8
smp_key_size
;
struct
crypto_blkcipher
*
tfm
;
struct
work_struct
confirm
;
struct
work_struct
random
;
};
/* SMP Commands */
int
smp_conn_security
(
struct
l2cap_conn
*
conn
,
__u8
sec_level
);
int
smp_sig_channel
(
struct
l2cap_conn
*
conn
,
struct
sk_buff
*
skb
);
int
smp_distribute_keys
(
struct
l2cap_conn
*
conn
,
__u8
force
);
void
smp_chan_destroy
(
struct
l2cap_conn
*
conn
);
#endif
/* __SMP_H */
net/bluetooth/hci_conn.c
View file @
bb8f2cb2
...
...
@@ -218,7 +218,7 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
cp
.
handle
=
cpu_to_le16
(
conn
->
handle
);
memcpy
(
cp
.
ltk
,
ltk
,
sizeof
(
cp
.
ltk
));
cp
.
ediv
=
ediv
;
memcpy
(
cp
.
rand
,
rand
,
sizeof
(
rand
));
memcpy
(
cp
.
rand
,
rand
,
sizeof
(
cp
.
rand
));
hci_send_cmd
(
hdev
,
HCI_OP_LE_START_ENC
,
sizeof
(
cp
),
&
cp
);
}
...
...
net/bluetooth/hci_core.c
View file @
bb8f2cb2
...
...
@@ -1312,59 +1312,41 @@ int hci_blacklist_clear(struct hci_dev *hdev)
int
hci_blacklist_add
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
)
{
struct
bdaddr_list
*
entry
;
int
err
;
if
(
bacmp
(
bdaddr
,
BDADDR_ANY
)
==
0
)
return
-
EBADF
;
hci_dev_lock_bh
(
hdev
);
if
(
hci_blacklist_lookup
(
hdev
,
bdaddr
))
{
err
=
-
EEXIST
;
goto
err
;
}
if
(
hci_blacklist_lookup
(
hdev
,
bdaddr
))
return
-
EEXIST
;
entry
=
kzalloc
(
sizeof
(
struct
bdaddr_list
),
GFP_KERNEL
);
if
(
!
entry
)
{
err
=
-
ENOMEM
;
goto
err
;
}
if
(
!
entry
)
return
-
ENOMEM
;
bacpy
(
&
entry
->
bdaddr
,
bdaddr
);
list_add
(
&
entry
->
list
,
&
hdev
->
blacklist
);
err
=
0
;
err:
hci_dev_unlock_bh
(
hdev
);
return
err
;
return
mgmt_device_blocked
(
hdev
->
id
,
bdaddr
);
}
int
hci_blacklist_del
(
struct
hci_dev
*
hdev
,
bdaddr_t
*
bdaddr
)
{
struct
bdaddr_list
*
entry
;
int
err
=
0
;
hci_dev_lock_bh
(
hdev
);
if
(
bacmp
(
bdaddr
,
BDADDR_ANY
)
==
0
)
{
hci_blacklist_clear
(
hdev
);
goto
done
;
return
hci_blacklist_clear
(
hdev
);
}
entry
=
hci_blacklist_lookup
(
hdev
,
bdaddr
);
if
(
!
entry
)
{
err
=
-
ENOENT
;
goto
done
;
return
-
ENOENT
;
}
list_del
(
&
entry
->
list
);
kfree
(
entry
);
done:
hci_dev_unlock_bh
(
hdev
);
return
err
;
return
mgmt_device_unblocked
(
hdev
->
id
,
bdaddr
);
}
static
void
hci_clear_adv_cache
(
unsigned
long
arg
)
...
...
@@ -1523,11 +1505,6 @@ int hci_register_dev(struct hci_dev *hdev)
if
(
!
hdev
->
workqueue
)
goto
nomem
;
hdev
->
tfm
=
crypto_alloc_blkcipher
(
"ecb(aes)"
,
0
,
CRYPTO_ALG_ASYNC
);
if
(
IS_ERR
(
hdev
->
tfm
))
BT_INFO
(
"Failed to load transform for ecb(aes): %ld"
,
PTR_ERR
(
hdev
->
tfm
));
hci_register_sysfs
(
hdev
);
hdev
->
rfkill
=
rfkill_alloc
(
hdev
->
name
,
&
hdev
->
dev
,
...
...
@@ -1576,9 +1553,6 @@ int hci_unregister_dev(struct hci_dev *hdev)
!
test_bit
(
HCI_SETUP
,
&
hdev
->
flags
))
mgmt_index_removed
(
hdev
->
id
);
if
(
!
IS_ERR
(
hdev
->
tfm
))
crypto_free_blkcipher
(
hdev
->
tfm
);
hci_notify
(
hdev
,
HCI_DEV_UNREG
);
if
(
hdev
->
rfkill
)
{
...
...
@@ -2074,6 +2048,9 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
min
=
c
->
sent
;
conn
=
c
;
}
if
(
hci_conn_num
(
hdev
,
type
)
==
num
)
break
;
}
if
(
conn
)
{
...
...
@@ -2131,6 +2108,9 @@ static inline void hci_sched_acl(struct hci_dev *hdev)
BT_DBG
(
"%s"
,
hdev
->
name
);
if
(
!
hci_conn_num
(
hdev
,
ACL_LINK
))
return
;
if
(
!
test_bit
(
HCI_RAW
,
&
hdev
->
flags
))
{
/* ACL tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */
...
...
@@ -2162,6 +2142,9 @@ static inline void hci_sched_sco(struct hci_dev *hdev)
BT_DBG
(
"%s"
,
hdev
->
name
);
if
(
!
hci_conn_num
(
hdev
,
SCO_LINK
))
return
;
while
(
hdev
->
sco_cnt
&&
(
conn
=
hci_low_sent
(
hdev
,
SCO_LINK
,
&
quote
)))
{
while
(
quote
--
&&
(
skb
=
skb_dequeue
(
&
conn
->
data_q
)))
{
BT_DBG
(
"skb %p len %d"
,
skb
,
skb
->
len
);
...
...
@@ -2182,6 +2165,9 @@ static inline void hci_sched_esco(struct hci_dev *hdev)
BT_DBG
(
"%s"
,
hdev
->
name
);
if
(
!
hci_conn_num
(
hdev
,
ESCO_LINK
))
return
;
while
(
hdev
->
sco_cnt
&&
(
conn
=
hci_low_sent
(
hdev
,
ESCO_LINK
,
&
quote
)))
{
while
(
quote
--
&&
(
skb
=
skb_dequeue
(
&
conn
->
data_q
)))
{
BT_DBG
(
"skb %p len %d"
,
skb
,
skb
->
len
);
...
...
@@ -2202,6 +2188,9 @@ static inline void hci_sched_le(struct hci_dev *hdev)
BT_DBG
(
"%s"
,
hdev
->
name
);
if
(
!
hci_conn_num
(
hdev
,
LE_LINK
))
return
;
if
(
!
test_bit
(
HCI_RAW
,
&
hdev
->
flags
))
{
/* LE tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */
...
...
net/bluetooth/hci_event.c
View file @
bb8f2cb2
...
...
@@ -898,16 +898,15 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
if
(
!
cp
)
return
;
hci_dev_lock
(
hdev
);
if
(
cp
->
enable
==
0x01
)
{
del_timer
(
&
hdev
->
adv_timer
);
hci_dev_lock
(
hdev
);
hci_adv_entries_clear
(
hdev
);
hci_dev_unlock
(
hdev
);
}
else
if
(
cp
->
enable
==
0x00
)
{
mod_timer
(
&
hdev
->
adv_timer
,
jiffies
+
ADV_CLEAR_TIMEOUT
);
}
hci_dev_unlock
(
hdev
);
}
static
void
hci_cc_le_ltk_reply
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
...
...
@@ -1103,9 +1102,10 @@ static int hci_outgoing_auth_needed(struct hci_dev *hdev,
return
0
;
/* Only request authentication for SSP connections or non-SSP
* devices with sec_level HIGH */
* devices with sec_level HIGH
or if MITM protection is requested
*/
if
(
!
(
hdev
->
ssp_mode
>
0
&&
conn
->
ssp_mode
>
0
)
&&
conn
->
pending_sec_level
!=
BT_SECURITY_HIGH
)
conn
->
pending_sec_level
!=
BT_SECURITY_HIGH
&&
!
(
conn
->
auth_type
&
0x01
))
return
0
;
return
1
;
...
...
@@ -1412,7 +1412,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
conn
->
state
=
BT_CONFIG
;
hci_conn_hold
(
conn
);
conn
->
disc_timeout
=
HCI_DISCONN_TIMEOUT
;
mgmt_connected
(
hdev
->
id
,
&
ev
->
bdaddr
);
mgmt_connected
(
hdev
->
id
,
&
ev
->
bdaddr
,
conn
->
type
);
}
else
conn
->
state
=
BT_CONNECTED
;
...
...
@@ -2816,7 +2816,7 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff
goto
unlock
;
}
mgmt_connected
(
hdev
->
id
,
&
ev
->
bdaddr
);
mgmt_connected
(
hdev
->
id
,
&
ev
->
bdaddr
,
conn
->
type
);
conn
->
sec_level
=
BT_SECURITY_LOW
;
conn
->
handle
=
__le16_to_cpu
(
ev
->
handle
);
...
...
net/bluetooth/hci_sock.c
View file @
bb8f2cb2
...
...
@@ -183,21 +183,35 @@ static int hci_sock_release(struct socket *sock)
static
int
hci_sock_blacklist_add
(
struct
hci_dev
*
hdev
,
void
__user
*
arg
)
{
bdaddr_t
bdaddr
;
int
err
;
if
(
copy_from_user
(
&
bdaddr
,
arg
,
sizeof
(
bdaddr
)))
return
-
EFAULT
;
return
hci_blacklist_add
(
hdev
,
&
bdaddr
);
hci_dev_lock_bh
(
hdev
);
err
=
hci_blacklist_add
(
hdev
,
&
bdaddr
);
hci_dev_unlock_bh
(
hdev
);
return
err
;
}
static
int
hci_sock_blacklist_del
(
struct
hci_dev
*
hdev
,
void
__user
*
arg
)
{
bdaddr_t
bdaddr
;
int
err
;
if
(
copy_from_user
(
&
bdaddr
,
arg
,
sizeof
(
bdaddr
)))
return
-
EFAULT
;
return
hci_blacklist_del
(
hdev
,
&
bdaddr
);
hci_dev_lock_bh
(
hdev
);
err
=
hci_blacklist_del
(
hdev
,
&
bdaddr
);
hci_dev_unlock_bh
(
hdev
);
return
err
;
}
/* Ioctls that require bound socket */
...
...
net/bluetooth/hci_sysfs.c
View file @
bb8f2cb2
...
...
@@ -23,6 +23,8 @@ static inline char *link_typetostr(int type)
return
"SCO"
;
case
ESCO_LINK
:
return
"eSCO"
;
case
LE_LINK
:
return
"LE"
;
default:
return
"UNKNOWN"
;
}
...
...
net/bluetooth/hidp/core.c
View file @
bb8f2cb2
...
...
@@ -872,6 +872,9 @@ static int hidp_start(struct hid_device *hid)
struct
hidp_session
*
session
=
hid
->
driver_data
;
struct
hid_report
*
report
;
if
(
hid
->
quirks
&
HID_QUIRK_NO_INIT_REPORTS
)
return
0
;
list_for_each_entry
(
report
,
&
hid
->
report_enum
[
HID_INPUT_REPORT
].
report_list
,
list
)
hidp_send_report
(
session
,
report
);
...
...
net/bluetooth/l2cap_core.c
View file @
bb8f2cb2
...
...
@@ -907,6 +907,9 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
if
(
!
conn
->
hcon
->
out
&&
conn
->
hcon
->
type
==
LE_LINK
)
l2cap_le_conn_ready
(
conn
);
if
(
conn
->
hcon
->
out
&&
conn
->
hcon
->
type
==
LE_LINK
)
smp_conn_security
(
conn
,
conn
->
hcon
->
pending_sec_level
);
read_lock
(
&
conn
->
chan_lock
);
list_for_each_entry
(
chan
,
&
conn
->
chan_l
,
list
)
{
...
...
@@ -986,8 +989,10 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
if
(
conn
->
info_state
&
L2CAP_INFO_FEAT_MASK_REQ_SENT
)
del_timer_sync
(
&
conn
->
info_timer
);
if
(
test_
bit
(
HCI_CONN_ENCRYPT_PEND
,
&
hcon
->
pend
))
if
(
test_
and_clear_bit
(
HCI_CONN_LE_SMP_PEND
,
&
hcon
->
pend
))
{
del_timer
(
&
conn
->
security_timer
);
smp_chan_destroy
(
conn
);
}
hcon
->
l2cap_data
=
NULL
;
kfree
(
conn
);
...
...
@@ -1519,7 +1524,9 @@ struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *m
return
skb
;
}
struct
sk_buff
*
l2cap_create_iframe_pdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
,
u16
control
,
u16
sdulen
)
static
struct
sk_buff
*
l2cap_create_iframe_pdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
,
u16
control
,
u16
sdulen
)
{
struct
sock
*
sk
=
chan
->
sk
;
struct
l2cap_conn
*
conn
=
chan
->
conn
;
...
...
@@ -4093,6 +4100,11 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
BT_DBG
(
"conn %p"
,
conn
);
if
(
hcon
->
type
==
LE_LINK
)
{
smp_distribute_keys
(
conn
,
0
);
del_timer
(
&
conn
->
security_timer
);
}
read_lock
(
&
conn
->
chan_lock
);
list_for_each_entry
(
chan
,
&
conn
->
chan_l
,
list
)
{
...
...
@@ -4105,9 +4117,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
if
(
chan
->
scid
==
L2CAP_CID_LE_DATA
)
{
if
(
!
status
&&
encrypt
)
{
chan
->
sec_level
=
hcon
->
sec_level
;
del_timer
(
&
conn
->
security_timer
);
l2cap_chan_ready
(
sk
);
smp_distribute_keys
(
conn
,
0
);
}
bh_unlock_sock
(
sk
);
...
...
net/bluetooth/mgmt.c
View file @
bb8f2cb2
...
...
@@ -908,7 +908,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
struct
hci_dev
*
hdev
;
struct
mgmt_cp_load_keys
*
cp
;
u16
key_count
,
expected_len
;
int
i
,
err
;
int
i
;
cp
=
(
void
*
)
data
;
...
...
@@ -918,9 +918,9 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
key_count
=
get_unaligned_le16
(
&
cp
->
key_count
);
expected_len
=
sizeof
(
*
cp
)
+
key_count
*
sizeof
(
struct
mgmt_key_info
);
if
(
expected_len
>
len
)
{
BT_ERR
(
"load_keys: expected
at least
%u bytes, got %u bytes"
,
expected_len
,
len
);
if
(
expected_len
!=
len
)
{
BT_ERR
(
"load_keys: expected %u bytes, got %u bytes"
,
len
,
expected_
len
);
return
-
EINVAL
;
}
...
...
@@ -942,36 +942,17 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
else
clear_bit
(
HCI_DEBUG_KEYS
,
&
hdev
->
flags
);
len
-=
sizeof
(
*
cp
);
i
=
0
;
while
(
i
<
len
)
{
struct
mgmt_key_info
*
key
=
(
void
*
)
cp
->
keys
+
i
;
i
+=
sizeof
(
*
key
)
+
key
->
dlen
;
if
(
key
->
type
==
HCI_LK_SMP_LTK
)
{
struct
key_master_id
*
id
=
(
void
*
)
key
->
data
;
if
(
key
->
dlen
!=
sizeof
(
struct
key_master_id
))
continue
;
hci_add_ltk
(
hdev
,
0
,
&
key
->
bdaddr
,
key
->
pin_len
,
id
->
ediv
,
id
->
rand
,
key
->
val
);
continue
;
}
for
(
i
=
0
;
i
<
key_count
;
i
++
)
{
struct
mgmt_key_info
*
key
=
&
cp
->
keys
[
i
];
hci_add_link_key
(
hdev
,
NULL
,
0
,
&
key
->
bdaddr
,
key
->
val
,
key
->
type
,
key
->
pin_len
);
}
err
=
cmd_complete
(
sk
,
index
,
MGMT_OP_LOAD_KEYS
,
NULL
,
0
);
hci_dev_unlock_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
return
0
;
}
static
int
remove_key
(
struct
sock
*
sk
,
u16
index
,
unsigned
char
*
data
,
u16
len
)
...
...
@@ -1347,6 +1328,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
struct
hci_dev
*
hdev
;
struct
mgmt_cp_pair_device
*
cp
;
struct
pending_cmd
*
cmd
;
struct
adv_entry
*
entry
;
u8
sec_level
,
auth_type
;
struct
hci_conn
*
conn
;
int
err
;
...
...
@@ -1364,15 +1346,20 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
hci_dev_lock_bh
(
hdev
);
if
(
cp
->
io_cap
==
0x03
)
{
sec_level
=
BT_SECURITY_MEDIUM
;
if
(
cp
->
io_cap
==
0x03
)
auth_type
=
HCI_AT_DEDICATED_BONDING
;
}
else
{
sec_level
=
BT_SECURITY_HIGH
;
else
auth_type
=
HCI_AT_DEDICATED_BONDING_MITM
;
}
conn
=
hci_connect
(
hdev
,
ACL_LINK
,
&
cp
->
bdaddr
,
sec_level
,
auth_type
);
entry
=
hci_find_adv_entry
(
hdev
,
&
cp
->
bdaddr
);
if
(
entry
)
conn
=
hci_connect
(
hdev
,
LE_LINK
,
&
cp
->
bdaddr
,
sec_level
,
auth_type
);
else
conn
=
hci_connect
(
hdev
,
ACL_LINK
,
&
cp
->
bdaddr
,
sec_level
,
auth_type
);
if
(
IS_ERR
(
conn
))
{
err
=
PTR_ERR
(
conn
);
goto
unlock
;
...
...
@@ -1391,7 +1378,10 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
goto
unlock
;
}
/* For LE, just connecting isn't a proof that the pairing finished */
if
(
!
entry
)
conn
->
connect_cfm_cb
=
pairing_complete_cb
;
conn
->
security_cfm_cb
=
pairing_complete_cb
;
conn
->
disconn_cfm_cb
=
pairing_complete_cb
;
conn
->
io_capability
=
cp
->
io_cap
;
...
...
@@ -1689,13 +1679,12 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data,
u16
len
)
{
struct
hci_dev
*
hdev
;
struct
mgmt_cp_block_device
*
cp
;
struct
pending_cmd
*
cmd
;
struct
mgmt_cp_block_device
*
cp
=
(
void
*
)
data
;
int
err
;
BT_DBG
(
"hci%u"
,
index
);
cp
=
(
void
*
)
data
;
if
(
len
!=
sizeof
(
*
cp
))
return
cmd_status
(
sk
,
index
,
MGMT_OP_BLOCK_DEVICE
,
EINVAL
);
...
...
@@ -1705,6 +1694,14 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data,
return
cmd_status
(
sk
,
index
,
MGMT_OP_BLOCK_DEVICE
,
ENODEV
);
hci_dev_lock_bh
(
hdev
);
cmd
=
mgmt_pending_add
(
sk
,
MGMT_OP_BLOCK_DEVICE
,
index
,
NULL
,
0
);
if
(
!
cmd
)
{
err
=
-
ENOMEM
;
goto
failed
;
}
err
=
hci_blacklist_add
(
hdev
,
&
cp
->
bdaddr
);
if
(
err
<
0
)
...
...
@@ -1712,6 +1709,11 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data,
else
err
=
cmd_complete
(
sk
,
index
,
MGMT_OP_BLOCK_DEVICE
,
NULL
,
0
);
mgmt_pending_remove
(
cmd
);
failed:
hci_dev_unlock_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -1721,13 +1723,12 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
u16
len
)
{
struct
hci_dev
*
hdev
;
struct
mgmt_cp_unblock_device
*
cp
;
struct
pending_cmd
*
cmd
;
struct
mgmt_cp_unblock_device
*
cp
=
(
void
*
)
data
;
int
err
;
BT_DBG
(
"hci%u"
,
index
);
cp
=
(
void
*
)
data
;
if
(
len
!=
sizeof
(
*
cp
))
return
cmd_status
(
sk
,
index
,
MGMT_OP_UNBLOCK_DEVICE
,
EINVAL
);
...
...
@@ -1737,6 +1738,14 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
return
cmd_status
(
sk
,
index
,
MGMT_OP_UNBLOCK_DEVICE
,
ENODEV
);
hci_dev_lock_bh
(
hdev
);
cmd
=
mgmt_pending_add
(
sk
,
MGMT_OP_UNBLOCK_DEVICE
,
index
,
NULL
,
0
);
if
(
!
cmd
)
{
err
=
-
ENOMEM
;
goto
failed
;
}
err
=
hci_blacklist_del
(
hdev
,
&
cp
->
bdaddr
);
if
(
err
<
0
)
...
...
@@ -1744,6 +1753,67 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
else
err
=
cmd_complete
(
sk
,
index
,
MGMT_OP_UNBLOCK_DEVICE
,
NULL
,
0
);
mgmt_pending_remove
(
cmd
);
failed:
hci_dev_unlock_bh
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
}
static
int
set_fast_connectable
(
struct
sock
*
sk
,
u16
index
,
unsigned
char
*
data
,
u16
len
)
{
struct
hci_dev
*
hdev
;
struct
mgmt_cp_set_fast_connectable
*
cp
=
(
void
*
)
data
;
struct
hci_cp_write_page_scan_activity
acp
;
u8
type
;
int
err
;
BT_DBG
(
"hci%u"
,
index
);
if
(
len
!=
sizeof
(
*
cp
))
return
cmd_status
(
sk
,
index
,
MGMT_OP_SET_FAST_CONNECTABLE
,
EINVAL
);
hdev
=
hci_dev_get
(
index
);
if
(
!
hdev
)
return
cmd_status
(
sk
,
index
,
MGMT_OP_SET_FAST_CONNECTABLE
,
ENODEV
);
hci_dev_lock
(
hdev
);
if
(
cp
->
enable
)
{
type
=
PAGE_SCAN_TYPE_INTERLACED
;
acp
.
interval
=
0x0024
;
/* 22.5 msec page scan interval */
}
else
{
type
=
PAGE_SCAN_TYPE_STANDARD
;
/* default */
acp
.
interval
=
0x0800
;
/* default 1.28 sec page scan */
}
acp
.
window
=
0x0012
;
/* default 11.25 msec page scan window */
err
=
hci_send_cmd
(
hdev
,
HCI_OP_WRITE_PAGE_SCAN_ACTIVITY
,
sizeof
(
acp
),
&
acp
);
if
(
err
<
0
)
{
err
=
cmd_status
(
sk
,
index
,
MGMT_OP_SET_FAST_CONNECTABLE
,
-
err
);
goto
done
;
}
err
=
hci_send_cmd
(
hdev
,
HCI_OP_WRITE_PAGE_SCAN_TYPE
,
1
,
&
type
);
if
(
err
<
0
)
{
err
=
cmd_status
(
sk
,
index
,
MGMT_OP_SET_FAST_CONNECTABLE
,
-
err
);
goto
done
;
}
err
=
cmd_complete
(
sk
,
index
,
MGMT_OP_SET_FAST_CONNECTABLE
,
NULL
,
0
);
done:
hci_dev_unlock
(
hdev
);
hci_dev_put
(
hdev
);
return
err
;
...
...
@@ -1869,6 +1939,10 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
case
MGMT_OP_UNBLOCK_DEVICE
:
err
=
unblock_device
(
sk
,
index
,
buf
+
sizeof
(
*
hdr
),
len
);
break
;
case
MGMT_OP_SET_FAST_CONNECTABLE
:
err
=
set_fast_connectable
(
sk
,
index
,
buf
+
sizeof
(
*
hdr
),
len
);
break
;
default:
BT_DBG
(
"Unknown op %u"
,
opcode
);
err
=
cmd_status
(
sk
,
index
,
opcode
,
0x01
);
...
...
@@ -1977,35 +2051,25 @@ int mgmt_connectable(u16 index, u8 connectable)
int
mgmt_new_key
(
u16
index
,
struct
link_key
*
key
,
u8
persistent
)
{
struct
mgmt_ev_new_key
*
ev
;
int
err
,
total
;
total
=
sizeof
(
struct
mgmt_ev_new_key
)
+
key
->
dlen
;
ev
=
kzalloc
(
total
,
GFP_ATOMIC
);
if
(
!
ev
)
return
-
ENOMEM
;
struct
mgmt_ev_new_key
ev
;
bacpy
(
&
ev
->
key
.
bdaddr
,
&
key
->
bdaddr
);
ev
->
key
.
type
=
key
->
type
;
memcpy
(
ev
->
key
.
val
,
key
->
val
,
16
);
ev
->
key
.
pin_len
=
key
->
pin_len
;
ev
->
key
.
dlen
=
key
->
dlen
;
ev
->
store_hint
=
persistent
;
memcpy
(
ev
->
key
.
data
,
key
->
data
,
key
->
dlen
);
err
=
mgmt_event
(
MGMT_EV_NEW_KEY
,
index
,
ev
,
total
,
NULL
);
memset
(
&
ev
,
0
,
sizeof
(
ev
));
kfree
(
ev
);
ev
.
store_hint
=
persistent
;
bacpy
(
&
ev
.
key
.
bdaddr
,
&
key
->
bdaddr
);
ev
.
key
.
type
=
key
->
type
;
memcpy
(
ev
.
key
.
val
,
key
->
val
,
16
);
ev
.
key
.
pin_len
=
key
->
pin_len
;
return
err
;
return
mgmt_event
(
MGMT_EV_NEW_KEY
,
index
,
&
ev
,
sizeof
(
ev
),
NULL
)
;
}
int
mgmt_connected
(
u16
index
,
bdaddr_t
*
bdaddr
)
int
mgmt_connected
(
u16
index
,
bdaddr_t
*
bdaddr
,
u8
link_type
)
{
struct
mgmt_ev_connected
ev
;
bacpy
(
&
ev
.
bdaddr
,
bdaddr
);
ev
.
link_type
=
link_type
;
return
mgmt_event
(
MGMT_EV_CONNECTED
,
index
,
&
ev
,
sizeof
(
ev
),
NULL
);
}
...
...
@@ -2260,12 +2324,14 @@ int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
memset
(
&
ev
,
0
,
sizeof
(
ev
));
bacpy
(
&
ev
.
bdaddr
,
bdaddr
);
memcpy
(
ev
.
dev_class
,
dev_class
,
sizeof
(
ev
.
dev_class
));
ev
.
rssi
=
rssi
;
if
(
eir
)
memcpy
(
ev
.
eir
,
eir
,
sizeof
(
ev
.
eir
));
if
(
dev_class
)
memcpy
(
ev
.
dev_class
,
dev_class
,
sizeof
(
ev
.
dev_class
));
return
mgmt_event
(
MGMT_EV_DEVICE_FOUND
,
index
,
&
ev
,
sizeof
(
ev
),
NULL
);
}
...
...
@@ -2286,3 +2352,29 @@ int mgmt_discovering(u16 index, u8 discovering)
return
mgmt_event
(
MGMT_EV_DISCOVERING
,
index
,
&
discovering
,
sizeof
(
discovering
),
NULL
);
}
int
mgmt_device_blocked
(
u16
index
,
bdaddr_t
*
bdaddr
)
{
struct
pending_cmd
*
cmd
;
struct
mgmt_ev_device_blocked
ev
;
cmd
=
mgmt_pending_find
(
MGMT_OP_BLOCK_DEVICE
,
index
);
bacpy
(
&
ev
.
bdaddr
,
bdaddr
);
return
mgmt_event
(
MGMT_EV_DEVICE_BLOCKED
,
index
,
&
ev
,
sizeof
(
ev
),
cmd
?
cmd
->
sk
:
NULL
);
}
int
mgmt_device_unblocked
(
u16
index
,
bdaddr_t
*
bdaddr
)
{
struct
pending_cmd
*
cmd
;
struct
mgmt_ev_device_unblocked
ev
;
cmd
=
mgmt_pending_find
(
MGMT_OP_UNBLOCK_DEVICE
,
index
);
bacpy
(
&
ev
.
bdaddr
,
bdaddr
);
return
mgmt_event
(
MGMT_EV_DEVICE_UNBLOCKED
,
index
,
&
ev
,
sizeof
(
ev
),
cmd
?
cmd
->
sk
:
NULL
);
}
net/bluetooth/smp.c
View file @
bb8f2cb2
This diff is collapsed.
Click to expand it.
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