aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorGustavo F. Padovan <padovan@profusion.mobi>2010-05-13 19:50:12 -0400
committerMarcel Holtmann <marcel@holtmann.org>2010-07-21 13:39:05 -0400
commitc13ffa620f15cb28d18268a773464cf51550fa9f (patch)
treef64298291240cb67270966e64977afaad7bec6f5 /net
parent51893f88dd916efead5e24a212c907b2cd35e160 (diff)
Bluetooth: Proper shutdown ERTM when closing the channel
Fix a crash regarding the Monitor Timeout, it was running even after the shutdown of the ACL connection, which doesn't make sense. The same code also fixes another issue, before this patch L2CAP was sending many Disconnections Requests while we have to send only one. The issues are related to each other, a expired Monitor Timeout can trigger a Disconnection Request and then we may have a crash if the link was already deleted. Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/l2cap.c59
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