aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2008-07-14 14:13:45 -0400
committerMarcel Holtmann <marcel@holtmann.org>2008-07-14 14:13:45 -0400
commit9719f8afce34d3d04e884873a8a5e3483e30974c (patch)
treeaee26f7df7e2d92aa54d4b9da88c4ff5987191dd
parent77db1980565626471a980f0d2d17299e4bd5e7a5 (diff)
[Bluetooth] Disconnect when encryption gets disabled
The Bluetooth specification allows to enable or disable the encryption of an ACL link at any time by either the peer or the remote device. If a L2CAP or RFCOMM connection requested an encrypted link, they will now disconnect that link if the encryption gets disabled. Higher protocols that don't care about encryption (like SDP) are not affected. Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/bluetooth/hci_core.h10
-rw-r--r--net/bluetooth/l2cap.c13
-rw-r--r--net/bluetooth/rfcomm/core.c8
3 files changed, 25 insertions, 6 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index ea13baa3851b..c8255adee8f5 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -474,7 +474,7 @@ struct hci_proto {
474 int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb, __u16 flags); 474 int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
475 int (*recv_scodata) (struct hci_conn *conn, struct sk_buff *skb); 475 int (*recv_scodata) (struct hci_conn *conn, struct sk_buff *skb);
476 int (*auth_cfm) (struct hci_conn *conn, __u8 status); 476 int (*auth_cfm) (struct hci_conn *conn, __u8 status);
477 int (*encrypt_cfm) (struct hci_conn *conn, __u8 status); 477 int (*encrypt_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
478}; 478};
479 479
480static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type) 480static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
@@ -532,17 +532,17 @@ static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
532 hp->auth_cfm(conn, status); 532 hp->auth_cfm(conn, status);
533} 533}
534 534
535static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status) 535static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt)
536{ 536{
537 register struct hci_proto *hp; 537 register struct hci_proto *hp;
538 538
539 hp = hci_proto[HCI_PROTO_L2CAP]; 539 hp = hci_proto[HCI_PROTO_L2CAP];
540 if (hp && hp->encrypt_cfm) 540 if (hp && hp->encrypt_cfm)
541 hp->encrypt_cfm(conn, status); 541 hp->encrypt_cfm(conn, status, encrypt);
542 542
543 hp = hci_proto[HCI_PROTO_SCO]; 543 hp = hci_proto[HCI_PROTO_SCO];
544 if (hp && hp->encrypt_cfm) 544 if (hp && hp->encrypt_cfm)
545 hp->encrypt_cfm(conn, status); 545 hp->encrypt_cfm(conn, status, encrypt);
546} 546}
547 547
548int hci_register_proto(struct hci_proto *hproto); 548int hci_register_proto(struct hci_proto *hproto);
@@ -579,7 +579,7 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encr
579{ 579{
580 struct list_head *p; 580 struct list_head *p;
581 581
582 hci_proto_encrypt_cfm(conn, status); 582 hci_proto_encrypt_cfm(conn, status, encrypt);
583 583
584 read_lock_bh(&hci_cb_list_lock); 584 read_lock_bh(&hci_cb_list_lock);
585 list_for_each(p, &hci_cb_list) { 585 list_for_each(p, &hci_cb_list) {
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 2e3abdfbd69d..252264062f59 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -2197,7 +2197,7 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)
2197 return 0; 2197 return 0;
2198} 2198}
2199 2199
2200static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status) 2200static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
2201{ 2201{
2202 struct l2cap_chan_list *l; 2202 struct l2cap_chan_list *l;
2203 struct l2cap_conn *conn = hcon->l2cap_data; 2203 struct l2cap_conn *conn = hcon->l2cap_data;
@@ -2215,8 +2215,19 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status)
2215 read_lock(&l->lock); 2215 read_lock(&l->lock);
2216 2216
2217 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { 2217 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
2218 struct l2cap_pinfo *pi = l2cap_pi(sk);
2219
2218 bh_lock_sock(sk); 2220 bh_lock_sock(sk);
2219 2221
2222 if ((pi->link_mode & (L2CAP_LM_ENCRYPT | L2CAP_LM_SECURE)) &&
2223 (sk->sk_state == BT_CONNECTED ||
2224 sk->sk_state == BT_CONFIG) &&
2225 !status && encrypt == 0x00) {
2226 __l2cap_sock_close(sk, ECONNREFUSED);
2227 bh_unlock_sock(sk);
2228 continue;
2229 }
2230
2220 if (sk->sk_state != BT_CONNECT2) { 2231 if (sk->sk_state != BT_CONNECT2) {
2221 bh_unlock_sock(sk); 2232 bh_unlock_sock(sk);
2222 continue; 2233 continue;
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 1f92f9ab4959..e7a6a03cea37 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -2003,6 +2003,14 @@ static void rfcomm_encrypt_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
2003 list_for_each_safe(p, n, &s->dlcs) { 2003 list_for_each_safe(p, n, &s->dlcs) {
2004 d = list_entry(p, struct rfcomm_dlc, list); 2004 d = list_entry(p, struct rfcomm_dlc, list);
2005 2005
2006 if ((d->link_mode & (RFCOMM_LM_ENCRYPT | RFCOMM_LM_SECURE)) &&
2007 (d->state == BT_CONNECTED ||
2008 d->state == BT_CONFIG) &&
2009 !status && encrypt == 0x00) {
2010 __rfcomm_dlc_close(d, ECONNREFUSED);
2011 continue;
2012 }
2013
2006 if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags)) 2014 if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags))
2007 continue; 2015 continue;
2008 2016