diff options
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/af_bluetooth.c | 2 | ||||
-rw-r--r-- | net/bluetooth/hci_conn.c | 21 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 3 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 11 | ||||
-rw-r--r-- | net/bluetooth/l2cap.c | 34 | ||||
-rw-r--r-- | net/bluetooth/sco.c | 2 |
6 files changed, 55 insertions, 18 deletions
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 1edfdf4c095b..f6348e078aa4 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -49,7 +49,7 @@ | |||
49 | #define BT_DBG(D...) | 49 | #define BT_DBG(D...) |
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | #define VERSION "2.12" | 52 | #define VERSION "2.13" |
53 | 53 | ||
54 | /* Bluetooth sockets */ | 54 | /* Bluetooth sockets */ |
55 | #define BT_MAX_PROTO 8 | 55 | #define BT_MAX_PROTO 8 |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index ca8d05245ca0..b7002429f152 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -330,7 +330,7 @@ EXPORT_SYMBOL(hci_get_route); | |||
330 | 330 | ||
331 | /* Create SCO or ACL connection. | 331 | /* Create SCO or ACL connection. |
332 | * Device _must_ be locked */ | 332 | * Device _must_ be locked */ |
333 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) | 333 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type) |
334 | { | 334 | { |
335 | struct hci_conn *acl; | 335 | struct hci_conn *acl; |
336 | struct hci_conn *sco; | 336 | struct hci_conn *sco; |
@@ -344,8 +344,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
344 | 344 | ||
345 | hci_conn_hold(acl); | 345 | hci_conn_hold(acl); |
346 | 346 | ||
347 | if (acl->state == BT_OPEN || acl->state == BT_CLOSED) | 347 | if (acl->state == BT_OPEN || acl->state == BT_CLOSED) { |
348 | acl->auth_type = auth_type; | ||
348 | hci_acl_connect(acl); | 349 | hci_acl_connect(acl); |
350 | } | ||
349 | 351 | ||
350 | if (type == ACL_LINK) | 352 | if (type == ACL_LINK) |
351 | return acl; | 353 | return acl; |
@@ -374,6 +376,19 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
374 | } | 376 | } |
375 | EXPORT_SYMBOL(hci_connect); | 377 | EXPORT_SYMBOL(hci_connect); |
376 | 378 | ||
379 | /* Check link security requirement */ | ||
380 | int hci_conn_check_link_mode(struct hci_conn *conn) | ||
381 | { | ||
382 | BT_DBG("conn %p", conn); | ||
383 | |||
384 | if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0 && | ||
385 | !(conn->link_mode & HCI_LM_ENCRYPT)) | ||
386 | return 0; | ||
387 | |||
388 | return 1; | ||
389 | } | ||
390 | EXPORT_SYMBOL(hci_conn_check_link_mode); | ||
391 | |||
377 | /* Authenticate remote device */ | 392 | /* Authenticate remote device */ |
378 | int hci_conn_auth(struct hci_conn *conn) | 393 | int hci_conn_auth(struct hci_conn *conn) |
379 | { | 394 | { |
@@ -381,7 +396,7 @@ int hci_conn_auth(struct hci_conn *conn) | |||
381 | 396 | ||
382 | if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) { | 397 | if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) { |
383 | if (!(conn->auth_type & 0x01)) { | 398 | if (!(conn->auth_type & 0x01)) { |
384 | conn->auth_type = HCI_AT_GENERAL_BONDING_MITM; | 399 | conn->auth_type |= 0x01; |
385 | conn->link_mode &= ~HCI_LM_AUTH; | 400 | conn->link_mode &= ~HCI_LM_AUTH; |
386 | } | 401 | } |
387 | } | 402 | } |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index f5b21cb93699..278a3ace14f6 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 * | |||
164 | { | 164 | { |
165 | int ret; | 165 | int ret; |
166 | 166 | ||
167 | if (!test_bit(HCI_UP, &hdev->flags)) | ||
168 | return -ENETDOWN; | ||
169 | |||
167 | /* Serialize all requests */ | 170 | /* Serialize all requests */ |
168 | hci_req_lock(hdev); | 171 | hci_req_lock(hdev); |
169 | ret = __hci_request(hdev, req, opt, timeout); | 172 | ret = __hci_request(hdev, req, opt, timeout); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0e3db289f4be..ad7a553d7713 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 | |||
1605 | 1605 | ||
1606 | if (conn->state == BT_CONFIG) { | 1606 | if (conn->state == BT_CONFIG) { |
1607 | if (!ev->status && hdev->ssp_mode > 0 && | 1607 | if (!ev->status && hdev->ssp_mode > 0 && |
1608 | conn->ssp_mode > 0) { | 1608 | conn->ssp_mode > 0 && conn->out) { |
1609 | if (conn->out) { | 1609 | struct hci_cp_auth_requested cp; |
1610 | struct hci_cp_auth_requested cp; | 1610 | cp.handle = ev->handle; |
1611 | cp.handle = ev->handle; | 1611 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, |
1612 | hci_send_cmd(hdev, | ||
1613 | HCI_OP_AUTH_REQUESTED, | ||
1614 | sizeof(cp), &cp); | 1612 | sizeof(cp), &cp); |
1615 | } | ||
1616 | } else { | 1613 | } else { |
1617 | conn->state = BT_CONNECTED; | 1614 | conn->state = BT_CONNECTED; |
1618 | hci_proto_connect_cfm(conn, ev->status); | 1615 | hci_proto_connect_cfm(conn, ev->status); |
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 3396d5bdef1c..9610a9c85b98 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -55,7 +55,7 @@ | |||
55 | #define BT_DBG(D...) | 55 | #define BT_DBG(D...) |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | #define VERSION "2.10" | 58 | #define VERSION "2.11" |
59 | 59 | ||
60 | static u32 l2cap_feat_mask = 0x0000; | 60 | static u32 l2cap_feat_mask = 0x0000; |
61 | 61 | ||
@@ -778,6 +778,7 @@ static int l2cap_do_connect(struct sock *sk) | |||
778 | struct l2cap_conn *conn; | 778 | struct l2cap_conn *conn; |
779 | struct hci_conn *hcon; | 779 | struct hci_conn *hcon; |
780 | struct hci_dev *hdev; | 780 | struct hci_dev *hdev; |
781 | __u8 auth_type; | ||
781 | int err = 0; | 782 | int err = 0; |
782 | 783 | ||
783 | BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), l2cap_pi(sk)->psm); | 784 | 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) | |||
789 | 790 | ||
790 | err = -ENOMEM; | 791 | err = -ENOMEM; |
791 | 792 | ||
792 | hcon = hci_connect(hdev, ACL_LINK, dst); | 793 | if (l2cap_pi(sk)->link_mode & L2CAP_LM_AUTH || |
794 | l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT || | ||
795 | l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) { | ||
796 | if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) | ||
797 | auth_type = HCI_AT_NO_BONDING_MITM; | ||
798 | else | ||
799 | auth_type = HCI_AT_GENERAL_BONDING_MITM; | ||
800 | } else { | ||
801 | if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) | ||
802 | auth_type = HCI_AT_NO_BONDING; | ||
803 | else | ||
804 | auth_type = HCI_AT_GENERAL_BONDING; | ||
805 | } | ||
806 | |||
807 | hcon = hci_connect(hdev, ACL_LINK, dst, auth_type); | ||
793 | if (!hcon) | 808 | if (!hcon) |
794 | goto done; | 809 | goto done; |
795 | 810 | ||
@@ -1553,10 +1568,10 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
1553 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; | 1568 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; |
1554 | struct l2cap_conn_rsp rsp; | 1569 | struct l2cap_conn_rsp rsp; |
1555 | struct sock *sk, *parent; | 1570 | struct sock *sk, *parent; |
1556 | int result, status = 0; | 1571 | int result, status = L2CAP_CS_NO_INFO; |
1557 | 1572 | ||
1558 | u16 dcid = 0, scid = __le16_to_cpu(req->scid); | 1573 | u16 dcid = 0, scid = __le16_to_cpu(req->scid); |
1559 | __le16 psm = req->psm; | 1574 | __le16 psm = req->psm; |
1560 | 1575 | ||
1561 | BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid); | 1576 | BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid); |
1562 | 1577 | ||
@@ -1567,6 +1582,13 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
1567 | goto sendresp; | 1582 | goto sendresp; |
1568 | } | 1583 | } |
1569 | 1584 | ||
1585 | /* Check if the ACL is secure enough (if not SDP) */ | ||
1586 | if (psm != cpu_to_le16(0x0001) && | ||
1587 | !hci_conn_check_link_mode(conn->hcon)) { | ||
1588 | result = L2CAP_CR_SEC_BLOCK; | ||
1589 | goto response; | ||
1590 | } | ||
1591 | |||
1570 | result = L2CAP_CR_NO_MEM; | 1592 | result = L2CAP_CR_NO_MEM; |
1571 | 1593 | ||
1572 | /* Check for backlog size */ | 1594 | /* Check for backlog size */ |
@@ -2224,7 +2246,7 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status) | |||
2224 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); | 2246 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); |
2225 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); | 2247 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); |
2226 | rsp.result = cpu_to_le16(result); | 2248 | rsp.result = cpu_to_le16(result); |
2227 | rsp.status = cpu_to_le16(0); | 2249 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
2228 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | 2250 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, |
2229 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); | 2251 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); |
2230 | } | 2252 | } |
@@ -2296,7 +2318,7 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
2296 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); | 2318 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); |
2297 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); | 2319 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); |
2298 | rsp.result = cpu_to_le16(result); | 2320 | rsp.result = cpu_to_le16(result); |
2299 | rsp.status = cpu_to_le16(0); | 2321 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
2300 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | 2322 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, |
2301 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); | 2323 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); |
2302 | } | 2324 | } |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index a16011fedc1d..0cc91e6da76d 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -200,7 +200,7 @@ static int sco_connect(struct sock *sk) | |||
200 | else | 200 | else |
201 | type = SCO_LINK; | 201 | type = SCO_LINK; |
202 | 202 | ||
203 | hcon = hci_connect(hdev, type, dst); | 203 | hcon = hci_connect(hdev, type, dst, HCI_AT_NO_BONDING); |
204 | if (!hcon) | 204 | if (!hcon) |
205 | goto done; | 205 | goto done; |
206 | 206 | ||