From 9719f8afce34d3d04e884873a8a5e3483e30974c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 14 Jul 2008 20:13:45 +0200 Subject: [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 --- net/bluetooth/l2cap.c | 13 ++++++++++++- net/bluetooth/rfcomm/core.c | 8 ++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) (limited to 'net/bluetooth') 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) return 0; } -static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status) +static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) { struct l2cap_chan_list *l; struct l2cap_conn *conn = hcon->l2cap_data; @@ -2215,8 +2215,19 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status) read_lock(&l->lock); for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { + struct l2cap_pinfo *pi = l2cap_pi(sk); + bh_lock_sock(sk); + if ((pi->link_mode & (L2CAP_LM_ENCRYPT | L2CAP_LM_SECURE)) && + (sk->sk_state == BT_CONNECTED || + sk->sk_state == BT_CONFIG) && + !status && encrypt == 0x00) { + __l2cap_sock_close(sk, ECONNREFUSED); + bh_unlock_sock(sk); + continue; + } + if (sk->sk_state != BT_CONNECT2) { bh_unlock_sock(sk); 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) list_for_each_safe(p, n, &s->dlcs) { d = list_entry(p, struct rfcomm_dlc, list); + if ((d->link_mode & (RFCOMM_LM_ENCRYPT | RFCOMM_LM_SECURE)) && + (d->state == BT_CONNECTED || + d->state == BT_CONFIG) && + !status && encrypt == 0x00) { + __rfcomm_dlc_close(d, ECONNREFUSED); + continue; + } + if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags)) continue; -- cgit v1.2.3