Skip to content

Commit

Permalink
Bluetooth: Fix ERTM error reporting to the userspace
Browse files Browse the repository at this point in the history
If any error occurs during transfers we have to tell userspace that
something wrong happened.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
  • Loading branch information
Gustavo F. Padovan authored and Marcel Holtmann committed Jul 21, 2010
1 parent 4ea727e commit 9b108fc
Showing 1 changed file with 22 additions and 17 deletions.
39 changes: 22 additions & 17 deletions net/bluetooth/l2cap.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ static void l2cap_do_start(struct sock *sk)
}
}

static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk)
static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
{
struct l2cap_disconn_req req;

Expand All @@ -477,6 +477,7 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk)
L2CAP_DISCONN_REQ, sizeof(req), &req);

sk->sk_state = BT_DISCONN;
sk->sk_err = err;
}

/* ---- L2CAP connections ---- */
Expand Down Expand Up @@ -770,7 +771,7 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
struct l2cap_conn *conn = l2cap_pi(sk)->conn;

l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
l2cap_send_disconn_req(conn, sk);
l2cap_send_disconn_req(conn, sk, reason);
} else
l2cap_chan_del(sk, reason);
break;
Expand Down Expand Up @@ -1315,7 +1316,7 @@ static void l2cap_monitor_timeout(unsigned long arg)

bh_lock_sock(sk);
if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk);
l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
bh_unlock_sock(sk);
return;
}
Expand Down Expand Up @@ -1423,7 +1424,7 @@ static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)

if (pi->remote_max_tx &&
bt_cb(skb)->retries == pi->remote_max_tx) {
l2cap_send_disconn_req(pi->conn, sk);
l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
return;
}

Expand Down Expand Up @@ -1463,7 +1464,7 @@ static int l2cap_ertm_send(struct sock *sk)

if (pi->remote_max_tx &&
bt_cb(skb)->retries == pi->remote_max_tx) {
l2cap_send_disconn_req(pi->conn, sk);
l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
break;
}

Expand Down Expand Up @@ -2191,6 +2192,10 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
err = bt_sock_wait_state(sk, BT_CLOSED,
sk->sk_lingertime);
}

if (!err && sk->sk_err)
err = -sk->sk_err;

release_sock(sk);
return err;
}
Expand Down Expand Up @@ -2462,7 +2467,7 @@ static int l2cap_build_conf_req(struct sock *sk, void *data)
case L2CAP_MODE_ERTM:
pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
if (!l2cap_mode_supported(pi->mode, pi->conn->feat_mask))
l2cap_send_disconn_req(pi->conn, sk);
l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
break;
default:
pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
Expand Down Expand Up @@ -3030,7 +3035,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
/* Complete config. */
len = l2cap_parse_conf_req(sk, rsp);
if (len < 0) {
l2cap_send_disconn_req(conn, sk);
l2cap_send_disconn_req(conn, sk, ECONNRESET);
goto unlock;
}

Expand Down Expand Up @@ -3100,7 +3105,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
char req[64];

if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
l2cap_send_disconn_req(conn, sk);
l2cap_send_disconn_req(conn, sk, ECONNRESET);
goto done;
}

Expand All @@ -3109,7 +3114,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
len = l2cap_parse_conf_rsp(sk, rsp->data,
len, req, &result);
if (len < 0) {
l2cap_send_disconn_req(conn, sk);
l2cap_send_disconn_req(conn, sk, ECONNRESET);
goto done;
}

Expand All @@ -3124,7 +3129,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
default:
sk->sk_err = ECONNRESET;
l2cap_sock_set_timer(sk, HZ * 5);
l2cap_send_disconn_req(conn, sk);
l2cap_send_disconn_req(conn, sk, ECONNRESET);
goto done;
}

Expand Down Expand Up @@ -3565,7 +3570,7 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c
pi->sdu = NULL;

disconnect:
l2cap_send_disconn_req(pi->conn, sk);
l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
kfree_skb(skb);
return 0;
}
Expand All @@ -3588,7 +3593,7 @@ static void l2cap_busy_work(struct work_struct *work)

if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
err = -EBUSY;
l2cap_send_disconn_req(pi->conn, sk);
l2cap_send_disconn_req(pi->conn, sk, EBUSY);
goto done;
}

Expand Down Expand Up @@ -3864,7 +3869,7 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str

/* invalid tx_seq */
if (tx_seq_offset >= pi->tx_win) {
l2cap_send_disconn_req(pi->conn, sk);
l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
goto drop;
}

Expand Down Expand Up @@ -4181,7 +4186,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
len -= 2;

if (len > pi->mps) {
l2cap_send_disconn_req(pi->conn, sk);
l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
goto drop;
}

Expand All @@ -4197,20 +4202,20 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk

/* check for invalid req-seq */
if (req_seq_offset > next_tx_seq_offset) {
l2cap_send_disconn_req(pi->conn, sk);
l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
goto drop;
}

if (__is_iframe(control)) {
if (len < 0) {
l2cap_send_disconn_req(pi->conn, sk);
l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
goto drop;
}

l2cap_data_channel_iframe(sk, control, skb);
} else {
if (len != 0) {
l2cap_send_disconn_req(pi->conn, sk);
l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
goto drop;
}

Expand Down

0 comments on commit 9b108fc

Please sign in to comment.