Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 103680
b: refs/heads/master
c: b1235d7
h: refs/heads/master
v: v3
  • Loading branch information
Marcel Holtmann committed Jul 14, 2008
1 parent 14df2e4 commit db828d7
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 65 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: 7cb127d5b0e7af7a0afd23785722ca3edab4ceff
refs/heads/master: b1235d79611e78a07629b4cbe53291c9cffd1834
172 changes: 108 additions & 64 deletions trunk/net/bluetooth/l2cap.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,21 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
static void l2cap_sock_timeout(unsigned long arg)
{
struct sock *sk = (struct sock *) arg;
int reason;

BT_DBG("sock %p state %d", sk, sk->sk_state);

bh_lock_sock(sk);
__l2cap_sock_close(sk, ETIMEDOUT);

if (sk->sk_state == BT_CONNECT &&
(l2cap_pi(sk)->link_mode & (L2CAP_LM_AUTH |
L2CAP_LM_ENCRYPT | L2CAP_LM_SECURE)))
reason = ECONNREFUSED;
else
reason = ETIMEDOUT;

__l2cap_sock_close(sk, reason);

bh_unlock_sock(sk);

l2cap_sock_kill(sk);
Expand Down Expand Up @@ -240,7 +250,7 @@ static void l2cap_chan_del(struct sock *sk, int err)
hci_conn_put(conn->hcon);
}

sk->sk_state = BT_CLOSED;
sk->sk_state = BT_CLOSED;
sock_set_flag(sk, SOCK_ZAPPED);

if (err)
Expand Down Expand Up @@ -307,14 +317,16 @@ static void l2cap_do_start(struct sock *sk)
struct l2cap_conn *conn = l2cap_pi(sk)->conn;

if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
struct l2cap_conn_req req;
req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
req.psm = l2cap_pi(sk)->psm;
if (l2cap_check_link_mode(sk)) {
struct l2cap_conn_req req;
req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
req.psm = l2cap_pi(sk)->psm;

l2cap_pi(sk)->ident = l2cap_get_ident(conn);
l2cap_pi(sk)->ident = l2cap_get_ident(conn);

l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
L2CAP_CONN_REQ, sizeof(req), &req);
}
} else {
struct l2cap_info_req req;
req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
Expand Down Expand Up @@ -349,14 +361,16 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
}

if (sk->sk_state == BT_CONNECT) {
struct l2cap_conn_req req;
req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
req.psm = l2cap_pi(sk)->psm;
if (l2cap_check_link_mode(sk)) {
struct l2cap_conn_req req;
req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
req.psm = l2cap_pi(sk)->psm;

l2cap_pi(sk)->ident = l2cap_get_ident(conn);
l2cap_pi(sk)->ident = l2cap_get_ident(conn);

l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
L2CAP_CONN_REQ, sizeof(req), &req);
}
} else if (sk->sk_state == BT_CONNECT2) {
struct l2cap_conn_rsp rsp;
rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Expand Down Expand Up @@ -455,7 +469,8 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)

conn->feat_mask = 0;

setup_timer(&conn->info_timer, l2cap_info_timeout, (unsigned long)conn);
setup_timer(&conn->info_timer, l2cap_info_timeout,
(unsigned long) conn);

spin_lock_init(&conn->lock);
rwlock_init(&conn->chan_list.lock);
Expand Down Expand Up @@ -567,7 +582,7 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
while ((sk = bt_accept_dequeue(parent, NULL)))
l2cap_sock_close(sk);

parent->sk_state = BT_CLOSED;
parent->sk_state = BT_CLOSED;
sock_set_flag(parent, SOCK_ZAPPED);
}

Expand Down Expand Up @@ -610,9 +625,8 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
l2cap_send_cmd(conn, l2cap_get_ident(conn),
L2CAP_DISCONN_REQ, sizeof(req), &req);
} else {
} else
l2cap_chan_del(sk, reason);
}
break;

case BT_CONNECT:
Expand Down Expand Up @@ -681,9 +695,9 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p
sock_reset_flag(sk, SOCK_ZAPPED);

sk->sk_protocol = proto;
sk->sk_state = BT_OPEN;
sk->sk_state = BT_OPEN;

setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long)sk);
setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk);

bt_sock_link(&l2cap_sk_list, sk);
return sk;
Expand Down Expand Up @@ -1201,7 +1215,8 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
__l2cap_sock_close(sk, 0);

if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
err = bt_sock_wait_state(sk, BT_CLOSED,
sk->sk_lingertime);
}
release_sock(sk);
return err;
Expand Down Expand Up @@ -1245,6 +1260,11 @@ static void l2cap_chan_ready(struct sock *sk)
*/
parent->sk_data_ready(parent, 0);
}

if (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) {
struct l2cap_conn *conn = l2cap_pi(sk)->conn;
hci_conn_change_link_key(conn->hcon);
}
}

/* Copy frame to all raw sockets on that connection */
Expand Down Expand Up @@ -1778,7 +1798,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr

default:
sk->sk_state = BT_DISCONN;
sk->sk_err = ECONNRESET;
sk->sk_err = ECONNRESET;
l2cap_sock_set_timer(sk, HZ * 5);
{
struct l2cap_disconn_req req;
Expand Down Expand Up @@ -2151,9 +2171,7 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)
{
struct l2cap_chan_list *l;
struct l2cap_conn *conn = hcon->l2cap_data;
struct l2cap_conn_rsp rsp;
struct sock *sk;
int result;

if (!conn)
return 0;
Expand All @@ -2169,47 +2187,61 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)

bh_lock_sock(sk);

if (sk->sk_state != BT_CONNECT2) {
bh_unlock_sock(sk);
continue;
}

if ((pi->link_mode & (L2CAP_LM_ENCRYPT | L2CAP_LM_SECURE)) &&
!(hcon->link_mode & HCI_LM_ENCRYPT)) {
!(hcon->link_mode & HCI_LM_ENCRYPT) &&
!status) {
bh_unlock_sock(sk);
continue;
}

if (!status) {
sk->sk_state = BT_CONFIG;
result = 0;
} else {
sk->sk_state = BT_DISCONN;
l2cap_sock_set_timer(sk, HZ/10);
result = L2CAP_CR_SEC_BLOCK;
}
if (sk->sk_state == BT_CONNECT) {
if (!status) {
struct l2cap_conn_req req;
req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
req.psm = l2cap_pi(sk)->psm;

l2cap_pi(sk)->ident = l2cap_get_ident(conn);

l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
L2CAP_CONN_REQ, sizeof(req), &req);
} else {
l2cap_sock_clear_timer(sk);
l2cap_sock_set_timer(sk, HZ / 10);
}
} else if (sk->sk_state == BT_CONNECT2) {
struct l2cap_conn_rsp rsp;
__u16 result;

if (!status) {
sk->sk_state = BT_CONFIG;
result = L2CAP_CR_SUCCESS;
} else {
sk->sk_state = BT_DISCONN;
l2cap_sock_set_timer(sk, HZ / 10);
result = L2CAP_CR_SEC_BLOCK;
}

rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
rsp.result = cpu_to_le16(result);
rsp.status = cpu_to_le16(0);
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
L2CAP_CONN_RSP, sizeof(rsp), &rsp);
rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
rsp.result = cpu_to_le16(result);
rsp.status = cpu_to_le16(0);
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
L2CAP_CONN_RSP, sizeof(rsp), &rsp);
}

bh_unlock_sock(sk);
}

read_unlock(&l->lock);

return 0;
}

static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
{
struct l2cap_chan_list *l;
struct l2cap_conn *conn = hcon->l2cap_data;
struct l2cap_conn_rsp rsp;
struct sock *sk;
int result;

if (!conn)
return 0;
Expand All @@ -2234,34 +2266,46 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
continue;
}

if (sk->sk_state != BT_CONNECT2) {
bh_unlock_sock(sk);
continue;
}
if (sk->sk_state == BT_CONNECT) {
if (!status) {
struct l2cap_conn_req req;
req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
req.psm = l2cap_pi(sk)->psm;

if (!status) {
sk->sk_state = BT_CONFIG;
result = 0;
} else {
sk->sk_state = BT_DISCONN;
l2cap_sock_set_timer(sk, HZ/10);
result = L2CAP_CR_SEC_BLOCK;
}
l2cap_pi(sk)->ident = l2cap_get_ident(conn);

rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
rsp.result = cpu_to_le16(result);
rsp.status = cpu_to_le16(0);
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
L2CAP_CONN_RSP, sizeof(rsp), &rsp);
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
L2CAP_CONN_REQ, sizeof(req), &req);
} else {
l2cap_sock_clear_timer(sk);
l2cap_sock_set_timer(sk, HZ / 10);
}
} else if (sk->sk_state == BT_CONNECT2) {
struct l2cap_conn_rsp rsp;
__u16 result;

if (l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE)
hci_conn_change_link_key(hcon);
if (!status) {
sk->sk_state = BT_CONFIG;
result = L2CAP_CR_SUCCESS;
} else {
sk->sk_state = BT_DISCONN;
l2cap_sock_set_timer(sk, HZ / 10);
result = L2CAP_CR_SEC_BLOCK;
}

rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
rsp.result = cpu_to_le16(result);
rsp.status = cpu_to_le16(0);
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
L2CAP_CONN_RSP, sizeof(rsp), &rsp);
}

bh_unlock_sock(sk);
}

read_unlock(&l->lock);

return 0;
}

Expand Down

0 comments on commit db828d7

Please sign in to comment.