diff options
Diffstat (limited to 'net/bluetooth/l2cap.c')
-rw-r--r-- | net/bluetooth/l2cap.c | 110 |
1 files changed, 74 insertions, 36 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index daa7a988d9a6..c791fcda7b2d 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -57,7 +57,7 @@ | |||
57 | 57 | ||
58 | #define VERSION "2.15" | 58 | #define VERSION "2.15" |
59 | 59 | ||
60 | static int disable_ertm = 0; | 60 | static int disable_ertm; |
61 | 61 | ||
62 | static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; | 62 | static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; |
63 | static u8 l2cap_fixed_chan[8] = { 0x02, }; | 63 | static u8 l2cap_fixed_chan[8] = { 0x02, }; |
@@ -83,6 +83,18 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, | |||
83 | static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb); | 83 | static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb); |
84 | 84 | ||
85 | /* ---- L2CAP timers ---- */ | 85 | /* ---- L2CAP timers ---- */ |
86 | static void l2cap_sock_set_timer(struct sock *sk, long timeout) | ||
87 | { | ||
88 | BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout); | ||
89 | sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout); | ||
90 | } | ||
91 | |||
92 | static void l2cap_sock_clear_timer(struct sock *sk) | ||
93 | { | ||
94 | BT_DBG("sock %p state %d", sk, sk->sk_state); | ||
95 | sk_stop_timer(sk, &sk->sk_timer); | ||
96 | } | ||
97 | |||
86 | static void l2cap_sock_timeout(unsigned long arg) | 98 | static void l2cap_sock_timeout(unsigned long arg) |
87 | { | 99 | { |
88 | struct sock *sk = (struct sock *) arg; | 100 | struct sock *sk = (struct sock *) arg; |
@@ -92,6 +104,14 @@ static void l2cap_sock_timeout(unsigned long arg) | |||
92 | 104 | ||
93 | bh_lock_sock(sk); | 105 | bh_lock_sock(sk); |
94 | 106 | ||
107 | if (sock_owned_by_user(sk)) { | ||
108 | /* sk is owned by user. Try again later */ | ||
109 | l2cap_sock_set_timer(sk, HZ / 5); | ||
110 | bh_unlock_sock(sk); | ||
111 | sock_put(sk); | ||
112 | return; | ||
113 | } | ||
114 | |||
95 | if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG) | 115 | if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG) |
96 | reason = ECONNREFUSED; | 116 | reason = ECONNREFUSED; |
97 | else if (sk->sk_state == BT_CONNECT && | 117 | else if (sk->sk_state == BT_CONNECT && |
@@ -108,18 +128,6 @@ static void l2cap_sock_timeout(unsigned long arg) | |||
108 | sock_put(sk); | 128 | sock_put(sk); |
109 | } | 129 | } |
110 | 130 | ||
111 | static void l2cap_sock_set_timer(struct sock *sk, long timeout) | ||
112 | { | ||
113 | BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout); | ||
114 | sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout); | ||
115 | } | ||
116 | |||
117 | static void l2cap_sock_clear_timer(struct sock *sk) | ||
118 | { | ||
119 | BT_DBG("sock %p state %d", sk, sk->sk_state); | ||
120 | sk_stop_timer(sk, &sk->sk_timer); | ||
121 | } | ||
122 | |||
123 | /* ---- L2CAP channels ---- */ | 131 | /* ---- L2CAP channels ---- */ |
124 | static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid) | 132 | static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid) |
125 | { | 133 | { |
@@ -743,11 +751,13 @@ found: | |||
743 | /* Find socket with psm and source bdaddr. | 751 | /* Find socket with psm and source bdaddr. |
744 | * Returns closest match. | 752 | * Returns closest match. |
745 | */ | 753 | */ |
746 | static struct sock *__l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) | 754 | static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) |
747 | { | 755 | { |
748 | struct sock *sk = NULL, *sk1 = NULL; | 756 | struct sock *sk = NULL, *sk1 = NULL; |
749 | struct hlist_node *node; | 757 | struct hlist_node *node; |
750 | 758 | ||
759 | read_lock(&l2cap_sk_list.lock); | ||
760 | |||
751 | sk_for_each(sk, node, &l2cap_sk_list.head) { | 761 | sk_for_each(sk, node, &l2cap_sk_list.head) { |
752 | if (state && sk->sk_state != state) | 762 | if (state && sk->sk_state != state) |
753 | continue; | 763 | continue; |
@@ -762,20 +772,10 @@ static struct sock *__l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src | |||
762 | sk1 = sk; | 772 | sk1 = sk; |
763 | } | 773 | } |
764 | } | 774 | } |
765 | return node ? sk : sk1; | ||
766 | } | ||
767 | 775 | ||
768 | /* Find socket with given address (psm, src). | ||
769 | * Returns locked socket */ | ||
770 | static inline struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) | ||
771 | { | ||
772 | struct sock *s; | ||
773 | read_lock(&l2cap_sk_list.lock); | ||
774 | s = __l2cap_get_sock_by_psm(state, psm, src); | ||
775 | if (s) | ||
776 | bh_lock_sock(s); | ||
777 | read_unlock(&l2cap_sk_list.lock); | 776 | read_unlock(&l2cap_sk_list.lock); |
778 | return s; | 777 | |
778 | return node ? sk : sk1; | ||
779 | } | 779 | } |
780 | 780 | ||
781 | static void l2cap_sock_destruct(struct sock *sk) | 781 | static void l2cap_sock_destruct(struct sock *sk) |
@@ -2421,11 +2421,11 @@ static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned | |||
2421 | break; | 2421 | break; |
2422 | 2422 | ||
2423 | case 2: | 2423 | case 2: |
2424 | *val = __le16_to_cpu(*((__le16 *) opt->val)); | 2424 | *val = get_unaligned_le16(opt->val); |
2425 | break; | 2425 | break; |
2426 | 2426 | ||
2427 | case 4: | 2427 | case 4: |
2428 | *val = __le32_to_cpu(*((__le32 *) opt->val)); | 2428 | *val = get_unaligned_le32(opt->val); |
2429 | break; | 2429 | break; |
2430 | 2430 | ||
2431 | default: | 2431 | default: |
@@ -2452,11 +2452,11 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) | |||
2452 | break; | 2452 | break; |
2453 | 2453 | ||
2454 | case 2: | 2454 | case 2: |
2455 | *((__le16 *) opt->val) = cpu_to_le16(val); | 2455 | put_unaligned_le16(val, opt->val); |
2456 | break; | 2456 | break; |
2457 | 2457 | ||
2458 | case 4: | 2458 | case 4: |
2459 | *((__le32 *) opt->val) = cpu_to_le32(val); | 2459 | put_unaligned_le32(val, opt->val); |
2460 | break; | 2460 | break; |
2461 | 2461 | ||
2462 | default: | 2462 | default: |
@@ -2926,6 +2926,8 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2926 | goto sendresp; | 2926 | goto sendresp; |
2927 | } | 2927 | } |
2928 | 2928 | ||
2929 | bh_lock_sock(parent); | ||
2930 | |||
2929 | /* Check if the ACL is secure enough (if not SDP) */ | 2931 | /* Check if the ACL is secure enough (if not SDP) */ |
2930 | if (psm != cpu_to_le16(0x0001) && | 2932 | if (psm != cpu_to_le16(0x0001) && |
2931 | !hci_conn_check_link_mode(conn->hcon)) { | 2933 | !hci_conn_check_link_mode(conn->hcon)) { |
@@ -3078,6 +3080,14 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
3078 | break; | 3080 | break; |
3079 | 3081 | ||
3080 | default: | 3082 | default: |
3083 | /* don't delete l2cap channel if sk is owned by user */ | ||
3084 | if (sock_owned_by_user(sk)) { | ||
3085 | sk->sk_state = BT_DISCONN; | ||
3086 | l2cap_sock_clear_timer(sk); | ||
3087 | l2cap_sock_set_timer(sk, HZ / 5); | ||
3088 | break; | ||
3089 | } | ||
3090 | |||
3081 | l2cap_chan_del(sk, ECONNREFUSED); | 3091 | l2cap_chan_del(sk, ECONNREFUSED); |
3082 | break; | 3092 | break; |
3083 | } | 3093 | } |
@@ -3114,8 +3124,14 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
3114 | if (!sk) | 3124 | if (!sk) |
3115 | return -ENOENT; | 3125 | return -ENOENT; |
3116 | 3126 | ||
3117 | if (sk->sk_state == BT_DISCONN) | 3127 | if (sk->sk_state != BT_CONFIG) { |
3128 | struct l2cap_cmd_rej rej; | ||
3129 | |||
3130 | rej.reason = cpu_to_le16(0x0002); | ||
3131 | l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, | ||
3132 | sizeof(rej), &rej); | ||
3118 | goto unlock; | 3133 | goto unlock; |
3134 | } | ||
3119 | 3135 | ||
3120 | /* Reject if config buffer is too small. */ | 3136 | /* Reject if config buffer is too small. */ |
3121 | len = cmd_len - sizeof(*req); | 3137 | len = cmd_len - sizeof(*req); |
@@ -3283,6 +3299,15 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd | |||
3283 | 3299 | ||
3284 | sk->sk_shutdown = SHUTDOWN_MASK; | 3300 | sk->sk_shutdown = SHUTDOWN_MASK; |
3285 | 3301 | ||
3302 | /* don't delete l2cap channel if sk is owned by user */ | ||
3303 | if (sock_owned_by_user(sk)) { | ||
3304 | sk->sk_state = BT_DISCONN; | ||
3305 | l2cap_sock_clear_timer(sk); | ||
3306 | l2cap_sock_set_timer(sk, HZ / 5); | ||
3307 | bh_unlock_sock(sk); | ||
3308 | return 0; | ||
3309 | } | ||
3310 | |||
3286 | l2cap_chan_del(sk, ECONNRESET); | 3311 | l2cap_chan_del(sk, ECONNRESET); |
3287 | bh_unlock_sock(sk); | 3312 | bh_unlock_sock(sk); |
3288 | 3313 | ||
@@ -3305,6 +3330,15 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd | |||
3305 | if (!sk) | 3330 | if (!sk) |
3306 | return 0; | 3331 | return 0; |
3307 | 3332 | ||
3333 | /* don't delete l2cap channel if sk is owned by user */ | ||
3334 | if (sock_owned_by_user(sk)) { | ||
3335 | sk->sk_state = BT_DISCONN; | ||
3336 | l2cap_sock_clear_timer(sk); | ||
3337 | l2cap_sock_set_timer(sk, HZ / 5); | ||
3338 | bh_unlock_sock(sk); | ||
3339 | return 0; | ||
3340 | } | ||
3341 | |||
3308 | l2cap_chan_del(sk, 0); | 3342 | l2cap_chan_del(sk, 0); |
3309 | bh_unlock_sock(sk); | 3343 | bh_unlock_sock(sk); |
3310 | 3344 | ||
@@ -4134,11 +4168,10 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) | |||
4134 | __mod_retrans_timer(); | 4168 | __mod_retrans_timer(); |
4135 | 4169 | ||
4136 | pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; | 4170 | pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; |
4137 | if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { | 4171 | if (pi->conn_state & L2CAP_CONN_SREJ_SENT) |
4138 | l2cap_send_ack(pi); | 4172 | l2cap_send_ack(pi); |
4139 | } else { | 4173 | else |
4140 | l2cap_ertm_send(sk); | 4174 | l2cap_ertm_send(sk); |
4141 | } | ||
4142 | } | 4175 | } |
4143 | } | 4176 | } |
4144 | 4177 | ||
@@ -4430,6 +4463,8 @@ static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, str | |||
4430 | if (!sk) | 4463 | if (!sk) |
4431 | goto drop; | 4464 | goto drop; |
4432 | 4465 | ||
4466 | bh_lock_sock(sk); | ||
4467 | |||
4433 | BT_DBG("sk %p, len %d", sk, skb->len); | 4468 | BT_DBG("sk %p, len %d", sk, skb->len); |
4434 | 4469 | ||
4435 | if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED) | 4470 | if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED) |
@@ -4841,8 +4876,10 @@ static int __init l2cap_init(void) | |||
4841 | return err; | 4876 | return err; |
4842 | 4877 | ||
4843 | _busy_wq = create_singlethread_workqueue("l2cap"); | 4878 | _busy_wq = create_singlethread_workqueue("l2cap"); |
4844 | if (!_busy_wq) | 4879 | if (!_busy_wq) { |
4845 | goto error; | 4880 | proto_unregister(&l2cap_proto); |
4881 | return -ENOMEM; | ||
4882 | } | ||
4846 | 4883 | ||
4847 | err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); | 4884 | err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); |
4848 | if (err < 0) { | 4885 | if (err < 0) { |
@@ -4870,6 +4907,7 @@ static int __init l2cap_init(void) | |||
4870 | return 0; | 4907 | return 0; |
4871 | 4908 | ||
4872 | error: | 4909 | error: |
4910 | destroy_workqueue(_busy_wq); | ||
4873 | proto_unregister(&l2cap_proto); | 4911 | proto_unregister(&l2cap_proto); |
4874 | return err; | 4912 | return err; |
4875 | } | 4913 | } |