summaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/af_bluetooth.c2
-rw-r--r--net/bluetooth/hci_conn.c21
-rw-r--r--net/bluetooth/hci_core.c3
-rw-r--r--net/bluetooth/hci_event.c11
-rw-r--r--net/bluetooth/l2cap.c34
-rw-r--r--net/bluetooth/sco.c2
6 files changed, 55 insertions, 18 deletions
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 1edfdf4c095..f6348e078aa 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -49,7 +49,7 @@
#define BT_DBG(D...)
#endif
-#define VERSION "2.12"
+#define VERSION "2.13"
/* Bluetooth sockets */
#define BT_MAX_PROTO 8
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index ca8d05245ca..b7002429f15 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -330,7 +330,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)
+struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type)
{
struct hci_conn *acl;
struct hci_conn *sco;
@@ -344,8 +344,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
hci_conn_hold(acl);
- if (acl->state == BT_OPEN || acl->state == BT_CLOSED)
+ if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
+ acl->auth_type = auth_type;
hci_acl_connect(acl);
+ }
if (type == ACL_LINK)
return acl;
@@ -374,6 +376,19 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
}
EXPORT_SYMBOL(hci_connect);
+/* Check link security requirement */
+int hci_conn_check_link_mode(struct hci_conn *conn)
+{
+ BT_DBG("conn %p", conn);
+
+ if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0 &&
+ !(conn->link_mode & HCI_LM_ENCRYPT))
+ return 0;
+
+ return 1;
+}
+EXPORT_SYMBOL(hci_conn_check_link_mode);
+
/* Authenticate remote device */
int hci_conn_auth(struct hci_conn *conn)
{
@@ -381,7 +396,7 @@ int hci_conn_auth(struct hci_conn *conn)
if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) {
if (!(conn->auth_type & 0x01)) {
- conn->auth_type = HCI_AT_GENERAL_BONDING_MITM;
+ conn->auth_type |= 0x01;
conn->link_mode &= ~HCI_LM_AUTH;
}
}
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index f5b21cb9369..278a3ace14f 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -164,6 +164,9 @@ static inline int hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *
{
int ret;
+ if (!test_bit(HCI_UP, &hdev->flags))
+ return -ENETDOWN;
+
/* Serialize all requests */
hci_req_lock(hdev);
ret = __hci_request(hdev, req, opt, timeout);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0e3db289f4b..ad7a553d771 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1605,14 +1605,11 @@ 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) {
- if (conn->out) {
- struct hci_cp_auth_requested cp;
- cp.handle = ev->handle;
- hci_send_cmd(hdev,
- HCI_OP_AUTH_REQUESTED,
+ conn->ssp_mode > 0 && conn->out) {
+ struct hci_cp_auth_requested cp;
+ cp.handle = ev->handle;
+ hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
sizeof(cp), &cp);
- }
} else {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 3396d5bdef1..9610a9c85b9 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -55,7 +55,7 @@
#define BT_DBG(D...)
#endif
-#define VERSION "2.10"
+#define VERSION "2.11"
static u32 l2cap_feat_mask = 0x0000;
@@ -778,6 +778,7 @@ static int l2cap_do_connect(struct sock *sk)
struct l2cap_conn *conn;
struct hci_conn *hcon;
struct hci_dev *hdev;
+ __u8 auth_type;
int err = 0;
BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), l2cap_pi(sk)->psm);
@@ -789,7 +790,21 @@ static int l2cap_do_connect(struct sock *sk)
err = -ENOMEM;
- hcon = hci_connect(hdev, ACL_LINK, dst);
+ 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))
+ 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
+ auth_type = HCI_AT_GENERAL_BONDING;
+ }
+
+ hcon = hci_connect(hdev, ACL_LINK, dst, auth_type);
if (!hcon)
goto done;
@@ -1553,10 +1568,10 @@ 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 sock *sk, *parent;
- int result, status = 0;
+ int result, status = L2CAP_CS_NO_INFO;
u16 dcid = 0, scid = __le16_to_cpu(req->scid);
- __le16 psm = req->psm;
+ __le16 psm = req->psm;
BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
@@ -1567,6 +1582,13 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
goto sendresp;
}
+ /* Check if the ACL is secure enough (if not SDP) */
+ if (psm != cpu_to_le16(0x0001) &&
+ !hci_conn_check_link_mode(conn->hcon)) {
+ result = L2CAP_CR_SEC_BLOCK;
+ goto response;
+ }
+
result = L2CAP_CR_NO_MEM;
/* Check for backlog size */
@@ -2224,7 +2246,7 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)
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(0);
+ rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
L2CAP_CONN_RSP, sizeof(rsp), &rsp);
}
@@ -2296,7 +2318,7 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
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(0);
+ rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
L2CAP_CONN_RSP, sizeof(rsp), &rsp);
}
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index a16011fedc1..0cc91e6da76 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -200,7 +200,7 @@ static int sco_connect(struct sock *sk)
else
type = SCO_LINK;
- hcon = hci_connect(hdev, type, dst);
+ hcon = hci_connect(hdev, type, dst, HCI_AT_NO_BONDING);
if (!hcon)
goto done;