summaryrefslogtreecommitdiffstats
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.c48
1 files changed, 29 insertions, 19 deletions
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 39a5d87e33b..5759bb7054f 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -41,7 +41,7 @@
#include <linux/slab.h>
#include <net/sock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
@@ -51,10 +51,10 @@
#define VERSION "1.11"
-static int disable_cfc = 0;
+static int disable_cfc;
+static int l2cap_ertm;
static int channel_mtu = -1;
static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU;
-static int l2cap_ertm = 0;
static struct task_struct *rfcomm_thread;
@@ -79,7 +79,10 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr);
static void rfcomm_process_connect(struct rfcomm_session *s);
-static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int *err);
+static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
+ bdaddr_t *dst,
+ u8 sec_level,
+ int *err);
static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst);
static void rfcomm_session_del(struct rfcomm_session *s);
@@ -229,6 +232,8 @@ static int rfcomm_l2sock_create(struct socket **sock)
static inline int rfcomm_check_security(struct rfcomm_dlc *d)
{
struct sock *sk = d->session->sock->sk;
+ struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
+
__u8 auth_type;
switch (d->sec_level) {
@@ -243,8 +248,7 @@ static inline int rfcomm_check_security(struct rfcomm_dlc *d)
break;
}
- return hci_conn_security(l2cap_pi(sk)->conn->hcon, d->sec_level,
- auth_type);
+ return hci_conn_security(conn->hcon, d->sec_level, auth_type);
}
static void rfcomm_session_timeout(unsigned long arg)
@@ -308,6 +312,7 @@ static void rfcomm_dlc_clear_state(struct rfcomm_dlc *d)
d->state = BT_OPEN;
d->flags = 0;
d->mscex = 0;
+ d->sec_level = BT_SECURITY_LOW;
d->mtu = RFCOMM_DEFAULT_MTU;
d->v24_sig = RFCOMM_V24_RTC | RFCOMM_V24_RTR | RFCOMM_V24_DV;
@@ -401,7 +406,7 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
s = rfcomm_session_get(src, dst);
if (!s) {
- s = rfcomm_session_create(src, dst, &err);
+ s = rfcomm_session_create(src, dst, d->sec_level, &err);
if (!s)
return err;
}
@@ -679,7 +684,10 @@ static void rfcomm_session_close(struct rfcomm_session *s, int err)
rfcomm_session_put(s);
}
-static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int *err)
+static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
+ bdaddr_t *dst,
+ u8 sec_level,
+ int *err)
{
struct rfcomm_session *s = NULL;
struct sockaddr_l2 addr;
@@ -703,9 +711,10 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst
/* Set L2CAP options */
sk = sock->sk;
lock_sock(sk);
- l2cap_pi(sk)->imtu = l2cap_mtu;
+ l2cap_pi(sk)->chan->imtu = l2cap_mtu;
+ l2cap_pi(sk)->chan->sec_level = sec_level;
if (l2cap_ertm)
- l2cap_pi(sk)->mode = L2CAP_MODE_ERTM;
+ l2cap_pi(sk)->chan->mode = L2CAP_MODE_ERTM;
release_sock(sk);
s = rfcomm_session_add(sock, BT_BOUND);
@@ -1156,7 +1165,8 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
* initiator rfcomm_process_rx already calls
* rfcomm_session_put() */
if (s->sock->sk->sk_state != BT_CLOSED)
- rfcomm_session_put(s);
+ if (list_empty(&s->dlcs))
+ rfcomm_session_put(s);
break;
}
}
@@ -1232,6 +1242,7 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
void rfcomm_dlc_accept(struct rfcomm_dlc *d)
{
struct sock *sk = d->session->sock->sk;
+ struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
BT_DBG("dlc %p", d);
@@ -1245,7 +1256,7 @@ void rfcomm_dlc_accept(struct rfcomm_dlc *d)
rfcomm_dlc_unlock(d);
if (d->role_switch)
- hci_conn_switch_role(l2cap_pi(sk)->conn->hcon, 0x00);
+ hci_conn_switch_role(conn->hcon, 0x00);
rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig);
}
@@ -1881,7 +1892,8 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s)
/* We should adjust MTU on incoming sessions.
* L2CAP MTU minus UIH header and FCS. */
- s->mtu = min(l2cap_pi(nsock->sk)->omtu, l2cap_pi(nsock->sk)->imtu) - 5;
+ s->mtu = min(l2cap_pi(nsock->sk)->chan->omtu,
+ l2cap_pi(nsock->sk)->chan->imtu) - 5;
rfcomm_schedule();
} else
@@ -1894,13 +1906,13 @@ static inline void rfcomm_check_connection(struct rfcomm_session *s)
BT_DBG("%p state %ld", s, s->state);
- switch(sk->sk_state) {
+ switch (sk->sk_state) {
case BT_CONNECTED:
s->state = BT_CONNECT;
/* We can adjust MTU on outgoing sessions.
* L2CAP MTU minus UIH header and FCS. */
- s->mtu = min(l2cap_pi(sk)->omtu, l2cap_pi(sk)->imtu) - 5;
+ s->mtu = min(l2cap_pi(sk)->chan->omtu, l2cap_pi(sk)->chan->imtu) - 5;
rfcomm_send_sabm(s, 0);
break;
@@ -1983,7 +1995,7 @@ static int rfcomm_add_listener(bdaddr_t *ba)
/* Set L2CAP options */
sk = sock->sk;
lock_sock(sk);
- l2cap_pi(sk)->imtu = l2cap_mtu;
+ l2cap_pi(sk)->chan->imtu = l2cap_mtu;
release_sock(sk);
/* Start listening on the socket */
@@ -2084,7 +2096,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags))
continue;
- if (!status)
+ if (!status && hci_conn_check_secure(conn, d->sec_level))
set_bit(RFCOMM_AUTH_ACCEPT, &d->flags);
else
set_bit(RFCOMM_AUTH_REJECT, &d->flags);
@@ -2145,8 +2157,6 @@ static int __init rfcomm_init(void)
{
int err;
- l2cap_load();
-
hci_register_cb(&rfcomm_cb);
rfcomm_thread = kthread_run(rfcomm_run, NULL, "krfcommd");