diff options
Diffstat (limited to 'net/bluetooth/l2cap.c')
-rw-r--r-- | net/bluetooth/l2cap.c | 59 |
1 files changed, 37 insertions, 22 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 4af8fc0d512c..4415eb48c6ae 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -272,6 +272,24 @@ static void l2cap_chan_del(struct sock *sk, int err) | |||
272 | parent->sk_data_ready(parent, 0); | 272 | parent->sk_data_ready(parent, 0); |
273 | } else | 273 | } else |
274 | sk->sk_state_change(sk); | 274 | sk->sk_state_change(sk); |
275 | |||
276 | skb_queue_purge(TX_QUEUE(sk)); | ||
277 | |||
278 | if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { | ||
279 | struct srej_list *l, *tmp; | ||
280 | |||
281 | del_timer(&l2cap_pi(sk)->retrans_timer); | ||
282 | del_timer(&l2cap_pi(sk)->monitor_timer); | ||
283 | del_timer(&l2cap_pi(sk)->ack_timer); | ||
284 | |||
285 | skb_queue_purge(SREJ_QUEUE(sk)); | ||
286 | skb_queue_purge(BUSY_QUEUE(sk)); | ||
287 | |||
288 | list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) { | ||
289 | list_del(&l->list); | ||
290 | kfree(l); | ||
291 | } | ||
292 | } | ||
275 | } | 293 | } |
276 | 294 | ||
277 | /* Service level security */ | 295 | /* Service level security */ |
@@ -345,8 +363,12 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) | |||
345 | struct sk_buff *skb; | 363 | struct sk_buff *skb; |
346 | struct l2cap_hdr *lh; | 364 | struct l2cap_hdr *lh; |
347 | struct l2cap_conn *conn = pi->conn; | 365 | struct l2cap_conn *conn = pi->conn; |
366 | struct sock *sk = (struct sock *)pi; | ||
348 | int count, hlen = L2CAP_HDR_SIZE + 2; | 367 | int count, hlen = L2CAP_HDR_SIZE + 2; |
349 | 368 | ||
369 | if (sk->sk_state != BT_CONNECTED) | ||
370 | return; | ||
371 | |||
350 | if (pi->fcs == L2CAP_FCS_CRC16) | 372 | if (pi->fcs == L2CAP_FCS_CRC16) |
351 | hlen += 2; | 373 | hlen += 2; |
352 | 374 | ||
@@ -438,10 +460,23 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk) | |||
438 | { | 460 | { |
439 | struct l2cap_disconn_req req; | 461 | struct l2cap_disconn_req req; |
440 | 462 | ||
463 | if (!conn) | ||
464 | return; | ||
465 | |||
466 | skb_queue_purge(TX_QUEUE(sk)); | ||
467 | |||
468 | if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { | ||
469 | del_timer(&l2cap_pi(sk)->retrans_timer); | ||
470 | del_timer(&l2cap_pi(sk)->monitor_timer); | ||
471 | del_timer(&l2cap_pi(sk)->ack_timer); | ||
472 | } | ||
473 | |||
441 | req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid); | 474 | req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid); |
442 | req.scid = cpu_to_le16(l2cap_pi(sk)->scid); | 475 | req.scid = cpu_to_le16(l2cap_pi(sk)->scid); |
443 | l2cap_send_cmd(conn, l2cap_get_ident(conn), | 476 | l2cap_send_cmd(conn, l2cap_get_ident(conn), |
444 | L2CAP_DISCONN_REQ, sizeof(req), &req); | 477 | L2CAP_DISCONN_REQ, sizeof(req), &req); |
478 | |||
479 | sk->sk_state = BT_DISCONN; | ||
445 | } | 480 | } |
446 | 481 | ||
447 | /* ---- L2CAP connections ---- */ | 482 | /* ---- L2CAP connections ---- */ |
@@ -734,7 +769,6 @@ static void __l2cap_sock_close(struct sock *sk, int reason) | |||
734 | sk->sk_type == SOCK_STREAM) { | 769 | sk->sk_type == SOCK_STREAM) { |
735 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; | 770 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; |
736 | 771 | ||
737 | sk->sk_state = BT_DISCONN; | ||
738 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); | 772 | l2cap_sock_set_timer(sk, sk->sk_sndtimeo); |
739 | l2cap_send_disconn_req(conn, sk); | 773 | l2cap_send_disconn_req(conn, sk); |
740 | } else | 774 | } else |
@@ -1415,6 +1449,8 @@ static int l2cap_ertm_send(struct sock *sk) | |||
1415 | u16 control, fcs; | 1449 | u16 control, fcs; |
1416 | int nsent = 0; | 1450 | int nsent = 0; |
1417 | 1451 | ||
1452 | if (sk->sk_state != BT_CONNECTED) | ||
1453 | return -ENOTCONN; | ||
1418 | 1454 | ||
1419 | while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) { | 1455 | while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) { |
1420 | 1456 | ||
@@ -3072,7 +3108,6 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
3072 | } | 3108 | } |
3073 | 3109 | ||
3074 | default: | 3110 | default: |
3075 | sk->sk_state = BT_DISCONN; | ||
3076 | sk->sk_err = ECONNRESET; | 3111 | sk->sk_err = ECONNRESET; |
3077 | l2cap_sock_set_timer(sk, HZ * 5); | 3112 | l2cap_sock_set_timer(sk, HZ * 5); |
3078 | l2cap_send_disconn_req(conn, sk); | 3113 | l2cap_send_disconn_req(conn, sk); |
@@ -3126,16 +3161,6 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd | |||
3126 | 3161 | ||
3127 | sk->sk_shutdown = SHUTDOWN_MASK; | 3162 | sk->sk_shutdown = SHUTDOWN_MASK; |
3128 | 3163 | ||
3129 | skb_queue_purge(TX_QUEUE(sk)); | ||
3130 | |||
3131 | if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { | ||
3132 | skb_queue_purge(SREJ_QUEUE(sk)); | ||
3133 | skb_queue_purge(BUSY_QUEUE(sk)); | ||
3134 | del_timer(&l2cap_pi(sk)->retrans_timer); | ||
3135 | del_timer(&l2cap_pi(sk)->monitor_timer); | ||
3136 | del_timer(&l2cap_pi(sk)->ack_timer); | ||
3137 | } | ||
3138 | |||
3139 | l2cap_chan_del(sk, ECONNRESET); | 3164 | l2cap_chan_del(sk, ECONNRESET); |
3140 | bh_unlock_sock(sk); | 3165 | bh_unlock_sock(sk); |
3141 | 3166 | ||
@@ -3158,16 +3183,6 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd | |||
3158 | if (!sk) | 3183 | if (!sk) |
3159 | return 0; | 3184 | return 0; |
3160 | 3185 | ||
3161 | skb_queue_purge(TX_QUEUE(sk)); | ||
3162 | |||
3163 | if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { | ||
3164 | skb_queue_purge(SREJ_QUEUE(sk)); | ||
3165 | skb_queue_purge(BUSY_QUEUE(sk)); | ||
3166 | del_timer(&l2cap_pi(sk)->retrans_timer); | ||
3167 | del_timer(&l2cap_pi(sk)->monitor_timer); | ||
3168 | del_timer(&l2cap_pi(sk)->ack_timer); | ||
3169 | } | ||
3170 | |||
3171 | l2cap_chan_del(sk, 0); | 3186 | l2cap_chan_del(sk, 0); |
3172 | bh_unlock_sock(sk); | 3187 | bh_unlock_sock(sk); |
3173 | 3188 | ||