Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 134719
b: refs/heads/master
c: 9f2c8a0
h: refs/heads/master
i:
  134717: 11efc0f
  134715: bb79b38
  134711: 150fb32
  134703: fa5858c
  134687: 83ef6cc
  134655: a27a407
v: v3
  • Loading branch information
Marcel Holtmann committed Feb 27, 2009
1 parent a087ec3 commit eb4263d
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 32 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2af6b9d518ddfbc4d6990d5f9c9b1a05341c1cef
refs/heads/master: 9f2c8a03fbb3048cf38b158f87aa0c3c09bca084
7 changes: 4 additions & 3 deletions trunk/include/net/bluetooth/rfcomm.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,8 @@ struct rfcomm_dlc {
u8 remote_v24_sig;
u8 mscex;
u8 out;

u32 link_mode;
u8 sec_level;
u8 role_switch;
u32 defer_setup;

uint mtu;
Expand Down Expand Up @@ -307,7 +307,8 @@ struct rfcomm_pinfo {
struct bt_sock bt;
struct rfcomm_dlc *dlc;
u8 channel;
u32 link_mode;
u8 sec_level;
u8 role_switch;
};

int rfcomm_init_sockets(void);
Expand Down
28 changes: 7 additions & 21 deletions trunk/net/bluetooth/rfcomm/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,21 +223,11 @@ static int rfcomm_l2sock_create(struct socket **sock)
return err;
}

static inline int rfcomm_check_link_mode(struct rfcomm_dlc *d)
static inline int rfcomm_check_security(struct rfcomm_dlc *d)
{
struct sock *sk = d->session->sock->sk;
struct l2cap_conn *conn = l2cap_pi(sk)->conn;

if (d->link_mode & RFCOMM_LM_SECURE)
return hci_conn_security(conn->hcon, BT_SECURITY_HIGH);

if (d->link_mode & RFCOMM_LM_ENCRYPT)
return hci_conn_security(conn->hcon, BT_SECURITY_MEDIUM);

if (d->link_mode & RFCOMM_LM_AUTH)
return hci_conn_security(conn->hcon, BT_SECURITY_LOW);

return 1;
return hci_conn_security(l2cap_pi(sk)->conn->hcon, d->sec_level);
}

/* ---- RFCOMM DLCs ---- */
Expand Down Expand Up @@ -390,7 +380,7 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
d->cfc = (s->cfc == RFCOMM_CFC_UNKNOWN) ? 0 : s->cfc;

if (s->state == BT_CONNECTED) {
if (rfcomm_check_link_mode(d))
if (rfcomm_check_security(d))
rfcomm_send_pn(s, 1, d);
else
set_bit(RFCOMM_AUTH_PENDING, &d->flags);
Expand Down Expand Up @@ -1192,15 +1182,15 @@ void rfcomm_dlc_accept(struct rfcomm_dlc *d)
d->state_change(d, 0);
rfcomm_dlc_unlock(d);

if (d->link_mode & RFCOMM_LM_MASTER)
if (d->role_switch)
hci_conn_switch_role(l2cap_pi(sk)->conn->hcon, 0x00);

rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig);
}

static void rfcomm_check_accept(struct rfcomm_dlc *d)
{
if (rfcomm_check_link_mode(d)) {
if (rfcomm_check_security(d)) {
if (d->defer_setup) {
set_bit(RFCOMM_DEFER_SETUP, &d->flags);
rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
Expand Down Expand Up @@ -1660,7 +1650,7 @@ static void rfcomm_process_connect(struct rfcomm_session *s)
d = list_entry(p, struct rfcomm_dlc, list);
if (d->state == BT_CONFIG) {
d->mtu = s->mtu;
if (rfcomm_check_link_mode(d)) {
if (rfcomm_check_security(d)) {
rfcomm_send_pn(s, 1, d);
} else {
set_bit(RFCOMM_AUTH_PENDING, &d->flags);
Expand Down Expand Up @@ -1748,10 +1738,6 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
} else
rfcomm_dlc_accept(d);
}
if (d->link_mode & RFCOMM_LM_SECURE) {
struct sock *sk = s->sock->sk;
hci_conn_change_link_key(l2cap_pi(sk)->conn->hcon);
}
continue;
} else if (test_and_clear_bit(RFCOMM_AUTH_REJECT, &d->flags)) {
rfcomm_dlc_clear_timer(d);
Expand Down Expand Up @@ -1994,7 +1980,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
d = list_entry(p, struct rfcomm_dlc, list);

if (!status && encrypt == 0x00 &&
(d->link_mode & RFCOMM_LM_ENCRYPT) &&
d->sec_level == BT_SECURITY_HIGH &&
(d->state == BT_CONNECTED ||
d->state == BT_CONFIG)) {
__rfcomm_dlc_close(d, ECONNREFUSED);
Expand Down
75 changes: 68 additions & 7 deletions trunk/net/bluetooth/rfcomm/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,19 @@ static void rfcomm_sock_init(struct sock *sk, struct sock *parent)

if (parent) {
sk->sk_type = parent->sk_type;
pi->link_mode = rfcomm_pi(parent)->link_mode;
pi->dlc->defer_setup = bt_sk(parent)->defer_setup;

pi->sec_level = rfcomm_pi(parent)->sec_level;
pi->role_switch = rfcomm_pi(parent)->role_switch;
} else {
pi->link_mode = 0;
pi->dlc->defer_setup = 0;

pi->sec_level = BT_SECURITY_LOW;
pi->role_switch = 0;
}

pi->dlc->link_mode = pi->link_mode;
pi->dlc->sec_level = pi->sec_level;
pi->dlc->role_switch = pi->role_switch;
}

static struct proto rfcomm_proto = {
Expand Down Expand Up @@ -408,7 +413,8 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
bacpy(&bt_sk(sk)->dst, &sa->rc_bdaddr);
rfcomm_pi(sk)->channel = sa->rc_channel;

d->link_mode = rfcomm_pi(sk)->link_mode;
d->sec_level = rfcomm_pi(sk)->sec_level;
d->role_switch = rfcomm_pi(sk)->role_switch;

err = rfcomm_dlc_open(d, &bt_sk(sk)->src, &sa->rc_bdaddr, sa->rc_channel);
if (!err)
Expand Down Expand Up @@ -741,7 +747,14 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __u
break;
}

rfcomm_pi(sk)->link_mode = opt;
if (opt & RFCOMM_LM_AUTH)
rfcomm_pi(sk)->sec_level = BT_SECURITY_LOW;
if (opt & RFCOMM_LM_ENCRYPT)
rfcomm_pi(sk)->sec_level = BT_SECURITY_MEDIUM;
if (opt & RFCOMM_LM_SECURE)
rfcomm_pi(sk)->sec_level = BT_SECURITY_HIGH;

rfcomm_pi(sk)->role_switch = (opt & RFCOMM_LM_MASTER);
break;

default:
Expand All @@ -756,7 +769,8 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __u
static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen)
{
struct sock *sk = sock->sk;
int err = 0;
struct bt_security sec;
int len, err = 0;
u32 opt;

BT_DBG("sk %p", sk);
Expand All @@ -767,6 +781,23 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
lock_sock(sk);

switch (optname) {
case BT_SECURITY:
sec.level = BT_SECURITY_LOW;

len = min_t(unsigned int, sizeof(sec), optlen);
if (copy_from_user((char *) &sec, optval, len)) {
err = -EFAULT;
break;
}

if (sec.level > BT_SECURITY_HIGH) {
err = -EINVAL;
break;
}

rfcomm_pi(sk)->sec_level = sec.level;
break;

case BT_DEFER_SETUP:
if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
err = -EINVAL;
Expand Down Expand Up @@ -796,6 +827,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
struct sock *l2cap_sk;
struct rfcomm_conninfo cinfo;
int len, err = 0;
u32 opt;

BT_DBG("sk %p", sk);

Expand All @@ -806,7 +838,26 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u

switch (optname) {
case RFCOMM_LM:
if (put_user(rfcomm_pi(sk)->link_mode, (u32 __user *) optval))
switch (rfcomm_pi(sk)->sec_level) {
case BT_SECURITY_LOW:
opt = RFCOMM_LM_AUTH;
break;
case BT_SECURITY_MEDIUM:
opt = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT;
break;
case BT_SECURITY_HIGH:
opt = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT |
RFCOMM_LM_SECURE;
break;
default:
opt = 0;
break;
}

if (rfcomm_pi(sk)->role_switch)
opt |= RFCOMM_LM_MASTER;

if (put_user(opt, (u32 __user *) optval))
err = -EFAULT;
break;

Expand Down Expand Up @@ -840,6 +891,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
{
struct sock *sk = sock->sk;
struct bt_security sec;
int len, err = 0;

BT_DBG("sk %p", sk);
Expand All @@ -853,6 +905,15 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c
lock_sock(sk);

switch (optname) {
case BT_SECURITY:
sec.level = rfcomm_pi(sk)->sec_level;

len = min_t(unsigned int, len, sizeof(sec));
if (copy_to_user(optval, (char *) &sec, len))
err = -EFAULT;

break;

case BT_DEFER_SETUP:
if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
err = -EINVAL;
Expand Down

0 comments on commit eb4263d

Please sign in to comment.