aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2009-01-15 15:58:44 -0500
committerMarcel Holtmann <marcel@holtmann.org>2009-02-27 00:14:33 -0500
commitf62e4323ab43c59e7cd7f72c1eb392d7c767ce5a (patch)
tree8ee582e12c91260ee4eccecbbe2fe055b41d97aa /net/bluetooth
parent8c84b83076b5062f59b6167cdda90d9e5124aa71 (diff)
Bluetooth: Disconnect L2CAP connections without encryption
For L2CAP connections with high security setting, the link will be immediately dropped when the encryption gets disabled. For L2CAP connections with medium security there will be grace period where the remote device has the chance to re-enable encryption. If it doesn't happen then the link will also be disconnected. The requirement for the grace period with medium security comes from Bluetooth 2.0 and earlier devices that require role switching. Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/l2cap.c26
1 files changed, 19 insertions, 7 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index e899a9371c00..b2d279c245cf 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -77,7 +77,9 @@ static void l2cap_sock_timeout(unsigned long arg)
77 77
78 bh_lock_sock(sk); 78 bh_lock_sock(sk);
79 79
80 if (sk->sk_state == BT_CONNECT && 80 if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
81 reason = ECONNREFUSED;
82 else if (sk->sk_state == BT_CONNECT &&
81 l2cap_pi(sk)->sec_level != BT_SECURITY_SDP) 83 l2cap_pi(sk)->sec_level != BT_SECURITY_SDP)
82 reason = ECONNREFUSED; 84 reason = ECONNREFUSED;
83 else 85 else
@@ -2400,6 +2402,20 @@ static int l2cap_disconn_ind(struct hci_conn *hcon, u8 reason)
2400 return 0; 2402 return 0;
2401} 2403}
2402 2404
2405static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
2406{
2407 if (encrypt == 0x00) {
2408 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
2409 l2cap_sock_clear_timer(sk);
2410 l2cap_sock_set_timer(sk, HZ * 5);
2411 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
2412 __l2cap_sock_close(sk, ECONNREFUSED);
2413 } else {
2414 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
2415 l2cap_sock_clear_timer(sk);
2416 }
2417}
2418
2403static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) 2419static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
2404{ 2420{
2405 struct l2cap_chan_list *l; 2421 struct l2cap_chan_list *l;
@@ -2416,15 +2432,11 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
2416 read_lock(&l->lock); 2432 read_lock(&l->lock);
2417 2433
2418 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { 2434 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
2419 struct l2cap_pinfo *pi = l2cap_pi(sk);
2420
2421 bh_lock_sock(sk); 2435 bh_lock_sock(sk);
2422 2436
2423 if (!status && encrypt == 0x00 && 2437 if (!status && (sk->sk_state == BT_CONNECTED ||
2424 pi->sec_level == BT_SECURITY_HIGH &&
2425 (sk->sk_state == BT_CONNECTED ||
2426 sk->sk_state == BT_CONFIG)) { 2438 sk->sk_state == BT_CONFIG)) {
2427 __l2cap_sock_close(sk, ECONNREFUSED); 2439 l2cap_check_encryption(sk, encrypt);
2428 bh_unlock_sock(sk); 2440 bh_unlock_sock(sk);
2429 continue; 2441 continue;
2430 } 2442 }