aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2009-01-16 02:17:51 -0500
committerMarcel Holtmann <marcel@holtmann.org>2009-02-27 00:14:33 -0500
commit8c84b83076b5062f59b6167cdda90d9e5124aa71 (patch)
tree7a47b0b80be4222494b272846ad5233f0d04c6e6 /net/bluetooth
parent9f2c8a03fbb3048cf38b158f87aa0c3c09bca084 (diff)
Bluetooth: Pause RFCOMM TX when encryption drops
A role switch with devices following the Bluetooth pre-2.1 standards or without Encryption Pause and Resume support is not possible if encryption is enabled. Most newer headsets require the role switch, but also require that the connection is encrypted. For connections with a high security mode setting, the link will be immediately dropped. When the connection uses medium security mode setting, then a grace period is introduced where the TX is halted and the remote device gets a change to re-enable encryption after the role switch. If not re-enabled the link will be dropped. Based on initial work by Ville Tervo <ville.tervo@nokia.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/rfcomm/core.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index db83f92d274c..dafaee91cdfb 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -1979,12 +1979,23 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
1979 list_for_each_safe(p, n, &s->dlcs) { 1979 list_for_each_safe(p, n, &s->dlcs) {
1980 d = list_entry(p, struct rfcomm_dlc, list); 1980 d = list_entry(p, struct rfcomm_dlc, list);
1981 1981
1982 if (!status && encrypt == 0x00 && 1982 if (test_and_clear_bit(RFCOMM_SEC_PENDING, &d->flags)) {
1983 d->sec_level == BT_SECURITY_HIGH && 1983 rfcomm_dlc_clear_timer(d);
1984 (d->state == BT_CONNECTED || 1984 if (status || encrypt == 0x00) {
1985 d->state == BT_CONFIG)) { 1985 __rfcomm_dlc_close(d, ECONNREFUSED);
1986 __rfcomm_dlc_close(d, ECONNREFUSED); 1986 continue;
1987 continue; 1987 }
1988 }
1989
1990 if (d->state == BT_CONNECTED && !status && encrypt == 0x00) {
1991 if (d->sec_level == BT_SECURITY_MEDIUM) {
1992 set_bit(RFCOMM_SEC_PENDING, &d->flags);
1993 rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
1994 continue;
1995 } else if (d->sec_level == BT_SECURITY_HIGH) {
1996 __rfcomm_dlc_close(d, ECONNREFUSED);
1997 continue;
1998 }
1988 } 1999 }
1989 2000
1990 if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags)) 2001 if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags))