aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/rfcomm/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bluetooth/rfcomm/core.c')
-rw-r--r--net/bluetooth/rfcomm/core.c25
1 files changed, 10 insertions, 15 deletions
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 754b153..2d28dfe 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -409,19 +409,11 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
return err;
}
- /* After L2sock created, increase refcnt immediately
- * It can make connection drop in rfcomm_security_cfm because of refcnt.
- */
- rfcomm_session_hold(s);
-
dlci = __dlci(!s->initiator, channel);
/* Check if DLCI already exists */
- if (rfcomm_dlc_get(s, dlci)) {
- /* decrement refcnt */
- rfcomm_session_put(s);
+ if (rfcomm_dlc_get(s, dlci))
return -EBUSY;
- }
rfcomm_dlc_clear_state(d);
@@ -437,9 +429,6 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
d->mtu = s->mtu;
d->cfc = (s->cfc == RFCOMM_CFC_UNKNOWN) ? 0 : s->cfc;
- /* decrement refcnt */
- rfcomm_session_put(s);
-
if (s->state == BT_CONNECTED) {
if (rfcomm_check_security(d))
rfcomm_send_pn(s, 1, d);
@@ -475,6 +464,7 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
switch (d->state) {
case BT_CONNECT:
+ case BT_CONFIG:
if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
set_bit(RFCOMM_AUTH_REJECT, &d->flags);
rfcomm_schedule();
@@ -1173,7 +1163,7 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
/* When socket is closed and we are not RFCOMM
* initiator rfcomm_process_rx already calls
* rfcomm_session_put() */
- if (s->sock->sk->sk_state != BT_CLOSED && !s->initiator)
+ if (s->sock->sk->sk_state != BT_CLOSED)
if (list_empty(&s->dlcs))
rfcomm_session_put(s);
break;
@@ -1813,6 +1803,11 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
continue;
}
+ if (test_bit(RFCOMM_ENC_DROP, &d->flags)) {
+ __rfcomm_dlc_close(d, ECONNREFUSED);
+ continue;
+ }
+
if (test_and_clear_bit(RFCOMM_AUTH_ACCEPT, &d->flags)) {
rfcomm_dlc_clear_timer(d);
if (d->out) {
@@ -2088,7 +2083,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
if (test_and_clear_bit(RFCOMM_SEC_PENDING, &d->flags)) {
rfcomm_dlc_clear_timer(d);
if (status || encrypt == 0x00) {
- __rfcomm_dlc_close(d, ECONNREFUSED);
+ set_bit(RFCOMM_ENC_DROP, &d->flags);
continue;
}
}
@@ -2099,7 +2094,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
continue;
} else if (d->sec_level == BT_SECURITY_HIGH) {
- __rfcomm_dlc_close(d, ECONNREFUSED);
+ set_bit(RFCOMM_ENC_DROP, &d->flags);
continue;
}
}