|
@@ -272,6 +272,24 @@ static void l2cap_chan_del(struct sock *sk, int err)
|
|
parent->sk_data_ready(parent, 0);
|
|
parent->sk_data_ready(parent, 0);
|
|
} else
|
|
} else
|
|
sk->sk_state_change(sk);
|
|
sk->sk_state_change(sk);
|
|
|
|
+
|
|
|
|
+ skb_queue_purge(TX_QUEUE(sk));
|
|
|
|
+
|
|
|
|
+ if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
|
|
|
|
+ struct srej_list *l, *tmp;
|
|
|
|
+
|
|
|
|
+ del_timer(&l2cap_pi(sk)->retrans_timer);
|
|
|
|
+ del_timer(&l2cap_pi(sk)->monitor_timer);
|
|
|
|
+ del_timer(&l2cap_pi(sk)->ack_timer);
|
|
|
|
+
|
|
|
|
+ skb_queue_purge(SREJ_QUEUE(sk));
|
|
|
|
+ skb_queue_purge(BUSY_QUEUE(sk));
|
|
|
|
+
|
|
|
|
+ list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
|
|
|
|
+ list_del(&l->list);
|
|
|
|
+ kfree(l);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
/* Service level security */
|
|
/* Service level security */
|
|
@@ -345,8 +363,12 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
|
|
struct sk_buff *skb;
|
|
struct sk_buff *skb;
|
|
struct l2cap_hdr *lh;
|
|
struct l2cap_hdr *lh;
|
|
struct l2cap_conn *conn = pi->conn;
|
|
struct l2cap_conn *conn = pi->conn;
|
|
|
|
+ struct sock *sk = (struct sock *)pi;
|
|
int count, hlen = L2CAP_HDR_SIZE + 2;
|
|
int count, hlen = L2CAP_HDR_SIZE + 2;
|
|
|
|
|
|
|
|
+ if (sk->sk_state != BT_CONNECTED)
|
|
|
|
+ return;
|
|
|
|
+
|
|
if (pi->fcs == L2CAP_FCS_CRC16)
|
|
if (pi->fcs == L2CAP_FCS_CRC16)
|
|
hlen += 2;
|
|
hlen += 2;
|
|
|
|
|
|
@@ -438,10 +460,23 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk)
|
|
{
|
|
{
|
|
struct l2cap_disconn_req req;
|
|
struct l2cap_disconn_req req;
|
|
|
|
|
|
|
|
+ if (!conn)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ skb_queue_purge(TX_QUEUE(sk));
|
|
|
|
+
|
|
|
|
+ if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
|
|
|
|
+ del_timer(&l2cap_pi(sk)->retrans_timer);
|
|
|
|
+ del_timer(&l2cap_pi(sk)->monitor_timer);
|
|
|
|
+ del_timer(&l2cap_pi(sk)->ack_timer);
|
|
|
|
+ }
|
|
|
|
+
|
|
req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
|
|
req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
|
|
req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
|
|
req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
|
|
l2cap_send_cmd(conn, l2cap_get_ident(conn),
|
|
l2cap_send_cmd(conn, l2cap_get_ident(conn),
|
|
L2CAP_DISCONN_REQ, sizeof(req), &req);
|
|
L2CAP_DISCONN_REQ, sizeof(req), &req);
|
|
|
|
+
|
|
|
|
+ sk->sk_state = BT_DISCONN;
|
|
}
|
|
}
|
|
|
|
|
|
/* ---- L2CAP connections ---- */
|
|
/* ---- L2CAP connections ---- */
|
|
@@ -734,7 +769,6 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
|
|
sk->sk_type == SOCK_STREAM) {
|
|
sk->sk_type == SOCK_STREAM) {
|
|
struct l2cap_conn *conn = l2cap_pi(sk)->conn;
|
|
struct l2cap_conn *conn = l2cap_pi(sk)->conn;
|
|
|
|
|
|
- sk->sk_state = BT_DISCONN;
|
|
|
|
l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
|
|
l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
|
|
l2cap_send_disconn_req(conn, sk);
|
|
l2cap_send_disconn_req(conn, sk);
|
|
} else
|
|
} else
|
|
@@ -1415,6 +1449,8 @@ static int l2cap_ertm_send(struct sock *sk)
|
|
u16 control, fcs;
|
|
u16 control, fcs;
|
|
int nsent = 0;
|
|
int nsent = 0;
|
|
|
|
|
|
|
|
+ if (sk->sk_state != BT_CONNECTED)
|
|
|
|
+ return -ENOTCONN;
|
|
|
|
|
|
while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
|
|
while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
|
|
|
|
|
|
@@ -3072,7 +3108,6 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
|
|
}
|
|
}
|
|
|
|
|
|
default:
|
|
default:
|
|
- sk->sk_state = BT_DISCONN;
|
|
|
|
sk->sk_err = ECONNRESET;
|
|
sk->sk_err = ECONNRESET;
|
|
l2cap_sock_set_timer(sk, HZ * 5);
|
|
l2cap_sock_set_timer(sk, HZ * 5);
|
|
l2cap_send_disconn_req(conn, sk);
|
|
l2cap_send_disconn_req(conn, sk);
|
|
@@ -3126,16 +3161,6 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
|
|
|
|
|
|
sk->sk_shutdown = SHUTDOWN_MASK;
|
|
sk->sk_shutdown = SHUTDOWN_MASK;
|
|
|
|
|
|
- skb_queue_purge(TX_QUEUE(sk));
|
|
|
|
-
|
|
|
|
- if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
|
|
|
|
- skb_queue_purge(SREJ_QUEUE(sk));
|
|
|
|
- skb_queue_purge(BUSY_QUEUE(sk));
|
|
|
|
- del_timer(&l2cap_pi(sk)->retrans_timer);
|
|
|
|
- del_timer(&l2cap_pi(sk)->monitor_timer);
|
|
|
|
- del_timer(&l2cap_pi(sk)->ack_timer);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
l2cap_chan_del(sk, ECONNRESET);
|
|
l2cap_chan_del(sk, ECONNRESET);
|
|
bh_unlock_sock(sk);
|
|
bh_unlock_sock(sk);
|
|
|
|
|
|
@@ -3158,16 +3183,6 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
|
|
if (!sk)
|
|
if (!sk)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- skb_queue_purge(TX_QUEUE(sk));
|
|
|
|
-
|
|
|
|
- if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
|
|
|
|
- skb_queue_purge(SREJ_QUEUE(sk));
|
|
|
|
- skb_queue_purge(BUSY_QUEUE(sk));
|
|
|
|
- del_timer(&l2cap_pi(sk)->retrans_timer);
|
|
|
|
- del_timer(&l2cap_pi(sk)->monitor_timer);
|
|
|
|
- del_timer(&l2cap_pi(sk)->ack_timer);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
l2cap_chan_del(sk, 0);
|
|
l2cap_chan_del(sk, 0);
|
|
bh_unlock_sock(sk);
|
|
bh_unlock_sock(sk);
|
|
|
|
|