blob: 4b857adc53616e6f6b98c52ba811d51fc981165a [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
7 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation;
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
16 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090017 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090022 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
23 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 SOFTWARE IS DISCLAIMED.
25*/
26
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020027/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30
31#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080032#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
34#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/poll.h>
38#include <linux/fcntl.h>
39#include <linux/init.h>
40#include <linux/interrupt.h>
41#include <linux/socket.h>
42#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080044#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010045#include <linux/debugfs.h>
46#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030047#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030048#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/sock.h>
50
51#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
57
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020058int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020059
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070060static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010061static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030063static struct workqueue_struct *_busy_wq;
64
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020065struct bt_sock_list l2cap_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070066 .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070067};
68
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030069static void l2cap_busy_work(struct work_struct *work);
70
Linus Torvalds1da177e2005-04-16 15:20:36 -070071static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
72 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030073static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030075static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
76
Marcel Holtmann01394182006-07-03 10:02:46 +020077/* ---- L2CAP channels ---- */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030078static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020079{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030080 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030081
82 list_for_each_entry(c, &conn->chan_l, list) {
83 struct sock *s = c->sk;
84 if (l2cap_pi(s)->dcid == cid)
85 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020086 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030087 return NULL;
88
Marcel Holtmann01394182006-07-03 10:02:46 +020089}
90
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030091static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020092{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030093 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030094
95 list_for_each_entry(c, &conn->chan_l, list) {
96 struct sock *s = c->sk;
97 if (l2cap_pi(s)->scid == cid)
98 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020099 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300100 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200101}
102
103/* Find channel with given SCID.
104 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300105static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200106{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300107 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300108
109 read_lock(&conn->chan_lock);
110 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300111 if (c)
112 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300113 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300114 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200115}
116
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300117static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200118{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300119 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300120
121 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300122 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300123 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200124 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300125 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200126}
127
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300128static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200129{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300130 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300131
132 read_lock(&conn->chan_lock);
133 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300134 if (c)
135 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300136 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300137 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200138}
139
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300140static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200141{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300142 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200143
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300144 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300145 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200146 return cid;
147 }
148
149 return 0;
150}
151
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300152struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200153{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300154 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200155
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300156 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
157 if (!chan)
158 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200159
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300160 chan->sk = sk;
161
162 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200163}
164
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300165static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200166{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300167 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200168
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300169 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
170 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200171
Marcel Holtmann2950f212009-02-12 14:02:50 +0100172 conn->disc_reason = 0x13;
173
Marcel Holtmann01394182006-07-03 10:02:46 +0200174 l2cap_pi(sk)->conn = conn;
175
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300176 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Ville Tervob62f3282011-02-10 22:38:50 -0300177 if (conn->hcon->type == LE_LINK) {
178 /* LE connection */
179 l2cap_pi(sk)->omtu = L2CAP_LE_DEFAULT_MTU;
180 l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA;
181 l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA;
182 } else {
183 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300184 l2cap_pi(sk)->scid = l2cap_alloc_cid(conn);
Ville Tervob62f3282011-02-10 22:38:50 -0300185 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
186 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200187 } else if (sk->sk_type == SOCK_DGRAM) {
188 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300189 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
190 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200191 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
192 } else {
193 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300194 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
195 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200196 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
197 }
198
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300199 sock_hold(sk);
200
201 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200202}
203
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900204/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200205 * Must be called on the locked socket. */
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300206void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200207{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300208 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200209 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
210 struct sock *parent = bt_sk(sk)->parent;
211
212 l2cap_sock_clear_timer(sk);
213
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300214 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200215
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900216 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300217 /* Delete from channel list */
218 write_lock_bh(&conn->chan_lock);
219 list_del(&chan->list);
220 write_unlock_bh(&conn->chan_lock);
221 __sock_put(sk);
222
Marcel Holtmann01394182006-07-03 10:02:46 +0200223 l2cap_pi(sk)->conn = NULL;
224 hci_conn_put(conn->hcon);
225 }
226
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200227 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200228 sock_set_flag(sk, SOCK_ZAPPED);
229
230 if (err)
231 sk->sk_err = err;
232
233 if (parent) {
234 bt_accept_unlink(sk);
235 parent->sk_data_ready(parent, 0);
236 } else
237 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300238
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300239 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE &&
240 l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE))
241 goto free;
242
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300243 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300244
245 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
246 struct srej_list *l, *tmp;
247
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300248 del_timer(&chan->retrans_timer);
249 del_timer(&chan->monitor_timer);
250 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300251
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300252 skb_queue_purge(&chan->srej_q);
253 skb_queue_purge(&chan->busy_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300254
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300255 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300256 list_del(&l->list);
257 kfree(l);
258 }
259 }
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300260
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300261free:
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300262 kfree(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200263}
264
Johan Hedberg8556edd32011-01-19 12:06:50 +0530265static inline u8 l2cap_get_auth_type(struct sock *sk)
266{
267 if (sk->sk_type == SOCK_RAW) {
268 switch (l2cap_pi(sk)->sec_level) {
269 case BT_SECURITY_HIGH:
270 return HCI_AT_DEDICATED_BONDING_MITM;
271 case BT_SECURITY_MEDIUM:
272 return HCI_AT_DEDICATED_BONDING;
273 default:
274 return HCI_AT_NO_BONDING;
275 }
276 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
277 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
278 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
279
280 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
281 return HCI_AT_NO_BONDING_MITM;
282 else
283 return HCI_AT_NO_BONDING;
284 } else {
285 switch (l2cap_pi(sk)->sec_level) {
286 case BT_SECURITY_HIGH:
287 return HCI_AT_GENERAL_BONDING_MITM;
288 case BT_SECURITY_MEDIUM:
289 return HCI_AT_GENERAL_BONDING;
290 default:
291 return HCI_AT_NO_BONDING;
292 }
293 }
294}
295
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200296/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100297static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200298{
299 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100300 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200301
Johan Hedberg8556edd32011-01-19 12:06:50 +0530302 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100303
304 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
305 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200306}
307
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200308u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200309{
310 u8 id;
311
312 /* Get next available identificator.
313 * 1 - 128 are used by kernel.
314 * 129 - 199 are reserved.
315 * 200 - 254 are used by utilities like l2ping, etc.
316 */
317
318 spin_lock_bh(&conn->lock);
319
320 if (++conn->tx_ident > 128)
321 conn->tx_ident = 1;
322
323 id = conn->tx_ident;
324
325 spin_unlock_bh(&conn->lock);
326
327 return id;
328}
329
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200330void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200331{
332 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200333 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200334
335 BT_DBG("code 0x%2.2x", code);
336
337 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300338 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200339
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200340 if (lmp_no_flush_capable(conn->hcon->hdev))
341 flags = ACL_START_NO_FLUSH;
342 else
343 flags = ACL_START;
344
345 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200346}
347
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300348static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300349{
350 struct sk_buff *skb;
351 struct l2cap_hdr *lh;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300352 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300353 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300354 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300355 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200356 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300357
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300358 if (sk->sk_state != BT_CONNECTED)
359 return;
360
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300361 if (pi->fcs == L2CAP_FCS_CRC16)
362 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300363
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300364 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300365
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300366 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300367 control |= L2CAP_CTRL_FRAME_TYPE;
368
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300369 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300370 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300371 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300372 }
373
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300374 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300375 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300376 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300377 }
378
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300379 skb = bt_skb_alloc(count, GFP_ATOMIC);
380 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300381 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300382
383 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300384 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300385 lh->cid = cpu_to_le16(pi->dcid);
386 put_unaligned_le16(control, skb_put(skb, 2));
387
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300388 if (pi->fcs == L2CAP_FCS_CRC16) {
389 u16 fcs = crc16(0, (u8 *)lh, count - 2);
390 put_unaligned_le16(fcs, skb_put(skb, 2));
391 }
392
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200393 if (lmp_no_flush_capable(conn->hcon->hdev))
394 flags = ACL_START_NO_FLUSH;
395 else
396 flags = ACL_START;
397
398 hci_send_acl(pi->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300399}
400
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300401static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300402{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300403 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300404 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300405 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300406 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300407 control |= L2CAP_SUPER_RCV_READY;
408
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300409 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300410
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300411 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300412}
413
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300414static inline int __l2cap_no_conn_pending(struct sock *sk)
415{
416 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
417}
418
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300419static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200420{
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300421 struct sock *sk = chan->sk;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200422 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
423
424 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100425 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
426 return;
427
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300428 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200429 struct l2cap_conn_req req;
430 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
431 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200432
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300433 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300434 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200435
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300436 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
437 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200438 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200439 } else {
440 struct l2cap_info_req req;
441 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
442
443 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
444 conn->info_ident = l2cap_get_ident(conn);
445
446 mod_timer(&conn->info_timer, jiffies +
447 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
448
449 l2cap_send_cmd(conn, conn->info_ident,
450 L2CAP_INFO_REQ, sizeof(req), &req);
451 }
452}
453
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300454static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
455{
456 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300457 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300458 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
459
460 switch (mode) {
461 case L2CAP_MODE_ERTM:
462 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
463 case L2CAP_MODE_STREAMING:
464 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
465 default:
466 return 0x00;
467 }
468}
469
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300470void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300471{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300472 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300473 struct l2cap_disconn_req req;
474
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300475 if (!conn)
476 return;
477
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300478 sk = chan->sk;
479
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300480 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300481 del_timer(&chan->retrans_timer);
482 del_timer(&chan->monitor_timer);
483 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300484 }
485
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300486 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
487 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
488 l2cap_send_cmd(conn, l2cap_get_ident(conn),
489 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300490
491 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300492 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300493}
494
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200496static void l2cap_conn_start(struct l2cap_conn *conn)
497{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300498 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200499
500 BT_DBG("conn %p", conn);
501
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300502 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200503
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300504 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300505 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300506
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200507 bh_lock_sock(sk);
508
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300509 if (sk->sk_type != SOCK_SEQPACKET &&
510 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200511 bh_unlock_sock(sk);
512 continue;
513 }
514
515 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300516 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300517
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300518 if (!l2cap_check_security(sk) ||
519 !__l2cap_no_conn_pending(sk)) {
520 bh_unlock_sock(sk);
521 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200522 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300523
524 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
525 conn->feat_mask)
526 && l2cap_pi(sk)->conf_state &
527 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300528 /* __l2cap_sock_close() calls list_del(chan)
529 * so release the lock */
530 read_unlock_bh(&conn->chan_lock);
531 __l2cap_sock_close(sk, ECONNRESET);
532 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300533 bh_unlock_sock(sk);
534 continue;
535 }
536
537 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
538 req.psm = l2cap_pi(sk)->psm;
539
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300540 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300541 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
542
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300543 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
544 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300545
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200546 } else if (sk->sk_state == BT_CONNECT2) {
547 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300548 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200549 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
550 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
551
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100552 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100553 if (bt_sk(sk)->defer_setup) {
554 struct sock *parent = bt_sk(sk)->parent;
555 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
556 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
557 parent->sk_data_ready(parent, 0);
558
559 } else {
560 sk->sk_state = BT_CONFIG;
561 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
562 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
563 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200564 } else {
565 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
566 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
567 }
568
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300569 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
570 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300571
572 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
573 rsp.result != L2CAP_CR_SUCCESS) {
574 bh_unlock_sock(sk);
575 continue;
576 }
577
578 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
579 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300580 l2cap_build_conf_req(chan, buf), buf);
581 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200582 }
583
584 bh_unlock_sock(sk);
585 }
586
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300587 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200588}
589
Ville Tervob62f3282011-02-10 22:38:50 -0300590/* Find socket with cid and source bdaddr.
591 * Returns closest match, locked.
592 */
593static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
594{
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300595 struct sock *sk = NULL, *sk1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300596 struct hlist_node *node;
597
598 read_lock(&l2cap_sk_list.lock);
599
600 sk_for_each(sk, node, &l2cap_sk_list.head) {
601 if (state && sk->sk_state != state)
602 continue;
603
604 if (l2cap_pi(sk)->scid == cid) {
605 /* Exact match. */
606 if (!bacmp(&bt_sk(sk)->src, src))
607 break;
608
609 /* Closest match */
610 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
611 sk1 = sk;
612 }
613 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300614
Ville Tervob62f3282011-02-10 22:38:50 -0300615 read_unlock(&l2cap_sk_list.lock);
616
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300617 return node ? sk : sk1;
Ville Tervob62f3282011-02-10 22:38:50 -0300618}
619
620static void l2cap_le_conn_ready(struct l2cap_conn *conn)
621{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300622 struct sock *parent, *sk;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300623 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300624
625 BT_DBG("");
626
627 /* Check if we have socket listening on cid */
628 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
629 conn->src);
630 if (!parent)
631 return;
632
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300633 bh_lock_sock(parent);
634
Ville Tervob62f3282011-02-10 22:38:50 -0300635 /* Check for backlog size */
636 if (sk_acceptq_is_full(parent)) {
637 BT_DBG("backlog full %d", parent->sk_ack_backlog);
638 goto clean;
639 }
640
641 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
642 if (!sk)
643 goto clean;
644
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300645 chan = l2cap_chan_alloc(sk);
646 if (!chan) {
647 l2cap_sock_kill(sk);
648 goto clean;
649 }
650
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300651 l2cap_pi(sk)->chan = chan;
652
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300653 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300654
655 hci_conn_hold(conn->hcon);
656
657 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300658
Ville Tervob62f3282011-02-10 22:38:50 -0300659 bacpy(&bt_sk(sk)->src, conn->src);
660 bacpy(&bt_sk(sk)->dst, conn->dst);
661
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300662 bt_accept_enqueue(parent, sk);
663
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300664 __l2cap_chan_add(conn, chan);
665
Ville Tervob62f3282011-02-10 22:38:50 -0300666 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
667
668 sk->sk_state = BT_CONNECTED;
669 parent->sk_data_ready(parent, 0);
670
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300671 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300672
673clean:
674 bh_unlock_sock(parent);
675}
676
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200677static void l2cap_conn_ready(struct l2cap_conn *conn)
678{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300679 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200680
681 BT_DBG("conn %p", conn);
682
Ville Tervob62f3282011-02-10 22:38:50 -0300683 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
684 l2cap_le_conn_ready(conn);
685
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300686 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200687
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300688 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300689 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300690
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200691 bh_lock_sock(sk);
692
Ville Tervoacd7d372011-02-10 22:38:49 -0300693 if (conn->hcon->type == LE_LINK) {
694 l2cap_sock_clear_timer(sk);
695 sk->sk_state = BT_CONNECTED;
696 sk->sk_state_change(sk);
697 }
698
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300699 if (sk->sk_type != SOCK_SEQPACKET &&
700 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200701 l2cap_sock_clear_timer(sk);
702 sk->sk_state = BT_CONNECTED;
703 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200704 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300705 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200706
707 bh_unlock_sock(sk);
708 }
709
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300710 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200711}
712
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200713/* Notify sockets that we cannot guaranty reliability anymore */
714static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
715{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300716 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200717
718 BT_DBG("conn %p", conn);
719
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300720 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200721
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300722 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300723 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300724
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100725 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200726 sk->sk_err = err;
727 }
728
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300729 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200730}
731
732static void l2cap_info_timeout(unsigned long arg)
733{
734 struct l2cap_conn *conn = (void *) arg;
735
Marcel Holtmann984947d2009-02-06 23:35:19 +0100736 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100737 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100738
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200739 l2cap_conn_start(conn);
740}
741
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
743{
Marcel Holtmann01394182006-07-03 10:02:46 +0200744 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745
Marcel Holtmann01394182006-07-03 10:02:46 +0200746 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 return conn;
748
Marcel Holtmann01394182006-07-03 10:02:46 +0200749 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
750 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752
753 hcon->l2cap_data = conn;
754 conn->hcon = hcon;
755
Marcel Holtmann01394182006-07-03 10:02:46 +0200756 BT_DBG("hcon %p conn %p", hcon, conn);
757
Ville Tervoacd7d372011-02-10 22:38:49 -0300758 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
759 conn->mtu = hcon->hdev->le_mtu;
760 else
761 conn->mtu = hcon->hdev->acl_mtu;
762
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 conn->src = &hcon->hdev->bdaddr;
764 conn->dst = &hcon->dst;
765
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200766 conn->feat_mask = 0;
767
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300769 rwlock_init(&conn->chan_lock);
770
771 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772
Ville Tervob62f3282011-02-10 22:38:50 -0300773 if (hcon->type != LE_LINK)
774 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000775 (unsigned long) conn);
776
Marcel Holtmann2950f212009-02-12 14:02:50 +0100777 conn->disc_reason = 0x13;
778
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 return conn;
780}
781
Marcel Holtmann01394182006-07-03 10:02:46 +0200782static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783{
Marcel Holtmann01394182006-07-03 10:02:46 +0200784 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300785 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 struct sock *sk;
787
Marcel Holtmann01394182006-07-03 10:02:46 +0200788 if (!conn)
789 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
791 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
792
Wei Yongjun7585b972009-02-25 18:29:52 +0800793 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794
795 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300796 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300797 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300799 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 bh_unlock_sock(sk);
801 l2cap_sock_kill(sk);
802 }
803
Dave Young8e8440f2008-03-03 12:18:55 -0800804 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
805 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800806
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 hcon->l2cap_data = NULL;
808 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809}
810
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300811static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300813 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300814 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300815 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816}
817
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819
820/* Find socket with psm and source bdaddr.
821 * Returns closest match.
822 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000823static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824{
825 struct sock *sk = NULL, *sk1 = NULL;
826 struct hlist_node *node;
827
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000828 read_lock(&l2cap_sk_list.lock);
829
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 sk_for_each(sk, node, &l2cap_sk_list.head) {
831 if (state && sk->sk_state != state)
832 continue;
833
834 if (l2cap_pi(sk)->psm == psm) {
835 /* Exact match. */
836 if (!bacmp(&bt_sk(sk)->src, src))
837 break;
838
839 /* Closest match */
840 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
841 sk1 = sk;
842 }
843 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000846
847 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848}
849
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300850int l2cap_do_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300852 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 bdaddr_t *src = &bt_sk(sk)->src;
854 bdaddr_t *dst = &bt_sk(sk)->dst;
855 struct l2cap_conn *conn;
856 struct hci_conn *hcon;
857 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200858 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200859 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100861 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
862 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300864 hdev = hci_get_route(dst, src);
865 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 return -EHOSTUNREACH;
867
868 hci_dev_lock_bh(hdev);
869
Johan Hedberg8556edd32011-01-19 12:06:50 +0530870 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200871
Ville Tervoacd7d372011-02-10 22:38:49 -0300872 if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
873 hcon = hci_connect(hdev, LE_LINK, dst,
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100874 l2cap_pi(sk)->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300875 else
876 hcon = hci_connect(hdev, ACL_LINK, dst,
877 l2cap_pi(sk)->sec_level, auth_type);
878
Ville Tervo30e76272011-02-22 16:10:53 -0300879 if (IS_ERR(hcon)) {
880 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300882 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883
884 conn = l2cap_conn_add(hcon, 0);
885 if (!conn) {
886 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300887 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 goto done;
889 }
890
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 /* Update source addr of the socket */
892 bacpy(src, conn->src);
893
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300894 l2cap_chan_add(conn, chan);
895
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 sk->sk_state = BT_CONNECT;
897 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
898
899 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300900 if (sk->sk_type != SOCK_SEQPACKET &&
901 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530903 if (l2cap_check_security(sk))
904 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200905 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300906 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 }
908
Ville Tervo30e76272011-02-22 16:10:53 -0300909 err = 0;
910
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911done:
912 hci_dev_unlock_bh(hdev);
913 hci_dev_put(hdev);
914 return err;
915}
916
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200917int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300918{
919 DECLARE_WAITQUEUE(wait, current);
920 int err = 0;
921 int timeo = HZ/5;
922
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200923 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300924 while ((l2cap_pi(sk)->chan->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300925 set_current_state(TASK_INTERRUPTIBLE);
926
927 if (!timeo)
928 timeo = HZ/5;
929
930 if (signal_pending(current)) {
931 err = sock_intr_errno(timeo);
932 break;
933 }
934
935 release_sock(sk);
936 timeo = schedule_timeout(timeo);
937 lock_sock(sk);
938
939 err = sock_error(sk);
940 if (err)
941 break;
942 }
943 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200944 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300945 return err;
946}
947
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300948static void l2cap_monitor_timeout(unsigned long arg)
949{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300950 struct l2cap_chan *chan = (void *) arg;
951 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300952
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300953 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300954
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300955 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -0300956 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300957 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200958 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300959 return;
960 }
961
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300962 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300963 __mod_monitor_timer();
964
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300965 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300966 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300967}
968
969static void l2cap_retrans_timeout(unsigned long arg)
970{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300971 struct l2cap_chan *chan = (void *) arg;
972 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300973
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300974 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300975
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300976 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300977 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300978 __mod_monitor_timer();
979
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300980 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300981
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300982 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300983 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300984}
985
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300986static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300987{
988 struct sk_buff *skb;
989
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300990 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300991 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300992 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300993 break;
994
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300995 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300996 kfree_skb(skb);
997
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300998 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300999 }
1000
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001001 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001002 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001003}
1004
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001005void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001006{
1007 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001008 struct hci_conn *hcon = pi->conn->hcon;
1009 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001010
1011 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1012
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001013 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
1014 flags = ACL_START_NO_FLUSH;
1015 else
1016 flags = ACL_START;
1017
1018 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001019}
1020
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001021void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001022{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001023 struct sock *sk = chan->sk;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001024 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001025 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001026 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001027
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001028 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001029 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001030 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001031 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001032
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001033 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001034 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1035 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001036 }
1037
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001038 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001039
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001040 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001041 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001042}
1043
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001044static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001045{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001046 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001047 struct l2cap_pinfo *pi = l2cap_pi(sk);
1048 struct sk_buff *skb, *tx_skb;
1049 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001050
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001051 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001052 if (!skb)
1053 return;
1054
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001055 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001056 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001057 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001058
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001059 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001060 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001061
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001062 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001063
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001064 if (chan->remote_max_tx &&
1065 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001066 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001067 return;
1068 }
1069
1070 tx_skb = skb_clone(skb, GFP_ATOMIC);
1071 bt_cb(skb)->retries++;
1072 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001073 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001074
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001075 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001076 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001077 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001078 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001079
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001080 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001081 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001082
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001083 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1084
1085 if (pi->fcs == L2CAP_FCS_CRC16) {
1086 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1087 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1088 }
1089
1090 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001091}
1092
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001093int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001094{
1095 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001096 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001097 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001098 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001099 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001100
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001101 if (sk->sk_state != BT_CONNECTED)
1102 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001103
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001104 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001105
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001106 if (chan->remote_max_tx &&
1107 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001108 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001109 break;
1110 }
1111
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001112 tx_skb = skb_clone(skb, GFP_ATOMIC);
1113
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001114 bt_cb(skb)->retries++;
1115
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001116 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001117 control &= L2CAP_CTRL_SAR;
1118
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001119 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001120 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001121 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001122 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001123 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1124 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001125 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1126
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001127
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001128 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001129 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1130 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1131 }
1132
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001133 l2cap_do_send(sk, tx_skb);
1134
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001135 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001136
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001137 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1138 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001139
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301140 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001141 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301142
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001143 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001144
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001145 if (skb_queue_is_last(&chan->tx_q, skb))
1146 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001147 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001148 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001149
1150 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001151 }
1152
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001153 return nsent;
1154}
1155
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001156static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001157{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001158 int ret;
1159
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001160 if (!skb_queue_empty(&chan->tx_q))
1161 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001162
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001163 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001164 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001165 return ret;
1166}
1167
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001168static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001169{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001170 u16 control = 0;
1171
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001172 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001173
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001174 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001175 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001176 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1177 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001178 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001179 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001180
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001181 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001182 return;
1183
1184 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001185 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001186}
1187
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001188static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001189{
1190 struct srej_list *tail;
1191 u16 control;
1192
1193 control = L2CAP_SUPER_SELECT_REJECT;
1194 control |= L2CAP_CTRL_FINAL;
1195
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001196 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001197 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1198
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001199 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001200}
1201
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001202static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203{
1204 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001205 struct sk_buff **frag;
1206 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001208 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001209 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
1211 sent += count;
1212 len -= count;
1213
1214 /* Continuation fragments (no L2CAP header) */
1215 frag = &skb_shinfo(skb)->frag_list;
1216 while (len) {
1217 count = min_t(unsigned int, conn->mtu, len);
1218
1219 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1220 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001221 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001222 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1223 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224
1225 sent += count;
1226 len -= count;
1227
1228 frag = &(*frag)->next;
1229 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
1231 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001232}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001234struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001235{
1236 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1237 struct sk_buff *skb;
1238 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1239 struct l2cap_hdr *lh;
1240
1241 BT_DBG("sk %p len %d", sk, (int)len);
1242
1243 count = min_t(unsigned int, (conn->mtu - hlen), len);
1244 skb = bt_skb_send_alloc(sk, count + hlen,
1245 msg->msg_flags & MSG_DONTWAIT, &err);
1246 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001247 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001248
1249 /* Create L2CAP header */
1250 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1251 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1252 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1253 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1254
1255 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1256 if (unlikely(err < 0)) {
1257 kfree_skb(skb);
1258 return ERR_PTR(err);
1259 }
1260 return skb;
1261}
1262
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001263struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001264{
1265 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1266 struct sk_buff *skb;
1267 int err, count, hlen = L2CAP_HDR_SIZE;
1268 struct l2cap_hdr *lh;
1269
1270 BT_DBG("sk %p len %d", sk, (int)len);
1271
1272 count = min_t(unsigned int, (conn->mtu - hlen), len);
1273 skb = bt_skb_send_alloc(sk, count + hlen,
1274 msg->msg_flags & MSG_DONTWAIT, &err);
1275 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001276 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001277
1278 /* Create L2CAP header */
1279 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1280 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1281 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1282
1283 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1284 if (unlikely(err < 0)) {
1285 kfree_skb(skb);
1286 return ERR_PTR(err);
1287 }
1288 return skb;
1289}
1290
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001291struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001292{
1293 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1294 struct sk_buff *skb;
1295 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1296 struct l2cap_hdr *lh;
1297
1298 BT_DBG("sk %p len %d", sk, (int)len);
1299
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001300 if (!conn)
1301 return ERR_PTR(-ENOTCONN);
1302
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001303 if (sdulen)
1304 hlen += 2;
1305
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001306 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1307 hlen += 2;
1308
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001309 count = min_t(unsigned int, (conn->mtu - hlen), len);
1310 skb = bt_skb_send_alloc(sk, count + hlen,
1311 msg->msg_flags & MSG_DONTWAIT, &err);
1312 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001313 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001314
1315 /* Create L2CAP header */
1316 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1317 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1318 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1319 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001320 if (sdulen)
1321 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001322
1323 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1324 if (unlikely(err < 0)) {
1325 kfree_skb(skb);
1326 return ERR_PTR(err);
1327 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001328
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001329 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1330 put_unaligned_le16(0, skb_put(skb, 2));
1331
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001332 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001333 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334}
1335
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001336int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001337{
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001338 struct sock *sk = chan->sk;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001339 struct sk_buff *skb;
1340 struct sk_buff_head sar_queue;
1341 u16 control;
1342 size_t size = 0;
1343
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001344 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001345 control = L2CAP_SDU_START;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001346 skb = l2cap_create_iframe_pdu(sk, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001347 if (IS_ERR(skb))
1348 return PTR_ERR(skb);
1349
1350 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001351 len -= chan->remote_mps;
1352 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001353
1354 while (len > 0) {
1355 size_t buflen;
1356
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001357 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001358 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001359 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001360 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001361 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001362 buflen = len;
1363 }
1364
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001365 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001366 if (IS_ERR(skb)) {
1367 skb_queue_purge(&sar_queue);
1368 return PTR_ERR(skb);
1369 }
1370
1371 __skb_queue_tail(&sar_queue, skb);
1372 len -= buflen;
1373 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001374 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001375 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1376 if (chan->tx_send_head == NULL)
1377 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001378
1379 return size;
1380}
1381
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382static void l2cap_chan_ready(struct sock *sk)
1383{
1384 struct sock *parent = bt_sk(sk)->parent;
1385
1386 BT_DBG("sk %p, parent %p", sk, parent);
1387
1388 l2cap_pi(sk)->conf_state = 0;
1389 l2cap_sock_clear_timer(sk);
1390
1391 if (!parent) {
1392 /* Outgoing channel.
1393 * Wake up socket sleeping on connect.
1394 */
1395 sk->sk_state = BT_CONNECTED;
1396 sk->sk_state_change(sk);
1397 } else {
1398 /* Incoming channel.
1399 * Wake up socket sleeping on accept.
1400 */
1401 parent->sk_data_ready(parent, 0);
1402 }
1403}
1404
1405/* Copy frame to all raw sockets on that connection */
1406static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1407{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001409 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410
1411 BT_DBG("conn %p", conn);
1412
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001413 read_lock(&conn->chan_lock);
1414 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001415 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 if (sk->sk_type != SOCK_RAW)
1417 continue;
1418
1419 /* Don't send frame to the socket it came from */
1420 if (skb->sk == sk)
1421 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001422 nskb = skb_clone(skb, GFP_ATOMIC);
1423 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 continue;
1425
1426 if (sock_queue_rcv_skb(sk, nskb))
1427 kfree_skb(nskb);
1428 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001429 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430}
1431
1432/* ---- L2CAP signalling commands ---- */
1433static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1434 u8 code, u8 ident, u16 dlen, void *data)
1435{
1436 struct sk_buff *skb, **frag;
1437 struct l2cap_cmd_hdr *cmd;
1438 struct l2cap_hdr *lh;
1439 int len, count;
1440
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001441 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1442 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443
1444 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1445 count = min_t(unsigned int, conn->mtu, len);
1446
1447 skb = bt_skb_alloc(count, GFP_ATOMIC);
1448 if (!skb)
1449 return NULL;
1450
1451 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001452 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001453
1454 if (conn->hcon->type == LE_LINK)
1455 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1456 else
1457 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458
1459 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1460 cmd->code = code;
1461 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001462 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463
1464 if (dlen) {
1465 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1466 memcpy(skb_put(skb, count), data, count);
1467 data += count;
1468 }
1469
1470 len -= skb->len;
1471
1472 /* Continuation fragments (no L2CAP header) */
1473 frag = &skb_shinfo(skb)->frag_list;
1474 while (len) {
1475 count = min_t(unsigned int, conn->mtu, len);
1476
1477 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1478 if (!*frag)
1479 goto fail;
1480
1481 memcpy(skb_put(*frag, count), data, count);
1482
1483 len -= count;
1484 data += count;
1485
1486 frag = &(*frag)->next;
1487 }
1488
1489 return skb;
1490
1491fail:
1492 kfree_skb(skb);
1493 return NULL;
1494}
1495
1496static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1497{
1498 struct l2cap_conf_opt *opt = *ptr;
1499 int len;
1500
1501 len = L2CAP_CONF_OPT_SIZE + opt->len;
1502 *ptr += len;
1503
1504 *type = opt->type;
1505 *olen = opt->len;
1506
1507 switch (opt->len) {
1508 case 1:
1509 *val = *((u8 *) opt->val);
1510 break;
1511
1512 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001513 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 break;
1515
1516 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001517 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 break;
1519
1520 default:
1521 *val = (unsigned long) opt->val;
1522 break;
1523 }
1524
1525 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1526 return len;
1527}
1528
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1530{
1531 struct l2cap_conf_opt *opt = *ptr;
1532
1533 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1534
1535 opt->type = type;
1536 opt->len = len;
1537
1538 switch (len) {
1539 case 1:
1540 *((u8 *) opt->val) = val;
1541 break;
1542
1543 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001544 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 break;
1546
1547 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001548 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 break;
1550
1551 default:
1552 memcpy(opt->val, (void *) val, len);
1553 break;
1554 }
1555
1556 *ptr += L2CAP_CONF_OPT_SIZE + len;
1557}
1558
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001559static void l2cap_ack_timeout(unsigned long arg)
1560{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001561 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001562
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001563 bh_lock_sock(chan->sk);
1564 l2cap_send_ack(chan);
1565 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001566}
1567
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001568static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001569{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001570 struct sock *sk = chan->sk;
1571
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001572 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001573 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001574 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001575 chan->num_acked = 0;
1576 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001577
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001578 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1579 (unsigned long) chan);
1580 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1581 (unsigned long) chan);
1582 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001583
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001584 skb_queue_head_init(&chan->srej_q);
1585 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001586
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001587 INIT_LIST_HEAD(&chan->srej_l);
1588
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001589 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001590
1591 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001592}
1593
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001594static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1595{
1596 switch (mode) {
1597 case L2CAP_MODE_STREAMING:
1598 case L2CAP_MODE_ERTM:
1599 if (l2cap_mode_supported(mode, remote_feat_mask))
1600 return mode;
1601 /* fall through */
1602 default:
1603 return L2CAP_MODE_BASIC;
1604 }
1605}
1606
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001607static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001609 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001611 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 void *ptr = req->data;
1613
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001614 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001616 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001617 goto done;
1618
1619 switch (pi->mode) {
1620 case L2CAP_MODE_STREAMING:
1621 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001622 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001623 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001624
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001625 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001626 default:
1627 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1628 break;
1629 }
1630
1631done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001632 if (pi->imtu != L2CAP_DEFAULT_MTU)
1633 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1634
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001635 switch (pi->mode) {
1636 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001637 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1638 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1639 break;
1640
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001641 rfc.mode = L2CAP_MODE_BASIC;
1642 rfc.txwin_size = 0;
1643 rfc.max_transmit = 0;
1644 rfc.retrans_timeout = 0;
1645 rfc.monitor_timeout = 0;
1646 rfc.max_pdu_size = 0;
1647
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001648 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1649 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001650 break;
1651
1652 case L2CAP_MODE_ERTM:
1653 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001654 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001655 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001656 rfc.retrans_timeout = 0;
1657 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001658 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001659 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001660 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001661
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001662 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1663 (unsigned long) &rfc);
1664
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001665 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1666 break;
1667
1668 if (pi->fcs == L2CAP_FCS_NONE ||
1669 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1670 pi->fcs = L2CAP_FCS_NONE;
1671 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1672 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001673 break;
1674
1675 case L2CAP_MODE_STREAMING:
1676 rfc.mode = L2CAP_MODE_STREAMING;
1677 rfc.txwin_size = 0;
1678 rfc.max_transmit = 0;
1679 rfc.retrans_timeout = 0;
1680 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001681 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001682 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001683 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001684
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001685 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1686 (unsigned long) &rfc);
1687
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001688 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1689 break;
1690
1691 if (pi->fcs == L2CAP_FCS_NONE ||
1692 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1693 pi->fcs = L2CAP_FCS_NONE;
1694 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1695 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001696 break;
1697 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001699 req->dcid = cpu_to_le16(pi->dcid);
1700 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701
1702 return ptr - data;
1703}
1704
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001705static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001707 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001708 struct l2cap_conf_rsp *rsp = data;
1709 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001710 void *req = chan->conf_req;
1711 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001712 int type, hint, olen;
1713 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001714 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001715 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001716 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001718 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001719
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001720 while (len >= L2CAP_CONF_OPT_SIZE) {
1721 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001723 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001724 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001725
1726 switch (type) {
1727 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001728 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001729 break;
1730
1731 case L2CAP_CONF_FLUSH_TO:
1732 pi->flush_to = val;
1733 break;
1734
1735 case L2CAP_CONF_QOS:
1736 break;
1737
Marcel Holtmann6464f352007-10-20 13:39:51 +02001738 case L2CAP_CONF_RFC:
1739 if (olen == sizeof(rfc))
1740 memcpy(&rfc, (void *) val, olen);
1741 break;
1742
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001743 case L2CAP_CONF_FCS:
1744 if (val == L2CAP_FCS_NONE)
1745 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1746
1747 break;
1748
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001749 default:
1750 if (hint)
1751 break;
1752
1753 result = L2CAP_CONF_UNKNOWN;
1754 *((u8 *) ptr++) = type;
1755 break;
1756 }
1757 }
1758
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001759 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001760 goto done;
1761
1762 switch (pi->mode) {
1763 case L2CAP_MODE_STREAMING:
1764 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001765 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1766 pi->mode = l2cap_select_mode(rfc.mode,
1767 pi->conn->feat_mask);
1768 break;
1769 }
1770
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001771 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001772 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001773
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001774 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001775 }
1776
1777done:
1778 if (pi->mode != rfc.mode) {
1779 result = L2CAP_CONF_UNACCEPT;
1780 rfc.mode = pi->mode;
1781
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001782 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001783 return -ECONNREFUSED;
1784
1785 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1786 sizeof(rfc), (unsigned long) &rfc);
1787 }
1788
1789
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001790 if (result == L2CAP_CONF_SUCCESS) {
1791 /* Configure output options and let the other side know
1792 * which ones we don't like. */
1793
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001794 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1795 result = L2CAP_CONF_UNACCEPT;
1796 else {
1797 pi->omtu = mtu;
1798 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1799 }
1800 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001801
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001802 switch (rfc.mode) {
1803 case L2CAP_MODE_BASIC:
1804 pi->fcs = L2CAP_FCS_NONE;
1805 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1806 break;
1807
1808 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001809 chan->remote_tx_win = rfc.txwin_size;
1810 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001811
1812 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1813 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001814
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001815 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001816
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001817 rfc.retrans_timeout =
1818 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1819 rfc.monitor_timeout =
1820 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001821
1822 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001823
1824 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1825 sizeof(rfc), (unsigned long) &rfc);
1826
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001827 break;
1828
1829 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001830 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1831 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001832
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001833 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001834
1835 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001836
1837 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1838 sizeof(rfc), (unsigned long) &rfc);
1839
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001840 break;
1841
1842 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001843 result = L2CAP_CONF_UNACCEPT;
1844
1845 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001846 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001847 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001848
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001849 if (result == L2CAP_CONF_SUCCESS)
1850 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1851 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001852 rsp->scid = cpu_to_le16(pi->dcid);
1853 rsp->result = cpu_to_le16(result);
1854 rsp->flags = cpu_to_le16(0x0000);
1855
1856 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857}
1858
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001859static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1860{
1861 struct l2cap_pinfo *pi = l2cap_pi(sk);
1862 struct l2cap_conf_req *req = data;
1863 void *ptr = req->data;
1864 int type, olen;
1865 unsigned long val;
1866 struct l2cap_conf_rfc rfc;
1867
1868 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1869
1870 while (len >= L2CAP_CONF_OPT_SIZE) {
1871 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1872
1873 switch (type) {
1874 case L2CAP_CONF_MTU:
1875 if (val < L2CAP_DEFAULT_MIN_MTU) {
1876 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001877 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001878 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001879 pi->imtu = val;
1880 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001881 break;
1882
1883 case L2CAP_CONF_FLUSH_TO:
1884 pi->flush_to = val;
1885 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1886 2, pi->flush_to);
1887 break;
1888
1889 case L2CAP_CONF_RFC:
1890 if (olen == sizeof(rfc))
1891 memcpy(&rfc, (void *)val, olen);
1892
1893 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1894 rfc.mode != pi->mode)
1895 return -ECONNREFUSED;
1896
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001897 pi->fcs = 0;
1898
1899 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1900 sizeof(rfc), (unsigned long) &rfc);
1901 break;
1902 }
1903 }
1904
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001905 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1906 return -ECONNREFUSED;
1907
1908 pi->mode = rfc.mode;
1909
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001910 if (*result == L2CAP_CONF_SUCCESS) {
1911 switch (rfc.mode) {
1912 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001913 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1914 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001915 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001916 break;
1917 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001918 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001919 }
1920 }
1921
1922 req->dcid = cpu_to_le16(pi->dcid);
1923 req->flags = cpu_to_le16(0x0000);
1924
1925 return ptr - data;
1926}
1927
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001928static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929{
1930 struct l2cap_conf_rsp *rsp = data;
1931 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001933 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001935 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001936 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001937 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
1939 return ptr - data;
1940}
1941
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001942void __l2cap_connect_rsp_defer(struct sock *sk)
1943{
1944 struct l2cap_conn_rsp rsp;
1945 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1946 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
1947 u8 buf[128];
1948
1949 sk->sk_state = BT_CONFIG;
1950
1951 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1952 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1953 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1954 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1955 l2cap_send_cmd(conn, chan->ident,
1956 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1957
1958 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
1959 return;
1960
1961 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
1962 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1963 l2cap_build_conf_req(chan, buf), buf);
1964 chan->num_conf_req++;
1965}
1966
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001967static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1968{
1969 struct l2cap_pinfo *pi = l2cap_pi(sk);
1970 int type, olen;
1971 unsigned long val;
1972 struct l2cap_conf_rfc rfc;
1973
1974 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1975
1976 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1977 return;
1978
1979 while (len >= L2CAP_CONF_OPT_SIZE) {
1980 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1981
1982 switch (type) {
1983 case L2CAP_CONF_RFC:
1984 if (olen == sizeof(rfc))
1985 memcpy(&rfc, (void *)val, olen);
1986 goto done;
1987 }
1988 }
1989
1990done:
1991 switch (rfc.mode) {
1992 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001993 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1994 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001995 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1996 break;
1997 case L2CAP_MODE_STREAMING:
1998 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1999 }
2000}
2001
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002002static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2003{
2004 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2005
2006 if (rej->reason != 0x0000)
2007 return 0;
2008
2009 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2010 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002011 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002012
2013 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002014 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002015
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002016 l2cap_conn_start(conn);
2017 }
2018
2019 return 0;
2020}
2021
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2023{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2025 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002026 struct l2cap_chan *chan = NULL;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002027 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002028 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029
2030 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002031 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032
2033 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2034
2035 /* Check if we have socket listening on psm */
2036 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2037 if (!parent) {
2038 result = L2CAP_CR_BAD_PSM;
2039 goto sendresp;
2040 }
2041
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002042 bh_lock_sock(parent);
2043
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002044 /* Check if the ACL is secure enough (if not SDP) */
2045 if (psm != cpu_to_le16(0x0001) &&
2046 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002047 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002048 result = L2CAP_CR_SEC_BLOCK;
2049 goto response;
2050 }
2051
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 result = L2CAP_CR_NO_MEM;
2053
2054 /* Check for backlog size */
2055 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002056 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 goto response;
2058 }
2059
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002060 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 if (!sk)
2062 goto response;
2063
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002064 chan = l2cap_chan_alloc(sk);
2065 if (!chan) {
2066 l2cap_sock_kill(sk);
2067 goto response;
2068 }
2069
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03002070 l2cap_pi(sk)->chan = chan;
2071
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002072 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073
2074 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002075 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2076 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 sock_set_flag(sk, SOCK_ZAPPED);
2078 l2cap_sock_kill(sk);
2079 goto response;
2080 }
2081
2082 hci_conn_hold(conn->hcon);
2083
2084 l2cap_sock_init(sk, parent);
2085 bacpy(&bt_sk(sk)->src, conn->src);
2086 bacpy(&bt_sk(sk)->dst, conn->dst);
2087 l2cap_pi(sk)->psm = psm;
2088 l2cap_pi(sk)->dcid = scid;
2089
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002090 bt_accept_enqueue(parent, sk);
2091
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002092 __l2cap_chan_add(conn, chan);
2093
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094 dcid = l2cap_pi(sk)->scid;
2095
2096 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2097
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002098 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099
Marcel Holtmann984947d2009-02-06 23:35:19 +01002100 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002101 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002102 if (bt_sk(sk)->defer_setup) {
2103 sk->sk_state = BT_CONNECT2;
2104 result = L2CAP_CR_PEND;
2105 status = L2CAP_CS_AUTHOR_PEND;
2106 parent->sk_data_ready(parent, 0);
2107 } else {
2108 sk->sk_state = BT_CONFIG;
2109 result = L2CAP_CR_SUCCESS;
2110 status = L2CAP_CS_NO_INFO;
2111 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002112 } else {
2113 sk->sk_state = BT_CONNECT2;
2114 result = L2CAP_CR_PEND;
2115 status = L2CAP_CS_AUTHEN_PEND;
2116 }
2117 } else {
2118 sk->sk_state = BT_CONNECT2;
2119 result = L2CAP_CR_PEND;
2120 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 }
2122
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002123 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124
2125response:
2126 bh_unlock_sock(parent);
2127
2128sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002129 rsp.scid = cpu_to_le16(scid);
2130 rsp.dcid = cpu_to_le16(dcid);
2131 rsp.result = cpu_to_le16(result);
2132 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002134
2135 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2136 struct l2cap_info_req info;
2137 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2138
2139 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2140 conn->info_ident = l2cap_get_ident(conn);
2141
2142 mod_timer(&conn->info_timer, jiffies +
2143 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2144
2145 l2cap_send_cmd(conn, conn->info_ident,
2146 L2CAP_INFO_REQ, sizeof(info), &info);
2147 }
2148
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002149 if (chan && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002150 result == L2CAP_CR_SUCCESS) {
2151 u8 buf[128];
2152 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2153 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002154 l2cap_build_conf_req(chan, buf), buf);
2155 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002156 }
2157
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 return 0;
2159}
2160
2161static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2162{
2163 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2164 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002165 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 struct sock *sk;
2167 u8 req[128];
2168
2169 scid = __le16_to_cpu(rsp->scid);
2170 dcid = __le16_to_cpu(rsp->dcid);
2171 result = __le16_to_cpu(rsp->result);
2172 status = __le16_to_cpu(rsp->status);
2173
2174 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2175
2176 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002177 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002178 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002179 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002181 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002182 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002183 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 }
2185
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002186 sk = chan->sk;
2187
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 switch (result) {
2189 case L2CAP_CR_SUCCESS:
2190 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002191 chan->ident = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002193 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2194
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002195 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2196 break;
2197
2198 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2199
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002201 l2cap_build_conf_req(chan, req), req);
2202 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 break;
2204
2205 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002206 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 break;
2208
2209 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002210 /* don't delete l2cap channel if sk is owned by user */
2211 if (sock_owned_by_user(sk)) {
2212 sk->sk_state = BT_DISCONN;
2213 l2cap_sock_clear_timer(sk);
2214 l2cap_sock_set_timer(sk, HZ / 5);
2215 break;
2216 }
2217
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002218 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219 break;
2220 }
2221
2222 bh_unlock_sock(sk);
2223 return 0;
2224}
2225
Mat Martineau8c462b62010-08-24 15:35:42 -07002226static inline void set_default_fcs(struct l2cap_pinfo *pi)
2227{
2228 /* FCS is enabled only in ERTM or streaming mode, if one or both
2229 * sides request it.
2230 */
2231 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2232 pi->fcs = L2CAP_FCS_NONE;
2233 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2234 pi->fcs = L2CAP_FCS_CRC16;
2235}
2236
Al Viro88219a02007-07-29 00:17:25 -07002237static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238{
2239 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2240 u16 dcid, flags;
2241 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002242 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002244 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245
2246 dcid = __le16_to_cpu(req->dcid);
2247 flags = __le16_to_cpu(req->flags);
2248
2249 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2250
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002251 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002252 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253 return -ENOENT;
2254
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002255 sk = chan->sk;
2256
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002257 if (sk->sk_state != BT_CONFIG) {
2258 struct l2cap_cmd_rej rej;
2259
2260 rej.reason = cpu_to_le16(0x0002);
2261 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2262 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002263 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002264 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002265
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002266 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002267 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002268 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002269 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2270 l2cap_build_conf_rsp(sk, rsp,
2271 L2CAP_CONF_REJECT, flags), rsp);
2272 goto unlock;
2273 }
2274
2275 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002276 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2277 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278
2279 if (flags & 0x0001) {
2280 /* Incomplete config. Send empty response. */
2281 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002282 l2cap_build_conf_rsp(sk, rsp,
2283 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284 goto unlock;
2285 }
2286
2287 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002288 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002289 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002290 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002292 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002294 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002295 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002296
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002297 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002298 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002299
Marcel Holtmann876d9482007-10-20 13:35:42 +02002300 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2301 goto unlock;
2302
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002304 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002305
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002307
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002308 chan->next_tx_seq = 0;
2309 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002310 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002311 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002312 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002313
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002315 goto unlock;
2316 }
2317
2318 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002319 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002320 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002322 l2cap_build_conf_req(chan, buf), buf);
2323 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 }
2325
2326unlock:
2327 bh_unlock_sock(sk);
2328 return 0;
2329}
2330
2331static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2332{
2333 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2334 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002335 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002337 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338
2339 scid = __le16_to_cpu(rsp->scid);
2340 flags = __le16_to_cpu(rsp->flags);
2341 result = __le16_to_cpu(rsp->result);
2342
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002343 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2344 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002346 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002347 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 return 0;
2349
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002350 sk = chan->sk;
2351
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 switch (result) {
2353 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002354 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355 break;
2356
2357 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002358 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002359 char req[64];
2360
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002361 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002362 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002363 goto done;
2364 }
2365
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002366 /* throw out any old stored conf requests */
2367 result = L2CAP_CONF_SUCCESS;
2368 len = l2cap_parse_conf_rsp(sk, rsp->data,
2369 len, req, &result);
2370 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002371 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002372 goto done;
2373 }
2374
2375 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2376 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002377 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002378 if (result != L2CAP_CONF_SUCCESS)
2379 goto done;
2380 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 }
2382
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002383 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002384 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002386 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 goto done;
2388 }
2389
2390 if (flags & 0x01)
2391 goto done;
2392
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2394
2395 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002396 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002397
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002399 chan->next_tx_seq = 0;
2400 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002401 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002402 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002403 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002404
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 l2cap_chan_ready(sk);
2406 }
2407
2408done:
2409 bh_unlock_sock(sk);
2410 return 0;
2411}
2412
2413static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2414{
2415 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2416 struct l2cap_disconn_rsp rsp;
2417 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002418 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419 struct sock *sk;
2420
2421 scid = __le16_to_cpu(req->scid);
2422 dcid = __le16_to_cpu(req->dcid);
2423
2424 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2425
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002426 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002427 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 return 0;
2429
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002430 sk = chan->sk;
2431
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002432 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2433 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2435
2436 sk->sk_shutdown = SHUTDOWN_MASK;
2437
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002438 /* don't delete l2cap channel if sk is owned by user */
2439 if (sock_owned_by_user(sk)) {
2440 sk->sk_state = BT_DISCONN;
2441 l2cap_sock_clear_timer(sk);
2442 l2cap_sock_set_timer(sk, HZ / 5);
2443 bh_unlock_sock(sk);
2444 return 0;
2445 }
2446
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002447 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448 bh_unlock_sock(sk);
2449
2450 l2cap_sock_kill(sk);
2451 return 0;
2452}
2453
2454static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2455{
2456 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2457 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002458 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 struct sock *sk;
2460
2461 scid = __le16_to_cpu(rsp->scid);
2462 dcid = __le16_to_cpu(rsp->dcid);
2463
2464 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2465
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002466 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002467 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468 return 0;
2469
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002470 sk = chan->sk;
2471
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002472 /* don't delete l2cap channel if sk is owned by user */
2473 if (sock_owned_by_user(sk)) {
2474 sk->sk_state = BT_DISCONN;
2475 l2cap_sock_clear_timer(sk);
2476 l2cap_sock_set_timer(sk, HZ / 5);
2477 bh_unlock_sock(sk);
2478 return 0;
2479 }
2480
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002481 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482 bh_unlock_sock(sk);
2483
2484 l2cap_sock_kill(sk);
2485 return 0;
2486}
2487
2488static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2489{
2490 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491 u16 type;
2492
2493 type = __le16_to_cpu(req->type);
2494
2495 BT_DBG("type 0x%4.4x", type);
2496
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002497 if (type == L2CAP_IT_FEAT_MASK) {
2498 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002499 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002500 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2501 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2502 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002503 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002504 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2505 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002506 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002507 l2cap_send_cmd(conn, cmd->ident,
2508 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002509 } else if (type == L2CAP_IT_FIXED_CHAN) {
2510 u8 buf[12];
2511 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2512 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2513 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2514 memcpy(buf + 4, l2cap_fixed_chan, 8);
2515 l2cap_send_cmd(conn, cmd->ident,
2516 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002517 } else {
2518 struct l2cap_info_rsp rsp;
2519 rsp.type = cpu_to_le16(type);
2520 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2521 l2cap_send_cmd(conn, cmd->ident,
2522 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2523 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524
2525 return 0;
2526}
2527
2528static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2529{
2530 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2531 u16 type, result;
2532
2533 type = __le16_to_cpu(rsp->type);
2534 result = __le16_to_cpu(rsp->result);
2535
2536 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2537
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002538 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2539 if (cmd->ident != conn->info_ident ||
2540 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2541 return 0;
2542
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002543 del_timer(&conn->info_timer);
2544
Ville Tervoadb08ed2010-08-04 09:43:33 +03002545 if (result != L2CAP_IR_SUCCESS) {
2546 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2547 conn->info_ident = 0;
2548
2549 l2cap_conn_start(conn);
2550
2551 return 0;
2552 }
2553
Marcel Holtmann984947d2009-02-06 23:35:19 +01002554 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002555 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002556
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002557 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002558 struct l2cap_info_req req;
2559 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2560
2561 conn->info_ident = l2cap_get_ident(conn);
2562
2563 l2cap_send_cmd(conn, conn->info_ident,
2564 L2CAP_INFO_REQ, sizeof(req), &req);
2565 } else {
2566 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2567 conn->info_ident = 0;
2568
2569 l2cap_conn_start(conn);
2570 }
2571 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002572 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002573 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002574
2575 l2cap_conn_start(conn);
2576 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002577
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 return 0;
2579}
2580
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002581static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002582 u16 to_multiplier)
2583{
2584 u16 max_latency;
2585
2586 if (min > max || min < 6 || max > 3200)
2587 return -EINVAL;
2588
2589 if (to_multiplier < 10 || to_multiplier > 3200)
2590 return -EINVAL;
2591
2592 if (max >= to_multiplier * 8)
2593 return -EINVAL;
2594
2595 max_latency = (to_multiplier * 8 / max) - 1;
2596 if (latency > 499 || latency > max_latency)
2597 return -EINVAL;
2598
2599 return 0;
2600}
2601
2602static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2603 struct l2cap_cmd_hdr *cmd, u8 *data)
2604{
2605 struct hci_conn *hcon = conn->hcon;
2606 struct l2cap_conn_param_update_req *req;
2607 struct l2cap_conn_param_update_rsp rsp;
2608 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002609 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002610
2611 if (!(hcon->link_mode & HCI_LM_MASTER))
2612 return -EINVAL;
2613
2614 cmd_len = __le16_to_cpu(cmd->len);
2615 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2616 return -EPROTO;
2617
2618 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002619 min = __le16_to_cpu(req->min);
2620 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002621 latency = __le16_to_cpu(req->latency);
2622 to_multiplier = __le16_to_cpu(req->to_multiplier);
2623
2624 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2625 min, max, latency, to_multiplier);
2626
2627 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002628
2629 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2630 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002631 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2632 else
2633 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2634
2635 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2636 sizeof(rsp), &rsp);
2637
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002638 if (!err)
2639 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2640
Claudio Takahaside731152011-02-11 19:28:55 -02002641 return 0;
2642}
2643
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002644static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2645 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2646{
2647 int err = 0;
2648
2649 switch (cmd->code) {
2650 case L2CAP_COMMAND_REJ:
2651 l2cap_command_rej(conn, cmd, data);
2652 break;
2653
2654 case L2CAP_CONN_REQ:
2655 err = l2cap_connect_req(conn, cmd, data);
2656 break;
2657
2658 case L2CAP_CONN_RSP:
2659 err = l2cap_connect_rsp(conn, cmd, data);
2660 break;
2661
2662 case L2CAP_CONF_REQ:
2663 err = l2cap_config_req(conn, cmd, cmd_len, data);
2664 break;
2665
2666 case L2CAP_CONF_RSP:
2667 err = l2cap_config_rsp(conn, cmd, data);
2668 break;
2669
2670 case L2CAP_DISCONN_REQ:
2671 err = l2cap_disconnect_req(conn, cmd, data);
2672 break;
2673
2674 case L2CAP_DISCONN_RSP:
2675 err = l2cap_disconnect_rsp(conn, cmd, data);
2676 break;
2677
2678 case L2CAP_ECHO_REQ:
2679 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2680 break;
2681
2682 case L2CAP_ECHO_RSP:
2683 break;
2684
2685 case L2CAP_INFO_REQ:
2686 err = l2cap_information_req(conn, cmd, data);
2687 break;
2688
2689 case L2CAP_INFO_RSP:
2690 err = l2cap_information_rsp(conn, cmd, data);
2691 break;
2692
2693 default:
2694 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2695 err = -EINVAL;
2696 break;
2697 }
2698
2699 return err;
2700}
2701
2702static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2703 struct l2cap_cmd_hdr *cmd, u8 *data)
2704{
2705 switch (cmd->code) {
2706 case L2CAP_COMMAND_REJ:
2707 return 0;
2708
2709 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002710 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002711
2712 case L2CAP_CONN_PARAM_UPDATE_RSP:
2713 return 0;
2714
2715 default:
2716 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2717 return -EINVAL;
2718 }
2719}
2720
2721static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2722 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723{
2724 u8 *data = skb->data;
2725 int len = skb->len;
2726 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002727 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728
2729 l2cap_raw_recv(conn, skb);
2730
2731 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002732 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2734 data += L2CAP_CMD_HDR_SIZE;
2735 len -= L2CAP_CMD_HDR_SIZE;
2736
Al Viro88219a02007-07-29 00:17:25 -07002737 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738
Al Viro88219a02007-07-29 00:17:25 -07002739 BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740
Al Viro88219a02007-07-29 00:17:25 -07002741 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742 BT_DBG("corrupted command");
2743 break;
2744 }
2745
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002746 if (conn->hcon->type == LE_LINK)
2747 err = l2cap_le_sig_cmd(conn, &cmd, data);
2748 else
2749 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750
2751 if (err) {
2752 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002753
2754 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755
2756 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002757 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2759 }
2760
Al Viro88219a02007-07-29 00:17:25 -07002761 data += cmd_len;
2762 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 }
2764
2765 kfree_skb(skb);
2766}
2767
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002768static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2769{
2770 u16 our_fcs, rcv_fcs;
2771 int hdr_size = L2CAP_HDR_SIZE + 2;
2772
2773 if (pi->fcs == L2CAP_FCS_CRC16) {
2774 skb_trim(skb, skb->len - 2);
2775 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2776 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2777
2778 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002779 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002780 }
2781 return 0;
2782}
2783
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002784static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002785{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002786 u16 control = 0;
2787
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002788 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002789
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002790 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002791
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002792 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002793 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002794 l2cap_send_sframe(chan, control);
2795 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002796 }
2797
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002798 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2799 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002800
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002801 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002802
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002803 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002804 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002805 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002806 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002807 }
2808}
2809
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002810static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u8 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002811{
2812 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002813 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002814
2815 bt_cb(skb)->tx_seq = tx_seq;
2816 bt_cb(skb)->sar = sar;
2817
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002818 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002819 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002820 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002821 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002822 }
2823
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002824 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002825 if (tx_seq_offset < 0)
2826 tx_seq_offset += 64;
2827
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002828 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002829 if (bt_cb(next_skb)->tx_seq == tx_seq)
2830 return -EINVAL;
2831
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002832 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002833 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002834 if (next_tx_seq_offset < 0)
2835 next_tx_seq_offset += 64;
2836
2837 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002838 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002839 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002840 }
2841
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002842 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002843 break;
2844
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002845 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002846
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002847 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002848
2849 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002850}
2851
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002852static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002853{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002854 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002855 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002856 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002857
2858 switch (control & L2CAP_CTRL_SAR) {
2859 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002860 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002861 goto drop;
2862
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002863 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002864 if (!err)
2865 return err;
2866
2867 break;
2868
2869 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002870 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002871 goto drop;
2872
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002873 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002874
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002875 if (chan->sdu_len > pi->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002876 goto disconnect;
2877
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002878 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
2879 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002880 return -ENOMEM;
2881
2882 /* pull sdu_len bytes only after alloc, because of Local Busy
2883 * condition we have to be sure that this will be executed
2884 * only once, i.e., when alloc does not fail */
2885 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002886
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002887 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002888
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002889 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002890 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002891 break;
2892
2893 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002894 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002895 goto disconnect;
2896
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002897 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002898 goto disconnect;
2899
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002900 chan->partial_sdu_len += skb->len;
2901 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002902 goto drop;
2903
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002904 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002905
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002906 break;
2907
2908 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002909 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002910 goto disconnect;
2911
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002912 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002913 goto disconnect;
2914
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002915 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002916 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002917
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002918 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002919 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002920
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002921 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002922 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002923
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002924 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002925 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002926
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002927 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002928 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002929 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002930 return -ENOMEM;
2931 }
2932
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002933 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002934 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002935 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002936 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002937 return err;
2938 }
2939
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002940 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2941 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002942
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002943 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002944 break;
2945 }
2946
2947 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002948 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002949
2950drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002951 kfree_skb(chan->sdu);
2952 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002953
2954disconnect:
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002955 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002956 kfree_skb(skb);
2957 return 0;
2958}
2959
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002960static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002961{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002962 struct sk_buff *skb;
2963 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002964 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002965
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002966 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002967 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002968 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002969 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002970 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002971 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002972 }
2973
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002974 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002975 }
2976
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002977 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002978 goto done;
2979
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002980 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002981 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002982 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002983 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002984
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002985 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002986 __mod_monitor_timer();
2987
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002988 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002989
2990done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002991 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2992 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002993
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002994 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002995
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002996 return 0;
2997}
2998
2999static void l2cap_busy_work(struct work_struct *work)
3000{
3001 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003002 struct l2cap_chan *chan =
3003 container_of(work, struct l2cap_chan, busy_work);
3004 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003005 int n_tries = 0, timeo = HZ/5, err;
3006 struct sk_buff *skb;
3007
3008 lock_sock(sk);
3009
3010 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003011 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003012 set_current_state(TASK_INTERRUPTIBLE);
3013
3014 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3015 err = -EBUSY;
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003016 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003017 break;
3018 }
3019
3020 if (!timeo)
3021 timeo = HZ/5;
3022
3023 if (signal_pending(current)) {
3024 err = sock_intr_errno(timeo);
3025 break;
3026 }
3027
3028 release_sock(sk);
3029 timeo = schedule_timeout(timeo);
3030 lock_sock(sk);
3031
3032 err = sock_error(sk);
3033 if (err)
3034 break;
3035
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003036 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003037 break;
3038 }
3039
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003040 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003041 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003042
3043 release_sock(sk);
3044}
3045
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003046static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003047{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003048 int sctrl, err;
3049
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003050 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003051 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003052 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003053 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003054
3055
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003056 }
3057
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003058 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003059 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003060 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003061 return err;
3062 }
3063
3064 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003065 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003066
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003067 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003068 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003069 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003070
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003071 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003072 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003073 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003074
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003075 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003076
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003077 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003078
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003079 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003080
3081 return err;
3082}
3083
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003084static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003085{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003086 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003087 struct sk_buff *_skb;
3088 int err = -EINVAL;
3089
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003090 /*
3091 * TODO: We have to notify the userland if some data is lost with the
3092 * Streaming Mode.
3093 */
3094
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003095 switch (control & L2CAP_CTRL_SAR) {
3096 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003097 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003098 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003099 break;
3100 }
3101
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003102 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003103 if (!err)
3104 return 0;
3105
3106 break;
3107
3108 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003109 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003110 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003111 break;
3112 }
3113
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003114 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003115 skb_pull(skb, 2);
3116
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003117 if (chan->sdu_len > pi->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003118 err = -EMSGSIZE;
3119 break;
3120 }
3121
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003122 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3123 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003124 err = -ENOMEM;
3125 break;
3126 }
3127
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003128 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003129
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003130 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003131 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003132 err = 0;
3133 break;
3134
3135 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003136 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003137 break;
3138
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003139 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003140
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003141 chan->partial_sdu_len += skb->len;
3142 if (chan->partial_sdu_len > chan->sdu_len)
3143 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003144 else
3145 err = 0;
3146
3147 break;
3148
3149 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003150 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003151 break;
3152
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003153 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003154
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003155 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003156 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003157
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003158 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003159 goto drop;
3160
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003161 if (chan->partial_sdu_len == chan->sdu_len) {
3162 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003163 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003164 if (err < 0)
3165 kfree_skb(_skb);
3166 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003167 err = 0;
3168
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003169drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003170 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003171 break;
3172 }
3173
3174 kfree_skb(skb);
3175 return err;
3176}
3177
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003178static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003179{
3180 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003181 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003182
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003183 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003184 if (bt_cb(skb)->tx_seq != tx_seq)
3185 break;
3186
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003187 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003188 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003189 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003190 chan->buffer_seq_srej =
3191 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003192 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003193 }
3194}
3195
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003196static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003197{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003198 struct srej_list *l, *tmp;
3199 u16 control;
3200
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003201 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003202 if (l->tx_seq == tx_seq) {
3203 list_del(&l->list);
3204 kfree(l);
3205 return;
3206 }
3207 control = L2CAP_SUPER_SELECT_REJECT;
3208 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003209 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003210 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003211 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003212 }
3213}
3214
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003215static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003216{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003217 struct srej_list *new;
3218 u16 control;
3219
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003220 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003221 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003222 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003223 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003224
3225 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003226 new->tx_seq = chan->expected_tx_seq;
3227 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003228 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003229 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003230 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003231}
3232
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003233static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003234{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003235 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003236 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003237 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003238 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003239 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003240 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003241 int err = 0;
3242
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003243 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3244 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003245
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003246 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003247 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003248 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003249 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003250 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003251 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003252 }
3253
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003254 chan->expected_ack_seq = req_seq;
3255 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003256
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003257 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003258 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003259
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003260 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003261 if (tx_seq_offset < 0)
3262 tx_seq_offset += 64;
3263
3264 /* invalid tx_seq */
3265 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003266 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003267 goto drop;
3268 }
3269
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003270 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003271 goto drop;
3272
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003273 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003274 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003275
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003276 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003277 struct srej_list, list);
3278 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003279 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003280 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003281
3282 list_del(&first->list);
3283 kfree(first);
3284
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003285 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003286 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003287 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3288 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003289 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003290 }
3291 } else {
3292 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003293
3294 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003295 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003296 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003297
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003298 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003299 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003300 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003301 return 0;
3302 }
3303 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003304 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003305 }
3306 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003307 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003308 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003309 if (expected_tx_seq_offset < 0)
3310 expected_tx_seq_offset += 64;
3311
3312 /* duplicated tx_seq */
3313 if (tx_seq_offset < expected_tx_seq_offset)
3314 goto drop;
3315
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003316 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003317
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003318 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003319
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003320 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003321 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003322
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003323 __skb_queue_head_init(&chan->srej_q);
3324 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003325 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003326
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003327 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003328
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003329 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003330
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003331 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003332 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003333 return 0;
3334
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003335expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003336 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003337
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003338 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003339 bt_cb(skb)->tx_seq = tx_seq;
3340 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003341 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003342 return 0;
3343 }
3344
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003345 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003346 if (err < 0)
3347 return 0;
3348
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003349 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003350 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3351 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003352 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003353 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003354 }
3355
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003356 __mod_ack_timer();
3357
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003358 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3359 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003360 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003361
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003362 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003363
3364drop:
3365 kfree_skb(skb);
3366 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003367}
3368
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003369static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003370{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003371 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003372 rx_control);
3373
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003374 chan->expected_ack_seq = __get_reqseq(rx_control);
3375 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003376
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003377 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003378 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3379 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3380 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003381 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003382 __mod_retrans_timer();
3383
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003384 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3385 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003386 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003387 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003388 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003389
3390 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003391 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003392
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003393 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3394 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003395 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003396 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003397
3398 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003399 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003400 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003401 __mod_retrans_timer();
3402
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003403 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3404 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3405 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003406 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003407 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003408 }
3409}
3410
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003411static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003412{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003413 u8 tx_seq = __get_reqseq(rx_control);
3414
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003415 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003416
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003417 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003418
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003419 chan->expected_ack_seq = tx_seq;
3420 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003421
3422 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003423 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3424 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003425 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003426 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003427 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003428 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003429
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003430 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3431 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003432 }
3433}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003434static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003435{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003436 u8 tx_seq = __get_reqseq(rx_control);
3437
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003438 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003439
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003440 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003441
3442 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003443 chan->expected_ack_seq = tx_seq;
3444 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003445
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003446 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3447 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003448
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003449 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003450
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003451 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003452 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003453 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003454 }
3455 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003456 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003457 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003458 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003459 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003460 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003461 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003462 l2cap_retransmit_one_frame(chan, tx_seq);
3463 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003464 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003465 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003466 }
3467 }
3468}
3469
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003470static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003471{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003472 u8 tx_seq = __get_reqseq(rx_control);
3473
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003474 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003475
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003476 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003477 chan->expected_ack_seq = tx_seq;
3478 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003479
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003480 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003481 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003482
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003483 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003484 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003485 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003486 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003487 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003488 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003489
3490 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003491 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003492 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003493 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003494}
3495
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003496static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003497{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003498 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003499
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003500 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003501 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003502 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003503 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003504 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003505 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003506 }
3507
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003508 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3509 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003510 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003511 break;
3512
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003513 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003514 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003515 break;
3516
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003517 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003518 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003519 break;
3520
3521 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003522 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003523 break;
3524 }
3525
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003526 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003527 return 0;
3528}
3529
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003530static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3531{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003532 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003533 struct l2cap_pinfo *pi = l2cap_pi(sk);
3534 u16 control;
3535 u8 req_seq;
3536 int len, next_tx_seq_offset, req_seq_offset;
3537
3538 control = get_unaligned_le16(skb->data);
3539 skb_pull(skb, 2);
3540 len = skb->len;
3541
3542 /*
3543 * We can just drop the corrupted I-frame here.
3544 * Receiver will miss it and start proper recovery
3545 * procedures and ask retransmission.
3546 */
3547 if (l2cap_check_fcs(pi, skb))
3548 goto drop;
3549
3550 if (__is_sar_start(control) && __is_iframe(control))
3551 len -= 2;
3552
3553 if (pi->fcs == L2CAP_FCS_CRC16)
3554 len -= 2;
3555
3556 if (len > pi->mps) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003557 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003558 goto drop;
3559 }
3560
3561 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003562 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003563 if (req_seq_offset < 0)
3564 req_seq_offset += 64;
3565
3566 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003567 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003568 if (next_tx_seq_offset < 0)
3569 next_tx_seq_offset += 64;
3570
3571 /* check for invalid req-seq */
3572 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003573 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003574 goto drop;
3575 }
3576
3577 if (__is_iframe(control)) {
3578 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003579 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003580 goto drop;
3581 }
3582
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003583 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003584 } else {
3585 if (len != 0) {
3586 BT_ERR("%d", len);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003587 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003588 goto drop;
3589 }
3590
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003591 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003592 }
3593
3594 return 0;
3595
3596drop:
3597 kfree_skb(skb);
3598 return 0;
3599}
3600
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3602{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003603 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003604 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003605 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003606 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003607 u8 tx_seq;
3608 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003610 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003611 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612 BT_DBG("unknown cid 0x%4.4x", cid);
3613 goto drop;
3614 }
3615
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003616 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003617 pi = l2cap_pi(sk);
3618
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003619 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003620
3621 if (sk->sk_state != BT_CONNECTED)
3622 goto drop;
3623
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003624 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003625 case L2CAP_MODE_BASIC:
3626 /* If socket recv buffers overflows we drop data here
3627 * which is *bad* because L2CAP has to be reliable.
3628 * But we don't have any other choice. L2CAP doesn't
3629 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003631 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003632 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003634 if (!sock_queue_rcv_skb(sk, skb))
3635 goto done;
3636 break;
3637
3638 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003639 if (!sock_owned_by_user(sk)) {
3640 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003641 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003642 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003643 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003644 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003645
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003646 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003647
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003648 case L2CAP_MODE_STREAMING:
3649 control = get_unaligned_le16(skb->data);
3650 skb_pull(skb, 2);
3651 len = skb->len;
3652
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003653 if (l2cap_check_fcs(pi, skb))
3654 goto drop;
3655
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003656 if (__is_sar_start(control))
3657 len -= 2;
3658
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003659 if (pi->fcs == L2CAP_FCS_CRC16)
3660 len -= 2;
3661
Nathan Holstein51893f82010-06-09 15:46:25 -04003662 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003663 goto drop;
3664
3665 tx_seq = __get_txseq(control);
3666
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003667 if (chan->expected_tx_seq == tx_seq)
3668 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003669 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003670 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003671
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003672 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003673
3674 goto done;
3675
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003676 default:
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003677 BT_DBG("chan %p: bad mode 0x%2.2x", chan, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003678 break;
3679 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680
3681drop:
3682 kfree_skb(skb);
3683
3684done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003685 if (sk)
3686 bh_unlock_sock(sk);
3687
Linus Torvalds1da177e2005-04-16 15:20:36 -07003688 return 0;
3689}
3690
Al Viro8e036fc2007-07-29 00:16:36 -07003691static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692{
3693 struct sock *sk;
3694
3695 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3696 if (!sk)
3697 goto drop;
3698
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003699 bh_lock_sock(sk);
3700
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701 BT_DBG("sk %p, len %d", sk, skb->len);
3702
3703 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3704 goto drop;
3705
3706 if (l2cap_pi(sk)->imtu < skb->len)
3707 goto drop;
3708
3709 if (!sock_queue_rcv_skb(sk, skb))
3710 goto done;
3711
3712drop:
3713 kfree_skb(skb);
3714
3715done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003716 if (sk)
3717 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718 return 0;
3719}
3720
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003721static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3722{
3723 struct sock *sk;
3724
3725 sk = l2cap_get_sock_by_scid(0, cid, conn->src);
3726 if (!sk)
3727 goto drop;
3728
3729 bh_lock_sock(sk);
3730
3731 BT_DBG("sk %p, len %d", sk, skb->len);
3732
3733 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3734 goto drop;
3735
3736 if (l2cap_pi(sk)->imtu < skb->len)
3737 goto drop;
3738
3739 if (!sock_queue_rcv_skb(sk, skb))
3740 goto done;
3741
3742drop:
3743 kfree_skb(skb);
3744
3745done:
3746 if (sk)
3747 bh_unlock_sock(sk);
3748 return 0;
3749}
3750
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3752{
3753 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003754 u16 cid, len;
3755 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003756
3757 skb_pull(skb, L2CAP_HDR_SIZE);
3758 cid = __le16_to_cpu(lh->cid);
3759 len = __le16_to_cpu(lh->len);
3760
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003761 if (len != skb->len) {
3762 kfree_skb(skb);
3763 return;
3764 }
3765
Linus Torvalds1da177e2005-04-16 15:20:36 -07003766 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3767
3768 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003769 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003770 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771 l2cap_sig_channel(conn, skb);
3772 break;
3773
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003774 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003775 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776 skb_pull(skb, 2);
3777 l2cap_conless_channel(conn, psm, skb);
3778 break;
3779
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003780 case L2CAP_CID_LE_DATA:
3781 l2cap_att_channel(conn, cid, skb);
3782 break;
3783
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784 default:
3785 l2cap_data_channel(conn, cid, skb);
3786 break;
3787 }
3788}
3789
3790/* ---- L2CAP interface with lower layer (HCI) ---- */
3791
3792static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3793{
3794 int exact = 0, lm1 = 0, lm2 = 0;
3795 register struct sock *sk;
3796 struct hlist_node *node;
3797
3798 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003799 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800
3801 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3802
3803 /* Find listening sockets and check their link_mode */
3804 read_lock(&l2cap_sk_list.lock);
3805 sk_for_each(sk, node, &l2cap_sk_list.head) {
3806 if (sk->sk_state != BT_LISTEN)
3807 continue;
3808
3809 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003810 lm1 |= HCI_LM_ACCEPT;
3811 if (l2cap_pi(sk)->role_switch)
3812 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003814 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3815 lm2 |= HCI_LM_ACCEPT;
3816 if (l2cap_pi(sk)->role_switch)
3817 lm2 |= HCI_LM_MASTER;
3818 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819 }
3820 read_unlock(&l2cap_sk_list.lock);
3821
3822 return exact ? lm1 : lm2;
3823}
3824
3825static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3826{
Marcel Holtmann01394182006-07-03 10:02:46 +02003827 struct l2cap_conn *conn;
3828
Linus Torvalds1da177e2005-04-16 15:20:36 -07003829 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3830
Ville Tervoacd7d372011-02-10 22:38:49 -03003831 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003832 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833
3834 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835 conn = l2cap_conn_add(hcon, status);
3836 if (conn)
3837 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003838 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839 l2cap_conn_del(hcon, bt_err(status));
3840
3841 return 0;
3842}
3843
Marcel Holtmann2950f212009-02-12 14:02:50 +01003844static int l2cap_disconn_ind(struct hci_conn *hcon)
3845{
3846 struct l2cap_conn *conn = hcon->l2cap_data;
3847
3848 BT_DBG("hcon %p", hcon);
3849
3850 if (hcon->type != ACL_LINK || !conn)
3851 return 0x13;
3852
3853 return conn->disc_reason;
3854}
3855
3856static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857{
3858 BT_DBG("hcon %p reason %d", hcon, reason);
3859
Ville Tervoacd7d372011-02-10 22:38:49 -03003860 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003861 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862
3863 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003864
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865 return 0;
3866}
3867
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003868static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3869{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003870 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003871 return;
3872
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003873 if (encrypt == 0x00) {
3874 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3875 l2cap_sock_clear_timer(sk);
3876 l2cap_sock_set_timer(sk, HZ * 5);
3877 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3878 __l2cap_sock_close(sk, ECONNREFUSED);
3879 } else {
3880 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3881 l2cap_sock_clear_timer(sk);
3882 }
3883}
3884
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003885static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003886{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003887 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003888 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889
Marcel Holtmann01394182006-07-03 10:02:46 +02003890 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003892
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893 BT_DBG("conn %p", conn);
3894
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003895 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003897 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003898 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003899
Linus Torvalds1da177e2005-04-16 15:20:36 -07003900 bh_lock_sock(sk);
3901
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003902 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3903 bh_unlock_sock(sk);
3904 continue;
3905 }
3906
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003907 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003908 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003909 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003910 bh_unlock_sock(sk);
3911 continue;
3912 }
3913
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003914 if (sk->sk_state == BT_CONNECT) {
3915 if (!status) {
3916 struct l2cap_conn_req req;
3917 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3918 req.psm = l2cap_pi(sk)->psm;
3919
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003920 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003921 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003922
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003923 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003924 L2CAP_CONN_REQ, sizeof(req), &req);
3925 } else {
3926 l2cap_sock_clear_timer(sk);
3927 l2cap_sock_set_timer(sk, HZ / 10);
3928 }
3929 } else if (sk->sk_state == BT_CONNECT2) {
3930 struct l2cap_conn_rsp rsp;
3931 __u16 result;
3932
3933 if (!status) {
3934 sk->sk_state = BT_CONFIG;
3935 result = L2CAP_CR_SUCCESS;
3936 } else {
3937 sk->sk_state = BT_DISCONN;
3938 l2cap_sock_set_timer(sk, HZ / 10);
3939 result = L2CAP_CR_SEC_BLOCK;
3940 }
3941
3942 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3943 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3944 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003945 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003946 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
3947 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948 }
3949
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950 bh_unlock_sock(sk);
3951 }
3952
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003953 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003954
Linus Torvalds1da177e2005-04-16 15:20:36 -07003955 return 0;
3956}
3957
3958static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3959{
3960 struct l2cap_conn *conn = hcon->l2cap_data;
3961
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003962 if (!conn)
3963 conn = l2cap_conn_add(hcon, 0);
3964
3965 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966 goto drop;
3967
3968 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3969
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003970 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003971 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003972 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003973 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974 int len;
3975
3976 if (conn->rx_len) {
3977 BT_ERR("Unexpected start frame (len %d)", skb->len);
3978 kfree_skb(conn->rx_skb);
3979 conn->rx_skb = NULL;
3980 conn->rx_len = 0;
3981 l2cap_conn_unreliable(conn, ECOMM);
3982 }
3983
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003984 /* Start fragment always begin with Basic L2CAP header */
3985 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986 BT_ERR("Frame is too short (len %d)", skb->len);
3987 l2cap_conn_unreliable(conn, ECOMM);
3988 goto drop;
3989 }
3990
3991 hdr = (struct l2cap_hdr *) skb->data;
3992 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003993 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994
3995 if (len == skb->len) {
3996 /* Complete frame received */
3997 l2cap_recv_frame(conn, skb);
3998 return 0;
3999 }
4000
4001 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4002
4003 if (skb->len > len) {
4004 BT_ERR("Frame is too long (len %d, expected len %d)",
4005 skb->len, len);
4006 l2cap_conn_unreliable(conn, ECOMM);
4007 goto drop;
4008 }
4009
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004010 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004011
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004012 if (chan && chan->sk) {
4013 struct sock *sk = chan->sk;
4014
4015 if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
4016 BT_ERR("Frame exceeding recv MTU (len %d, "
4017 "MTU %d)", len,
4018 l2cap_pi(sk)->imtu);
4019 bh_unlock_sock(sk);
4020 l2cap_conn_unreliable(conn, ECOMM);
4021 goto drop;
4022 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004023 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004024 }
4025
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004027 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4028 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029 goto drop;
4030
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004031 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004032 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033 conn->rx_len = len - skb->len;
4034 } else {
4035 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4036
4037 if (!conn->rx_len) {
4038 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4039 l2cap_conn_unreliable(conn, ECOMM);
4040 goto drop;
4041 }
4042
4043 if (skb->len > conn->rx_len) {
4044 BT_ERR("Fragment is too long (len %d, expected %d)",
4045 skb->len, conn->rx_len);
4046 kfree_skb(conn->rx_skb);
4047 conn->rx_skb = NULL;
4048 conn->rx_len = 0;
4049 l2cap_conn_unreliable(conn, ECOMM);
4050 goto drop;
4051 }
4052
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004053 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004054 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055 conn->rx_len -= skb->len;
4056
4057 if (!conn->rx_len) {
4058 /* Complete frame received */
4059 l2cap_recv_frame(conn, conn->rx_skb);
4060 conn->rx_skb = NULL;
4061 }
4062 }
4063
4064drop:
4065 kfree_skb(skb);
4066 return 0;
4067}
4068
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004069static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070{
4071 struct sock *sk;
4072 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073
4074 read_lock_bh(&l2cap_sk_list.lock);
4075
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004076 sk_for_each(sk, node, &l2cap_sk_list.head) {
4077 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004079 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004080 batostr(&bt_sk(sk)->src),
4081 batostr(&bt_sk(sk)->dst),
4082 sk->sk_state, __le16_to_cpu(pi->psm),
4083 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004084 pi->imtu, pi->omtu, pi->sec_level,
4085 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087
Linus Torvalds1da177e2005-04-16 15:20:36 -07004088 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004089
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004090 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091}
4092
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004093static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4094{
4095 return single_open(file, l2cap_debugfs_show, inode->i_private);
4096}
4097
4098static const struct file_operations l2cap_debugfs_fops = {
4099 .open = l2cap_debugfs_open,
4100 .read = seq_read,
4101 .llseek = seq_lseek,
4102 .release = single_release,
4103};
4104
4105static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107static struct hci_proto l2cap_hci_proto = {
4108 .name = "L2CAP",
4109 .id = HCI_PROTO_L2CAP,
4110 .connect_ind = l2cap_connect_ind,
4111 .connect_cfm = l2cap_connect_cfm,
4112 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004113 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004114 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115 .recv_acldata = l2cap_recv_acldata
4116};
4117
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004118int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119{
4120 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004121
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004122 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123 if (err < 0)
4124 return err;
4125
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004126 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004127 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004128 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129 goto error;
4130 }
4131
4132 err = hci_register_proto(&l2cap_hci_proto);
4133 if (err < 0) {
4134 BT_ERR("L2CAP protocol registration failed");
4135 bt_sock_unregister(BTPROTO_L2CAP);
4136 goto error;
4137 }
4138
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004139 if (bt_debugfs) {
4140 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4141 bt_debugfs, NULL, &l2cap_debugfs_fops);
4142 if (!l2cap_debugfs)
4143 BT_ERR("Failed to create L2CAP debug file");
4144 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004145
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146 return 0;
4147
4148error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004149 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004150 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151 return err;
4152}
4153
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004154void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004156 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004158 flush_workqueue(_busy_wq);
4159 destroy_workqueue(_busy_wq);
4160
Linus Torvalds1da177e2005-04-16 15:20:36 -07004161 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4162 BT_ERR("L2CAP protocol unregistration failed");
4163
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004164 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165}
4166
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004167module_param(disable_ertm, bool, 0644);
4168MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");