blob: d975092904c1c29971ba91855e770c461fe2e83e [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. Padovan48454072011-03-25 00:22:30 -0300152static struct 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
214 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
215
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
239 skb_queue_purge(TX_QUEUE(sk));
240
241 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
242 struct srej_list *l, *tmp;
243
244 del_timer(&l2cap_pi(sk)->retrans_timer);
245 del_timer(&l2cap_pi(sk)->monitor_timer);
246 del_timer(&l2cap_pi(sk)->ack_timer);
247
248 skb_queue_purge(SREJ_QUEUE(sk));
249 skb_queue_purge(BUSY_QUEUE(sk));
250
251 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
252 list_del(&l->list);
253 kfree(l);
254 }
255 }
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300256
257 kfree(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200258}
259
Johan Hedberg8556edd32011-01-19 12:06:50 +0530260static inline u8 l2cap_get_auth_type(struct sock *sk)
261{
262 if (sk->sk_type == SOCK_RAW) {
263 switch (l2cap_pi(sk)->sec_level) {
264 case BT_SECURITY_HIGH:
265 return HCI_AT_DEDICATED_BONDING_MITM;
266 case BT_SECURITY_MEDIUM:
267 return HCI_AT_DEDICATED_BONDING;
268 default:
269 return HCI_AT_NO_BONDING;
270 }
271 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
272 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
273 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
274
275 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
276 return HCI_AT_NO_BONDING_MITM;
277 else
278 return HCI_AT_NO_BONDING;
279 } else {
280 switch (l2cap_pi(sk)->sec_level) {
281 case BT_SECURITY_HIGH:
282 return HCI_AT_GENERAL_BONDING_MITM;
283 case BT_SECURITY_MEDIUM:
284 return HCI_AT_GENERAL_BONDING;
285 default:
286 return HCI_AT_NO_BONDING;
287 }
288 }
289}
290
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200291/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100292static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200293{
294 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100295 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200296
Johan Hedberg8556edd32011-01-19 12:06:50 +0530297 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100298
299 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
300 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200301}
302
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200303u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200304{
305 u8 id;
306
307 /* Get next available identificator.
308 * 1 - 128 are used by kernel.
309 * 129 - 199 are reserved.
310 * 200 - 254 are used by utilities like l2ping, etc.
311 */
312
313 spin_lock_bh(&conn->lock);
314
315 if (++conn->tx_ident > 128)
316 conn->tx_ident = 1;
317
318 id = conn->tx_ident;
319
320 spin_unlock_bh(&conn->lock);
321
322 return id;
323}
324
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200325void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200326{
327 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200328 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200329
330 BT_DBG("code 0x%2.2x", code);
331
332 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300333 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200334
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200335 if (lmp_no_flush_capable(conn->hcon->hdev))
336 flags = ACL_START_NO_FLUSH;
337 else
338 flags = ACL_START;
339
340 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200341}
342
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300343static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300344{
345 struct sk_buff *skb;
346 struct l2cap_hdr *lh;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300347 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300348 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300349 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300350 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200351 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300352
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300353 if (sk->sk_state != BT_CONNECTED)
354 return;
355
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300356 if (pi->fcs == L2CAP_FCS_CRC16)
357 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300358
359 BT_DBG("pi %p, control 0x%2.2x", pi, control);
360
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300361 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300362 control |= L2CAP_CTRL_FRAME_TYPE;
363
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300364 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300365 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300366 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300367 }
368
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300369 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300370 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300371 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300372 }
373
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300374 skb = bt_skb_alloc(count, GFP_ATOMIC);
375 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300376 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300377
378 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300379 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300380 lh->cid = cpu_to_le16(pi->dcid);
381 put_unaligned_le16(control, skb_put(skb, 2));
382
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300383 if (pi->fcs == L2CAP_FCS_CRC16) {
384 u16 fcs = crc16(0, (u8 *)lh, count - 2);
385 put_unaligned_le16(fcs, skb_put(skb, 2));
386 }
387
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200388 if (lmp_no_flush_capable(conn->hcon->hdev))
389 flags = ACL_START_NO_FLUSH;
390 else
391 flags = ACL_START;
392
393 hci_send_acl(pi->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300394}
395
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300396static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300397{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300398 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300399 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300400 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300401 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300402 control |= L2CAP_SUPER_RCV_READY;
403
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300404 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300405
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300406 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300407}
408
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300409static inline int __l2cap_no_conn_pending(struct sock *sk)
410{
411 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
412}
413
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300414static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200415{
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300416 struct sock *sk = chan->sk;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200417 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
418
419 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100420 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
421 return;
422
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300423 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200424 struct l2cap_conn_req req;
425 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
426 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200427
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300428 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300429 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200430
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300431 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
432 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200433 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200434 } else {
435 struct l2cap_info_req req;
436 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
437
438 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
439 conn->info_ident = l2cap_get_ident(conn);
440
441 mod_timer(&conn->info_timer, jiffies +
442 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
443
444 l2cap_send_cmd(conn, conn->info_ident,
445 L2CAP_INFO_REQ, sizeof(req), &req);
446 }
447}
448
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300449static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
450{
451 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300452 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300453 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
454
455 switch (mode) {
456 case L2CAP_MODE_ERTM:
457 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
458 case L2CAP_MODE_STREAMING:
459 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
460 default:
461 return 0x00;
462 }
463}
464
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200465void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300466{
467 struct l2cap_disconn_req req;
468
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300469 if (!conn)
470 return;
471
472 skb_queue_purge(TX_QUEUE(sk));
473
474 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
475 del_timer(&l2cap_pi(sk)->retrans_timer);
476 del_timer(&l2cap_pi(sk)->monitor_timer);
477 del_timer(&l2cap_pi(sk)->ack_timer);
478 }
479
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300480 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
481 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
482 l2cap_send_cmd(conn, l2cap_get_ident(conn),
483 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300484
485 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300486 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300487}
488
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200490static void l2cap_conn_start(struct l2cap_conn *conn)
491{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300492 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200493
494 BT_DBG("conn %p", conn);
495
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300496 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200497
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300498 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300499 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300500
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200501 bh_lock_sock(sk);
502
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300503 if (sk->sk_type != SOCK_SEQPACKET &&
504 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200505 bh_unlock_sock(sk);
506 continue;
507 }
508
509 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300510 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300511
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300512 if (!l2cap_check_security(sk) ||
513 !__l2cap_no_conn_pending(sk)) {
514 bh_unlock_sock(sk);
515 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200516 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300517
518 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
519 conn->feat_mask)
520 && l2cap_pi(sk)->conf_state &
521 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300522 /* __l2cap_sock_close() calls list_del(chan)
523 * so release the lock */
524 read_unlock_bh(&conn->chan_lock);
525 __l2cap_sock_close(sk, ECONNRESET);
526 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300527 bh_unlock_sock(sk);
528 continue;
529 }
530
531 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
532 req.psm = l2cap_pi(sk)->psm;
533
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300534 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300535 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
536
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300537 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
538 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300539
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200540 } else if (sk->sk_state == BT_CONNECT2) {
541 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300542 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200543 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
544 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
545
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100546 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100547 if (bt_sk(sk)->defer_setup) {
548 struct sock *parent = bt_sk(sk)->parent;
549 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
550 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
551 parent->sk_data_ready(parent, 0);
552
553 } else {
554 sk->sk_state = BT_CONFIG;
555 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
556 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
557 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200558 } else {
559 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
560 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
561 }
562
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300563 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
564 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300565
566 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
567 rsp.result != L2CAP_CR_SUCCESS) {
568 bh_unlock_sock(sk);
569 continue;
570 }
571
572 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
573 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300574 l2cap_build_conf_req(chan, buf), buf);
575 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200576 }
577
578 bh_unlock_sock(sk);
579 }
580
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300581 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200582}
583
Ville Tervob62f3282011-02-10 22:38:50 -0300584/* Find socket with cid and source bdaddr.
585 * Returns closest match, locked.
586 */
587static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
588{
589 struct sock *s, *sk = NULL, *sk1 = NULL;
590 struct hlist_node *node;
591
592 read_lock(&l2cap_sk_list.lock);
593
594 sk_for_each(sk, node, &l2cap_sk_list.head) {
595 if (state && sk->sk_state != state)
596 continue;
597
598 if (l2cap_pi(sk)->scid == cid) {
599 /* Exact match. */
600 if (!bacmp(&bt_sk(sk)->src, src))
601 break;
602
603 /* Closest match */
604 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
605 sk1 = sk;
606 }
607 }
608 s = node ? sk : sk1;
609 if (s)
610 bh_lock_sock(s);
611 read_unlock(&l2cap_sk_list.lock);
612
613 return s;
614}
615
616static void l2cap_le_conn_ready(struct l2cap_conn *conn)
617{
Ville Tervob62f3282011-02-10 22:38:50 -0300618 struct sock *parent, *uninitialized_var(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300619 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300620
621 BT_DBG("");
622
623 /* Check if we have socket listening on cid */
624 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
625 conn->src);
626 if (!parent)
627 return;
628
629 /* Check for backlog size */
630 if (sk_acceptq_is_full(parent)) {
631 BT_DBG("backlog full %d", parent->sk_ack_backlog);
632 goto clean;
633 }
634
635 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
636 if (!sk)
637 goto clean;
638
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300639 chan = l2cap_chan_alloc(sk);
640 if (!chan) {
641 l2cap_sock_kill(sk);
642 goto clean;
643 }
644
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300645 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300646
647 hci_conn_hold(conn->hcon);
648
649 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300650
Ville Tervob62f3282011-02-10 22:38:50 -0300651 bacpy(&bt_sk(sk)->src, conn->src);
652 bacpy(&bt_sk(sk)->dst, conn->dst);
653
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300654 bt_accept_enqueue(parent, sk);
655
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300656 __l2cap_chan_add(conn, chan);
657
658 l2cap_pi(sk)->chan = chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300659
660 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
661
662 sk->sk_state = BT_CONNECTED;
663 parent->sk_data_ready(parent, 0);
664
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300665 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300666
667clean:
668 bh_unlock_sock(parent);
669}
670
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200671static void l2cap_conn_ready(struct l2cap_conn *conn)
672{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300673 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200674
675 BT_DBG("conn %p", conn);
676
Ville Tervob62f3282011-02-10 22:38:50 -0300677 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
678 l2cap_le_conn_ready(conn);
679
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300680 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200681
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300682 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300683 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300684
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200685 bh_lock_sock(sk);
686
Ville Tervoacd7d372011-02-10 22:38:49 -0300687 if (conn->hcon->type == LE_LINK) {
688 l2cap_sock_clear_timer(sk);
689 sk->sk_state = BT_CONNECTED;
690 sk->sk_state_change(sk);
691 }
692
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300693 if (sk->sk_type != SOCK_SEQPACKET &&
694 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200695 l2cap_sock_clear_timer(sk);
696 sk->sk_state = BT_CONNECTED;
697 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200698 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300699 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200700
701 bh_unlock_sock(sk);
702 }
703
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300704 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200705}
706
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200707/* Notify sockets that we cannot guaranty reliability anymore */
708static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
709{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300710 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200711
712 BT_DBG("conn %p", conn);
713
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300714 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200715
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300716 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300717 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300718
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100719 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200720 sk->sk_err = err;
721 }
722
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300723 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200724}
725
726static void l2cap_info_timeout(unsigned long arg)
727{
728 struct l2cap_conn *conn = (void *) arg;
729
Marcel Holtmann984947d2009-02-06 23:35:19 +0100730 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100731 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100732
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200733 l2cap_conn_start(conn);
734}
735
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
737{
Marcel Holtmann01394182006-07-03 10:02:46 +0200738 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739
Marcel Holtmann01394182006-07-03 10:02:46 +0200740 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 return conn;
742
Marcel Holtmann01394182006-07-03 10:02:46 +0200743 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
744 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746
747 hcon->l2cap_data = conn;
748 conn->hcon = hcon;
749
Marcel Holtmann01394182006-07-03 10:02:46 +0200750 BT_DBG("hcon %p conn %p", hcon, conn);
751
Ville Tervoacd7d372011-02-10 22:38:49 -0300752 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
753 conn->mtu = hcon->hdev->le_mtu;
754 else
755 conn->mtu = hcon->hdev->acl_mtu;
756
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 conn->src = &hcon->hdev->bdaddr;
758 conn->dst = &hcon->dst;
759
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200760 conn->feat_mask = 0;
761
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300763 rwlock_init(&conn->chan_lock);
764
765 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766
Ville Tervob62f3282011-02-10 22:38:50 -0300767 if (hcon->type != LE_LINK)
768 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000769 (unsigned long) conn);
770
Marcel Holtmann2950f212009-02-12 14:02:50 +0100771 conn->disc_reason = 0x13;
772
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 return conn;
774}
775
Marcel Holtmann01394182006-07-03 10:02:46 +0200776static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777{
Marcel Holtmann01394182006-07-03 10:02:46 +0200778 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300779 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 struct sock *sk;
781
Marcel Holtmann01394182006-07-03 10:02:46 +0200782 if (!conn)
783 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784
785 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
786
Wei Yongjun7585b972009-02-25 18:29:52 +0800787 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788
789 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300790 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300791 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300793 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 bh_unlock_sock(sk);
795 l2cap_sock_kill(sk);
796 }
797
Dave Young8e8440f2008-03-03 12:18:55 -0800798 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
799 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800800
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 hcon->l2cap_data = NULL;
802 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803}
804
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300805static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300807 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300808 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300809 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810}
811
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813
814/* Find socket with psm and source bdaddr.
815 * Returns closest match.
816 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000817static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818{
819 struct sock *sk = NULL, *sk1 = NULL;
820 struct hlist_node *node;
821
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000822 read_lock(&l2cap_sk_list.lock);
823
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 sk_for_each(sk, node, &l2cap_sk_list.head) {
825 if (state && sk->sk_state != state)
826 continue;
827
828 if (l2cap_pi(sk)->psm == psm) {
829 /* Exact match. */
830 if (!bacmp(&bt_sk(sk)->src, src))
831 break;
832
833 /* Closest match */
834 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
835 sk1 = sk;
836 }
837 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000840
841 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842}
843
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200844int l2cap_do_connect(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845{
846 bdaddr_t *src = &bt_sk(sk)->src;
847 bdaddr_t *dst = &bt_sk(sk)->dst;
848 struct l2cap_conn *conn;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300849 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 struct hci_conn *hcon;
851 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200852 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200853 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100855 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
856 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300858 hdev = hci_get_route(dst, src);
859 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 return -EHOSTUNREACH;
861
862 hci_dev_lock_bh(hdev);
863
Johan Hedberg8556edd32011-01-19 12:06:50 +0530864 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200865
Ville Tervoacd7d372011-02-10 22:38:49 -0300866 if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
867 hcon = hci_connect(hdev, LE_LINK, dst,
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100868 l2cap_pi(sk)->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300869 else
870 hcon = hci_connect(hdev, ACL_LINK, dst,
871 l2cap_pi(sk)->sec_level, auth_type);
872
Ville Tervo30e76272011-02-22 16:10:53 -0300873 if (IS_ERR(hcon)) {
874 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300876 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877
878 conn = l2cap_conn_add(hcon, 0);
879 if (!conn) {
880 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300881 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 goto done;
883 }
884
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300885 chan = l2cap_chan_alloc(sk);
886 if (!chan) {
887 hci_conn_put(hcon);
888 err = -ENOMEM;
889 goto done;
890 }
891
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 /* Update source addr of the socket */
893 bacpy(src, conn->src);
894
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300895 l2cap_chan_add(conn, chan);
896
897 l2cap_pi(sk)->chan = chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898
899 sk->sk_state = BT_CONNECT;
900 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
901
902 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300903 if (sk->sk_type != SOCK_SEQPACKET &&
904 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530906 if (l2cap_check_security(sk))
907 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200908 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300909 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 }
911
Ville Tervo30e76272011-02-22 16:10:53 -0300912 err = 0;
913
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914done:
915 hci_dev_unlock_bh(hdev);
916 hci_dev_put(hdev);
917 return err;
918}
919
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200920int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300921{
922 DECLARE_WAITQUEUE(wait, current);
923 int err = 0;
924 int timeo = HZ/5;
925
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200926 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300927 while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
928 set_current_state(TASK_INTERRUPTIBLE);
929
930 if (!timeo)
931 timeo = HZ/5;
932
933 if (signal_pending(current)) {
934 err = sock_intr_errno(timeo);
935 break;
936 }
937
938 release_sock(sk);
939 timeo = schedule_timeout(timeo);
940 lock_sock(sk);
941
942 err = sock_error(sk);
943 if (err)
944 break;
945 }
946 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200947 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300948 return err;
949}
950
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300951static void l2cap_monitor_timeout(unsigned long arg)
952{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300953 struct l2cap_chan *chan = (void *) arg;
954 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300955
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300956 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300957
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300958 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300959 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300960 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200961 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300962 return;
963 }
964
965 l2cap_pi(sk)->retry_count++;
966 __mod_monitor_timer();
967
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300968 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300969 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300970}
971
972static void l2cap_retrans_timeout(unsigned long arg)
973{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300974 struct l2cap_chan *chan = (void *) arg;
975 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300976
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300977 BT_DBG("sk %p", sk);
978
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300979 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300980 l2cap_pi(sk)->retry_count = 1;
981 __mod_monitor_timer();
982
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300983 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300984
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300985 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300986 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300987}
988
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300989static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300990{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300991 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300992 struct sk_buff *skb;
993
Gustavo F. Padovan812e7372010-05-01 16:15:42 -0300994 while ((skb = skb_peek(TX_QUEUE(sk))) &&
995 l2cap_pi(sk)->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300996 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300997 break;
998
999 skb = skb_dequeue(TX_QUEUE(sk));
1000 kfree_skb(skb);
1001
1002 l2cap_pi(sk)->unacked_frames--;
1003 }
1004
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001005 if (!l2cap_pi(sk)->unacked_frames)
1006 del_timer(&l2cap_pi(sk)->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001007}
1008
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001009void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001010{
1011 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001012 struct hci_conn *hcon = pi->conn->hcon;
1013 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001014
1015 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1016
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001017 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
1018 flags = ACL_START_NO_FLUSH;
1019 else
1020 flags = ACL_START;
1021
1022 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001023}
1024
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001025void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001026{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001027 struct sock *sk = chan->sk;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001028 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001029 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001030 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001031
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001032 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
1033 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001034 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001035 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001036
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001037 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001038 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1039 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001040 }
1041
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001042 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001043
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001044 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001045 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001046}
1047
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001048static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001049{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001050 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001051 struct l2cap_pinfo *pi = l2cap_pi(sk);
1052 struct sk_buff *skb, *tx_skb;
1053 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001054
1055 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001056 if (!skb)
1057 return;
1058
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001059 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001060 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001061 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001062
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001063 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1064 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001065
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001066 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001067
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001068 if (pi->remote_max_tx &&
1069 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001070 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001071 return;
1072 }
1073
1074 tx_skb = skb_clone(skb, GFP_ATOMIC);
1075 bt_cb(skb)->retries++;
1076 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001077
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001078 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001079 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001080 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001081 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001082
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001083 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001084 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001085
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001086 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1087
1088 if (pi->fcs == L2CAP_FCS_CRC16) {
1089 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1090 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1091 }
1092
1093 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001094}
1095
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001096int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001097{
1098 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001099 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001100 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001101 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001102 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001103
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001104 if (sk->sk_state != BT_CONNECTED)
1105 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001106
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001107 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001108
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001109 if (pi->remote_max_tx &&
1110 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001111 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001112 break;
1113 }
1114
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001115 tx_skb = skb_clone(skb, GFP_ATOMIC);
1116
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001117 bt_cb(skb)->retries++;
1118
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001119 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001120 control &= L2CAP_CTRL_SAR;
1121
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001122 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001123 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001124 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001125 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001126 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1127 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001128 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1129
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001130
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001131 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001132 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1133 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1134 }
1135
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001136 l2cap_do_send(sk, tx_skb);
1137
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001138 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001139
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001140 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1141 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001142
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301143 if (bt_cb(skb)->retries == 1)
1144 pi->unacked_frames++;
1145
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001146 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001147
1148 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1149 sk->sk_send_head = NULL;
1150 else
1151 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001152
1153 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001154 }
1155
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001156 return nsent;
1157}
1158
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001159static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001160{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001161 struct sock *sk = chan->sk;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001162 int ret;
1163
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001164 if (!skb_queue_empty(TX_QUEUE(sk)))
1165 sk->sk_send_head = TX_QUEUE(sk)->next;
1166
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001167 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001168 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001169 return ret;
1170}
1171
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001172static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001173{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001174 u16 control = 0;
1175
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001176 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001177
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001178 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001179 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001180 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1181 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001182 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001183 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001184
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001185 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001186 return;
1187
1188 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001189 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001190}
1191
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001192static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001193{
1194 struct srej_list *tail;
1195 u16 control;
1196
1197 control = L2CAP_SUPER_SELECT_REJECT;
1198 control |= L2CAP_CTRL_FINAL;
1199
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001200 tail = list_entry(SREJ_LIST(chan->sk)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001201 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1202
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001203 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001204}
1205
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001206static 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 -07001207{
1208 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001209 struct sk_buff **frag;
1210 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001212 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001213 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214
1215 sent += count;
1216 len -= count;
1217
1218 /* Continuation fragments (no L2CAP header) */
1219 frag = &skb_shinfo(skb)->frag_list;
1220 while (len) {
1221 count = min_t(unsigned int, conn->mtu, len);
1222
1223 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1224 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001225 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001226 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1227 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228
1229 sent += count;
1230 len -= count;
1231
1232 frag = &(*frag)->next;
1233 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234
1235 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001236}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001238struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001239{
1240 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1241 struct sk_buff *skb;
1242 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1243 struct l2cap_hdr *lh;
1244
1245 BT_DBG("sk %p len %d", sk, (int)len);
1246
1247 count = min_t(unsigned int, (conn->mtu - hlen), len);
1248 skb = bt_skb_send_alloc(sk, count + hlen,
1249 msg->msg_flags & MSG_DONTWAIT, &err);
1250 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001251 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001252
1253 /* Create L2CAP header */
1254 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1255 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1256 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1257 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1258
1259 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1260 if (unlikely(err < 0)) {
1261 kfree_skb(skb);
1262 return ERR_PTR(err);
1263 }
1264 return skb;
1265}
1266
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001267struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001268{
1269 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1270 struct sk_buff *skb;
1271 int err, count, hlen = L2CAP_HDR_SIZE;
1272 struct l2cap_hdr *lh;
1273
1274 BT_DBG("sk %p len %d", sk, (int)len);
1275
1276 count = min_t(unsigned int, (conn->mtu - hlen), len);
1277 skb = bt_skb_send_alloc(sk, count + hlen,
1278 msg->msg_flags & MSG_DONTWAIT, &err);
1279 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001280 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001281
1282 /* Create L2CAP header */
1283 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1284 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1285 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1286
1287 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1288 if (unlikely(err < 0)) {
1289 kfree_skb(skb);
1290 return ERR_PTR(err);
1291 }
1292 return skb;
1293}
1294
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001295struct 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 -03001296{
1297 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1298 struct sk_buff *skb;
1299 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1300 struct l2cap_hdr *lh;
1301
1302 BT_DBG("sk %p len %d", sk, (int)len);
1303
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001304 if (!conn)
1305 return ERR_PTR(-ENOTCONN);
1306
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001307 if (sdulen)
1308 hlen += 2;
1309
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001310 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1311 hlen += 2;
1312
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001313 count = min_t(unsigned int, (conn->mtu - hlen), len);
1314 skb = bt_skb_send_alloc(sk, count + hlen,
1315 msg->msg_flags & MSG_DONTWAIT, &err);
1316 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001317 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001318
1319 /* Create L2CAP header */
1320 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1321 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1322 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1323 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001324 if (sdulen)
1325 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001326
1327 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1328 if (unlikely(err < 0)) {
1329 kfree_skb(skb);
1330 return ERR_PTR(err);
1331 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001332
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001333 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1334 put_unaligned_le16(0, skb_put(skb, 2));
1335
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001336 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001337 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338}
1339
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001340int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001341{
1342 struct l2cap_pinfo *pi = l2cap_pi(sk);
1343 struct sk_buff *skb;
1344 struct sk_buff_head sar_queue;
1345 u16 control;
1346 size_t size = 0;
1347
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001348 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001349 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001350 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001351 if (IS_ERR(skb))
1352 return PTR_ERR(skb);
1353
1354 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001355 len -= pi->remote_mps;
1356 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001357
1358 while (len > 0) {
1359 size_t buflen;
1360
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001361 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001362 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001363 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001364 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001365 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001366 buflen = len;
1367 }
1368
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001369 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001370 if (IS_ERR(skb)) {
1371 skb_queue_purge(&sar_queue);
1372 return PTR_ERR(skb);
1373 }
1374
1375 __skb_queue_tail(&sar_queue, skb);
1376 len -= buflen;
1377 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001378 }
1379 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1380 if (sk->sk_send_head == NULL)
1381 sk->sk_send_head = sar_queue.next;
1382
1383 return size;
1384}
1385
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386static void l2cap_chan_ready(struct sock *sk)
1387{
1388 struct sock *parent = bt_sk(sk)->parent;
1389
1390 BT_DBG("sk %p, parent %p", sk, parent);
1391
1392 l2cap_pi(sk)->conf_state = 0;
1393 l2cap_sock_clear_timer(sk);
1394
1395 if (!parent) {
1396 /* Outgoing channel.
1397 * Wake up socket sleeping on connect.
1398 */
1399 sk->sk_state = BT_CONNECTED;
1400 sk->sk_state_change(sk);
1401 } else {
1402 /* Incoming channel.
1403 * Wake up socket sleeping on accept.
1404 */
1405 parent->sk_data_ready(parent, 0);
1406 }
1407}
1408
1409/* Copy frame to all raw sockets on that connection */
1410static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1411{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001413 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414
1415 BT_DBG("conn %p", conn);
1416
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001417 read_lock(&conn->chan_lock);
1418 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001419 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 if (sk->sk_type != SOCK_RAW)
1421 continue;
1422
1423 /* Don't send frame to the socket it came from */
1424 if (skb->sk == sk)
1425 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001426 nskb = skb_clone(skb, GFP_ATOMIC);
1427 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 continue;
1429
1430 if (sock_queue_rcv_skb(sk, nskb))
1431 kfree_skb(nskb);
1432 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001433 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434}
1435
1436/* ---- L2CAP signalling commands ---- */
1437static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1438 u8 code, u8 ident, u16 dlen, void *data)
1439{
1440 struct sk_buff *skb, **frag;
1441 struct l2cap_cmd_hdr *cmd;
1442 struct l2cap_hdr *lh;
1443 int len, count;
1444
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001445 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1446 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447
1448 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1449 count = min_t(unsigned int, conn->mtu, len);
1450
1451 skb = bt_skb_alloc(count, GFP_ATOMIC);
1452 if (!skb)
1453 return NULL;
1454
1455 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001456 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001457
1458 if (conn->hcon->type == LE_LINK)
1459 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1460 else
1461 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462
1463 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1464 cmd->code = code;
1465 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001466 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
1468 if (dlen) {
1469 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1470 memcpy(skb_put(skb, count), data, count);
1471 data += count;
1472 }
1473
1474 len -= skb->len;
1475
1476 /* Continuation fragments (no L2CAP header) */
1477 frag = &skb_shinfo(skb)->frag_list;
1478 while (len) {
1479 count = min_t(unsigned int, conn->mtu, len);
1480
1481 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1482 if (!*frag)
1483 goto fail;
1484
1485 memcpy(skb_put(*frag, count), data, count);
1486
1487 len -= count;
1488 data += count;
1489
1490 frag = &(*frag)->next;
1491 }
1492
1493 return skb;
1494
1495fail:
1496 kfree_skb(skb);
1497 return NULL;
1498}
1499
1500static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1501{
1502 struct l2cap_conf_opt *opt = *ptr;
1503 int len;
1504
1505 len = L2CAP_CONF_OPT_SIZE + opt->len;
1506 *ptr += len;
1507
1508 *type = opt->type;
1509 *olen = opt->len;
1510
1511 switch (opt->len) {
1512 case 1:
1513 *val = *((u8 *) opt->val);
1514 break;
1515
1516 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001517 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 break;
1519
1520 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001521 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 break;
1523
1524 default:
1525 *val = (unsigned long) opt->val;
1526 break;
1527 }
1528
1529 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1530 return len;
1531}
1532
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1534{
1535 struct l2cap_conf_opt *opt = *ptr;
1536
1537 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1538
1539 opt->type = type;
1540 opt->len = len;
1541
1542 switch (len) {
1543 case 1:
1544 *((u8 *) opt->val) = val;
1545 break;
1546
1547 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001548 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 break;
1550
1551 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001552 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 break;
1554
1555 default:
1556 memcpy(opt->val, (void *) val, len);
1557 break;
1558 }
1559
1560 *ptr += L2CAP_CONF_OPT_SIZE + len;
1561}
1562
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001563static void l2cap_ack_timeout(unsigned long arg)
1564{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001565 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001566
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001567 bh_lock_sock(chan->sk);
1568 l2cap_send_ack(chan);
1569 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001570}
1571
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001572static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001573{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001574 struct sock *sk = chan->sk;
1575
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001576 chan->expected_ack_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001577 l2cap_pi(sk)->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001578 chan->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03001579 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001580 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001581
1582 setup_timer(&l2cap_pi(sk)->retrans_timer,
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001583 l2cap_retrans_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001584 setup_timer(&l2cap_pi(sk)->monitor_timer,
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001585 l2cap_monitor_timeout, (unsigned long) chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001586 setup_timer(&l2cap_pi(sk)->ack_timer,
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001587 l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001588
1589 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001590 __skb_queue_head_init(BUSY_QUEUE(sk));
1591
1592 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001593
1594 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001595}
1596
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001597static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1598{
1599 switch (mode) {
1600 case L2CAP_MODE_STREAMING:
1601 case L2CAP_MODE_ERTM:
1602 if (l2cap_mode_supported(mode, remote_feat_mask))
1603 return mode;
1604 /* fall through */
1605 default:
1606 return L2CAP_MODE_BASIC;
1607 }
1608}
1609
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001610static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001612 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 struct l2cap_pinfo *pi = l2cap_pi(sk);
1614 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001615 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 void *ptr = req->data;
1617
1618 BT_DBG("sk %p", sk);
1619
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001620 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001621 goto done;
1622
1623 switch (pi->mode) {
1624 case L2CAP_MODE_STREAMING:
1625 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001626 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001627 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001628
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001629 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001630 default:
1631 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1632 break;
1633 }
1634
1635done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001636 if (pi->imtu != L2CAP_DEFAULT_MTU)
1637 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1638
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001639 switch (pi->mode) {
1640 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001641 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1642 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1643 break;
1644
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001645 rfc.mode = L2CAP_MODE_BASIC;
1646 rfc.txwin_size = 0;
1647 rfc.max_transmit = 0;
1648 rfc.retrans_timeout = 0;
1649 rfc.monitor_timeout = 0;
1650 rfc.max_pdu_size = 0;
1651
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001652 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1653 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001654 break;
1655
1656 case L2CAP_MODE_ERTM:
1657 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001658 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001659 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001660 rfc.retrans_timeout = 0;
1661 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001662 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001663 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001664 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001665
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001666 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1667 (unsigned long) &rfc);
1668
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001669 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1670 break;
1671
1672 if (pi->fcs == L2CAP_FCS_NONE ||
1673 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1674 pi->fcs = L2CAP_FCS_NONE;
1675 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1676 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001677 break;
1678
1679 case L2CAP_MODE_STREAMING:
1680 rfc.mode = L2CAP_MODE_STREAMING;
1681 rfc.txwin_size = 0;
1682 rfc.max_transmit = 0;
1683 rfc.retrans_timeout = 0;
1684 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001685 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001686 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001687 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001688
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001689 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1690 (unsigned long) &rfc);
1691
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001692 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1693 break;
1694
1695 if (pi->fcs == L2CAP_FCS_NONE ||
1696 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1697 pi->fcs = L2CAP_FCS_NONE;
1698 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1699 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001700 break;
1701 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001703 req->dcid = cpu_to_le16(pi->dcid);
1704 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705
1706 return ptr - data;
1707}
1708
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001709static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001711 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001712 struct l2cap_conf_rsp *rsp = data;
1713 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001714 void *req = chan->conf_req;
1715 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001716 int type, hint, olen;
1717 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001718 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001719 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001720 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001722 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001723
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001724 while (len >= L2CAP_CONF_OPT_SIZE) {
1725 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001727 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001728 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001729
1730 switch (type) {
1731 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001732 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001733 break;
1734
1735 case L2CAP_CONF_FLUSH_TO:
1736 pi->flush_to = val;
1737 break;
1738
1739 case L2CAP_CONF_QOS:
1740 break;
1741
Marcel Holtmann6464f352007-10-20 13:39:51 +02001742 case L2CAP_CONF_RFC:
1743 if (olen == sizeof(rfc))
1744 memcpy(&rfc, (void *) val, olen);
1745 break;
1746
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001747 case L2CAP_CONF_FCS:
1748 if (val == L2CAP_FCS_NONE)
1749 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1750
1751 break;
1752
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001753 default:
1754 if (hint)
1755 break;
1756
1757 result = L2CAP_CONF_UNKNOWN;
1758 *((u8 *) ptr++) = type;
1759 break;
1760 }
1761 }
1762
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001763 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001764 goto done;
1765
1766 switch (pi->mode) {
1767 case L2CAP_MODE_STREAMING:
1768 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001769 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1770 pi->mode = l2cap_select_mode(rfc.mode,
1771 pi->conn->feat_mask);
1772 break;
1773 }
1774
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001775 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001776 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001777
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001778 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001779 }
1780
1781done:
1782 if (pi->mode != rfc.mode) {
1783 result = L2CAP_CONF_UNACCEPT;
1784 rfc.mode = pi->mode;
1785
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001786 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001787 return -ECONNREFUSED;
1788
1789 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1790 sizeof(rfc), (unsigned long) &rfc);
1791 }
1792
1793
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001794 if (result == L2CAP_CONF_SUCCESS) {
1795 /* Configure output options and let the other side know
1796 * which ones we don't like. */
1797
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001798 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1799 result = L2CAP_CONF_UNACCEPT;
1800 else {
1801 pi->omtu = mtu;
1802 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1803 }
1804 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001805
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001806 switch (rfc.mode) {
1807 case L2CAP_MODE_BASIC:
1808 pi->fcs = L2CAP_FCS_NONE;
1809 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1810 break;
1811
1812 case L2CAP_MODE_ERTM:
1813 pi->remote_tx_win = rfc.txwin_size;
1814 pi->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001815
1816 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1817 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001818
1819 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001820
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001821 rfc.retrans_timeout =
1822 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1823 rfc.monitor_timeout =
1824 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001825
1826 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001827
1828 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1829 sizeof(rfc), (unsigned long) &rfc);
1830
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001831 break;
1832
1833 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001834 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1835 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001836
1837 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001838
1839 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001840
1841 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1842 sizeof(rfc), (unsigned long) &rfc);
1843
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001844 break;
1845
1846 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001847 result = L2CAP_CONF_UNACCEPT;
1848
1849 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001850 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001851 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001852
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001853 if (result == L2CAP_CONF_SUCCESS)
1854 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1855 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001856 rsp->scid = cpu_to_le16(pi->dcid);
1857 rsp->result = cpu_to_le16(result);
1858 rsp->flags = cpu_to_le16(0x0000);
1859
1860 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861}
1862
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001863static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1864{
1865 struct l2cap_pinfo *pi = l2cap_pi(sk);
1866 struct l2cap_conf_req *req = data;
1867 void *ptr = req->data;
1868 int type, olen;
1869 unsigned long val;
1870 struct l2cap_conf_rfc rfc;
1871
1872 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1873
1874 while (len >= L2CAP_CONF_OPT_SIZE) {
1875 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1876
1877 switch (type) {
1878 case L2CAP_CONF_MTU:
1879 if (val < L2CAP_DEFAULT_MIN_MTU) {
1880 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001881 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001882 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001883 pi->imtu = val;
1884 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001885 break;
1886
1887 case L2CAP_CONF_FLUSH_TO:
1888 pi->flush_to = val;
1889 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1890 2, pi->flush_to);
1891 break;
1892
1893 case L2CAP_CONF_RFC:
1894 if (olen == sizeof(rfc))
1895 memcpy(&rfc, (void *)val, olen);
1896
1897 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1898 rfc.mode != pi->mode)
1899 return -ECONNREFUSED;
1900
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001901 pi->fcs = 0;
1902
1903 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1904 sizeof(rfc), (unsigned long) &rfc);
1905 break;
1906 }
1907 }
1908
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001909 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1910 return -ECONNREFUSED;
1911
1912 pi->mode = rfc.mode;
1913
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001914 if (*result == L2CAP_CONF_SUCCESS) {
1915 switch (rfc.mode) {
1916 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001917 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1918 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001919 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001920 break;
1921 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001922 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001923 }
1924 }
1925
1926 req->dcid = cpu_to_le16(pi->dcid);
1927 req->flags = cpu_to_le16(0x0000);
1928
1929 return ptr - data;
1930}
1931
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001932static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933{
1934 struct l2cap_conf_rsp *rsp = data;
1935 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001937 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001939 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001940 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001941 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942
1943 return ptr - data;
1944}
1945
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001946void __l2cap_connect_rsp_defer(struct sock *sk)
1947{
1948 struct l2cap_conn_rsp rsp;
1949 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1950 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
1951 u8 buf[128];
1952
1953 sk->sk_state = BT_CONFIG;
1954
1955 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1956 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1957 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1958 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1959 l2cap_send_cmd(conn, chan->ident,
1960 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1961
1962 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
1963 return;
1964
1965 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
1966 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1967 l2cap_build_conf_req(chan, buf), buf);
1968 chan->num_conf_req++;
1969}
1970
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001971static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1972{
1973 struct l2cap_pinfo *pi = l2cap_pi(sk);
1974 int type, olen;
1975 unsigned long val;
1976 struct l2cap_conf_rfc rfc;
1977
1978 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1979
1980 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1981 return;
1982
1983 while (len >= L2CAP_CONF_OPT_SIZE) {
1984 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1985
1986 switch (type) {
1987 case L2CAP_CONF_RFC:
1988 if (olen == sizeof(rfc))
1989 memcpy(&rfc, (void *)val, olen);
1990 goto done;
1991 }
1992 }
1993
1994done:
1995 switch (rfc.mode) {
1996 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001997 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1998 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001999 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2000 break;
2001 case L2CAP_MODE_STREAMING:
2002 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2003 }
2004}
2005
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002006static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2007{
2008 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2009
2010 if (rej->reason != 0x0000)
2011 return 0;
2012
2013 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2014 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002015 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002016
2017 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002018 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002019
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002020 l2cap_conn_start(conn);
2021 }
2022
2023 return 0;
2024}
2025
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2027{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2029 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002030 struct l2cap_chan *chan = NULL;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002031 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002032 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033
2034 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002035 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036
2037 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2038
2039 /* Check if we have socket listening on psm */
2040 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2041 if (!parent) {
2042 result = L2CAP_CR_BAD_PSM;
2043 goto sendresp;
2044 }
2045
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002046 bh_lock_sock(parent);
2047
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002048 /* Check if the ACL is secure enough (if not SDP) */
2049 if (psm != cpu_to_le16(0x0001) &&
2050 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002051 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002052 result = L2CAP_CR_SEC_BLOCK;
2053 goto response;
2054 }
2055
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056 result = L2CAP_CR_NO_MEM;
2057
2058 /* Check for backlog size */
2059 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002060 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 goto response;
2062 }
2063
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002064 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 if (!sk)
2066 goto response;
2067
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002068 chan = l2cap_chan_alloc(sk);
2069 if (!chan) {
2070 l2cap_sock_kill(sk);
2071 goto response;
2072 }
2073
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002074 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075
2076 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002077 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2078 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 sock_set_flag(sk, SOCK_ZAPPED);
2080 l2cap_sock_kill(sk);
2081 goto response;
2082 }
2083
2084 hci_conn_hold(conn->hcon);
2085
2086 l2cap_sock_init(sk, parent);
2087 bacpy(&bt_sk(sk)->src, conn->src);
2088 bacpy(&bt_sk(sk)->dst, conn->dst);
2089 l2cap_pi(sk)->psm = psm;
2090 l2cap_pi(sk)->dcid = scid;
2091
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002092 bt_accept_enqueue(parent, sk);
2093
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002094 __l2cap_chan_add(conn, chan);
2095
2096 l2cap_pi(sk)->chan = chan;
2097
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098 dcid = l2cap_pi(sk)->scid;
2099
2100 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2101
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002102 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103
Marcel Holtmann984947d2009-02-06 23:35:19 +01002104 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002105 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002106 if (bt_sk(sk)->defer_setup) {
2107 sk->sk_state = BT_CONNECT2;
2108 result = L2CAP_CR_PEND;
2109 status = L2CAP_CS_AUTHOR_PEND;
2110 parent->sk_data_ready(parent, 0);
2111 } else {
2112 sk->sk_state = BT_CONFIG;
2113 result = L2CAP_CR_SUCCESS;
2114 status = L2CAP_CS_NO_INFO;
2115 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002116 } else {
2117 sk->sk_state = BT_CONNECT2;
2118 result = L2CAP_CR_PEND;
2119 status = L2CAP_CS_AUTHEN_PEND;
2120 }
2121 } else {
2122 sk->sk_state = BT_CONNECT2;
2123 result = L2CAP_CR_PEND;
2124 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 }
2126
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002127 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128
2129response:
2130 bh_unlock_sock(parent);
2131
2132sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002133 rsp.scid = cpu_to_le16(scid);
2134 rsp.dcid = cpu_to_le16(dcid);
2135 rsp.result = cpu_to_le16(result);
2136 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002138
2139 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2140 struct l2cap_info_req info;
2141 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2142
2143 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2144 conn->info_ident = l2cap_get_ident(conn);
2145
2146 mod_timer(&conn->info_timer, jiffies +
2147 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2148
2149 l2cap_send_cmd(conn, conn->info_ident,
2150 L2CAP_INFO_REQ, sizeof(info), &info);
2151 }
2152
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002153 if (chan && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002154 result == L2CAP_CR_SUCCESS) {
2155 u8 buf[128];
2156 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2157 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002158 l2cap_build_conf_req(chan, buf), buf);
2159 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002160 }
2161
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 return 0;
2163}
2164
2165static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2166{
2167 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2168 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002169 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170 struct sock *sk;
2171 u8 req[128];
2172
2173 scid = __le16_to_cpu(rsp->scid);
2174 dcid = __le16_to_cpu(rsp->dcid);
2175 result = __le16_to_cpu(rsp->result);
2176 status = __le16_to_cpu(rsp->status);
2177
2178 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2179
2180 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002181 chan = l2cap_get_chan_by_scid(conn, scid);
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 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002185 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002186 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002187 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 }
2189
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002190 sk = chan->sk;
2191
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 switch (result) {
2193 case L2CAP_CR_SUCCESS:
2194 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002195 chan->ident = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002197 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2198
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002199 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2200 break;
2201
2202 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2203
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002205 l2cap_build_conf_req(chan, req), req);
2206 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 break;
2208
2209 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002210 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 break;
2212
2213 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002214 /* don't delete l2cap channel if sk is owned by user */
2215 if (sock_owned_by_user(sk)) {
2216 sk->sk_state = BT_DISCONN;
2217 l2cap_sock_clear_timer(sk);
2218 l2cap_sock_set_timer(sk, HZ / 5);
2219 break;
2220 }
2221
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002222 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 break;
2224 }
2225
2226 bh_unlock_sock(sk);
2227 return 0;
2228}
2229
Mat Martineau8c462b62010-08-24 15:35:42 -07002230static inline void set_default_fcs(struct l2cap_pinfo *pi)
2231{
2232 /* FCS is enabled only in ERTM or streaming mode, if one or both
2233 * sides request it.
2234 */
2235 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2236 pi->fcs = L2CAP_FCS_NONE;
2237 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2238 pi->fcs = L2CAP_FCS_CRC16;
2239}
2240
Al Viro88219a02007-07-29 00:17:25 -07002241static 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 -07002242{
2243 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2244 u16 dcid, flags;
2245 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002246 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002248 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249
2250 dcid = __le16_to_cpu(req->dcid);
2251 flags = __le16_to_cpu(req->flags);
2252
2253 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2254
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002255 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002256 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 return -ENOENT;
2258
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002259 sk = chan->sk;
2260
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002261 if (sk->sk_state != BT_CONFIG) {
2262 struct l2cap_cmd_rej rej;
2263
2264 rej.reason = cpu_to_le16(0x0002);
2265 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2266 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002267 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002268 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002269
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002270 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002271 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002272 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002273 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2274 l2cap_build_conf_rsp(sk, rsp,
2275 L2CAP_CONF_REJECT, flags), rsp);
2276 goto unlock;
2277 }
2278
2279 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002280 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2281 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282
2283 if (flags & 0x0001) {
2284 /* Incomplete config. Send empty response. */
2285 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002286 l2cap_build_conf_rsp(sk, rsp,
2287 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 goto unlock;
2289 }
2290
2291 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002292 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002293 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002294 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002296 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002298 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002299 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002300
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002301 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002302 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002303
Marcel Holtmann876d9482007-10-20 13:35:42 +02002304 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2305 goto unlock;
2306
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002308 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002309
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002311
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002312 chan->next_tx_seq = 0;
2313 chan->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002314 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002315 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002316 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002317
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002319 goto unlock;
2320 }
2321
2322 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002323 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002324 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002326 l2cap_build_conf_req(chan, buf), buf);
2327 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 }
2329
2330unlock:
2331 bh_unlock_sock(sk);
2332 return 0;
2333}
2334
2335static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2336{
2337 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2338 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002339 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002341 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342
2343 scid = __le16_to_cpu(rsp->scid);
2344 flags = __le16_to_cpu(rsp->flags);
2345 result = __le16_to_cpu(rsp->result);
2346
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002347 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2348 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002350 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002351 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 return 0;
2353
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002354 sk = chan->sk;
2355
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 switch (result) {
2357 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002358 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 break;
2360
2361 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002362 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002363 char req[64];
2364
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002365 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002366 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002367 goto done;
2368 }
2369
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002370 /* throw out any old stored conf requests */
2371 result = L2CAP_CONF_SUCCESS;
2372 len = l2cap_parse_conf_rsp(sk, rsp->data,
2373 len, req, &result);
2374 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002375 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002376 goto done;
2377 }
2378
2379 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2380 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002381 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002382 if (result != L2CAP_CONF_SUCCESS)
2383 goto done;
2384 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385 }
2386
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002387 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002388 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002390 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 goto done;
2392 }
2393
2394 if (flags & 0x01)
2395 goto done;
2396
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2398
2399 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002400 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002401
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002403 chan->next_tx_seq = 0;
2404 chan->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002405 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002406 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002407 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002408
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409 l2cap_chan_ready(sk);
2410 }
2411
2412done:
2413 bh_unlock_sock(sk);
2414 return 0;
2415}
2416
2417static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2418{
2419 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2420 struct l2cap_disconn_rsp rsp;
2421 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002422 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 struct sock *sk;
2424
2425 scid = __le16_to_cpu(req->scid);
2426 dcid = __le16_to_cpu(req->dcid);
2427
2428 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2429
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002430 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002431 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 return 0;
2433
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002434 sk = chan->sk;
2435
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002436 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2437 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2439
2440 sk->sk_shutdown = SHUTDOWN_MASK;
2441
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002442 /* don't delete l2cap channel if sk is owned by user */
2443 if (sock_owned_by_user(sk)) {
2444 sk->sk_state = BT_DISCONN;
2445 l2cap_sock_clear_timer(sk);
2446 l2cap_sock_set_timer(sk, HZ / 5);
2447 bh_unlock_sock(sk);
2448 return 0;
2449 }
2450
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002451 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 bh_unlock_sock(sk);
2453
2454 l2cap_sock_kill(sk);
2455 return 0;
2456}
2457
2458static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2459{
2460 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2461 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002462 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 struct sock *sk;
2464
2465 scid = __le16_to_cpu(rsp->scid);
2466 dcid = __le16_to_cpu(rsp->dcid);
2467
2468 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2469
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002470 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002471 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472 return 0;
2473
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002474 sk = chan->sk;
2475
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002476 /* don't delete l2cap channel if sk is owned by user */
2477 if (sock_owned_by_user(sk)) {
2478 sk->sk_state = BT_DISCONN;
2479 l2cap_sock_clear_timer(sk);
2480 l2cap_sock_set_timer(sk, HZ / 5);
2481 bh_unlock_sock(sk);
2482 return 0;
2483 }
2484
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002485 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486 bh_unlock_sock(sk);
2487
2488 l2cap_sock_kill(sk);
2489 return 0;
2490}
2491
2492static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2493{
2494 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495 u16 type;
2496
2497 type = __le16_to_cpu(req->type);
2498
2499 BT_DBG("type 0x%4.4x", type);
2500
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002501 if (type == L2CAP_IT_FEAT_MASK) {
2502 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002503 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002504 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2505 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2506 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002507 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002508 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2509 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002510 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002511 l2cap_send_cmd(conn, cmd->ident,
2512 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002513 } else if (type == L2CAP_IT_FIXED_CHAN) {
2514 u8 buf[12];
2515 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2516 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2517 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2518 memcpy(buf + 4, l2cap_fixed_chan, 8);
2519 l2cap_send_cmd(conn, cmd->ident,
2520 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002521 } else {
2522 struct l2cap_info_rsp rsp;
2523 rsp.type = cpu_to_le16(type);
2524 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2525 l2cap_send_cmd(conn, cmd->ident,
2526 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2527 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528
2529 return 0;
2530}
2531
2532static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2533{
2534 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2535 u16 type, result;
2536
2537 type = __le16_to_cpu(rsp->type);
2538 result = __le16_to_cpu(rsp->result);
2539
2540 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2541
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002542 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2543 if (cmd->ident != conn->info_ident ||
2544 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2545 return 0;
2546
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002547 del_timer(&conn->info_timer);
2548
Ville Tervoadb08ed2010-08-04 09:43:33 +03002549 if (result != L2CAP_IR_SUCCESS) {
2550 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2551 conn->info_ident = 0;
2552
2553 l2cap_conn_start(conn);
2554
2555 return 0;
2556 }
2557
Marcel Holtmann984947d2009-02-06 23:35:19 +01002558 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002559 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002560
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002561 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002562 struct l2cap_info_req req;
2563 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2564
2565 conn->info_ident = l2cap_get_ident(conn);
2566
2567 l2cap_send_cmd(conn, conn->info_ident,
2568 L2CAP_INFO_REQ, sizeof(req), &req);
2569 } else {
2570 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2571 conn->info_ident = 0;
2572
2573 l2cap_conn_start(conn);
2574 }
2575 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002576 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002577 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002578
2579 l2cap_conn_start(conn);
2580 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002581
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582 return 0;
2583}
2584
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002585static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002586 u16 to_multiplier)
2587{
2588 u16 max_latency;
2589
2590 if (min > max || min < 6 || max > 3200)
2591 return -EINVAL;
2592
2593 if (to_multiplier < 10 || to_multiplier > 3200)
2594 return -EINVAL;
2595
2596 if (max >= to_multiplier * 8)
2597 return -EINVAL;
2598
2599 max_latency = (to_multiplier * 8 / max) - 1;
2600 if (latency > 499 || latency > max_latency)
2601 return -EINVAL;
2602
2603 return 0;
2604}
2605
2606static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2607 struct l2cap_cmd_hdr *cmd, u8 *data)
2608{
2609 struct hci_conn *hcon = conn->hcon;
2610 struct l2cap_conn_param_update_req *req;
2611 struct l2cap_conn_param_update_rsp rsp;
2612 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002613 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002614
2615 if (!(hcon->link_mode & HCI_LM_MASTER))
2616 return -EINVAL;
2617
2618 cmd_len = __le16_to_cpu(cmd->len);
2619 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2620 return -EPROTO;
2621
2622 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002623 min = __le16_to_cpu(req->min);
2624 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002625 latency = __le16_to_cpu(req->latency);
2626 to_multiplier = __le16_to_cpu(req->to_multiplier);
2627
2628 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2629 min, max, latency, to_multiplier);
2630
2631 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002632
2633 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2634 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002635 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2636 else
2637 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2638
2639 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2640 sizeof(rsp), &rsp);
2641
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002642 if (!err)
2643 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2644
Claudio Takahaside731152011-02-11 19:28:55 -02002645 return 0;
2646}
2647
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002648static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2649 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2650{
2651 int err = 0;
2652
2653 switch (cmd->code) {
2654 case L2CAP_COMMAND_REJ:
2655 l2cap_command_rej(conn, cmd, data);
2656 break;
2657
2658 case L2CAP_CONN_REQ:
2659 err = l2cap_connect_req(conn, cmd, data);
2660 break;
2661
2662 case L2CAP_CONN_RSP:
2663 err = l2cap_connect_rsp(conn, cmd, data);
2664 break;
2665
2666 case L2CAP_CONF_REQ:
2667 err = l2cap_config_req(conn, cmd, cmd_len, data);
2668 break;
2669
2670 case L2CAP_CONF_RSP:
2671 err = l2cap_config_rsp(conn, cmd, data);
2672 break;
2673
2674 case L2CAP_DISCONN_REQ:
2675 err = l2cap_disconnect_req(conn, cmd, data);
2676 break;
2677
2678 case L2CAP_DISCONN_RSP:
2679 err = l2cap_disconnect_rsp(conn, cmd, data);
2680 break;
2681
2682 case L2CAP_ECHO_REQ:
2683 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2684 break;
2685
2686 case L2CAP_ECHO_RSP:
2687 break;
2688
2689 case L2CAP_INFO_REQ:
2690 err = l2cap_information_req(conn, cmd, data);
2691 break;
2692
2693 case L2CAP_INFO_RSP:
2694 err = l2cap_information_rsp(conn, cmd, data);
2695 break;
2696
2697 default:
2698 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2699 err = -EINVAL;
2700 break;
2701 }
2702
2703 return err;
2704}
2705
2706static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2707 struct l2cap_cmd_hdr *cmd, u8 *data)
2708{
2709 switch (cmd->code) {
2710 case L2CAP_COMMAND_REJ:
2711 return 0;
2712
2713 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002714 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002715
2716 case L2CAP_CONN_PARAM_UPDATE_RSP:
2717 return 0;
2718
2719 default:
2720 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2721 return -EINVAL;
2722 }
2723}
2724
2725static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2726 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727{
2728 u8 *data = skb->data;
2729 int len = skb->len;
2730 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002731 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732
2733 l2cap_raw_recv(conn, skb);
2734
2735 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002736 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2738 data += L2CAP_CMD_HDR_SIZE;
2739 len -= L2CAP_CMD_HDR_SIZE;
2740
Al Viro88219a02007-07-29 00:17:25 -07002741 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742
Al Viro88219a02007-07-29 00:17:25 -07002743 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 -07002744
Al Viro88219a02007-07-29 00:17:25 -07002745 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746 BT_DBG("corrupted command");
2747 break;
2748 }
2749
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002750 if (conn->hcon->type == LE_LINK)
2751 err = l2cap_le_sig_cmd(conn, &cmd, data);
2752 else
2753 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754
2755 if (err) {
2756 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002757
2758 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759
2760 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002761 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2763 }
2764
Al Viro88219a02007-07-29 00:17:25 -07002765 data += cmd_len;
2766 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 }
2768
2769 kfree_skb(skb);
2770}
2771
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002772static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2773{
2774 u16 our_fcs, rcv_fcs;
2775 int hdr_size = L2CAP_HDR_SIZE + 2;
2776
2777 if (pi->fcs == L2CAP_FCS_CRC16) {
2778 skb_trim(skb, skb->len - 2);
2779 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2780 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2781
2782 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002783 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002784 }
2785 return 0;
2786}
2787
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002788static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002789{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002790 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002791 u16 control = 0;
2792
2793 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002794
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002795 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002796
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002797 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002798 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002799 l2cap_send_sframe(chan, control);
2800 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002801 }
2802
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002803 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2804 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002805
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002806 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002807
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002808 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002809 pi->frames_sent == 0) {
2810 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002811 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002812 }
2813}
2814
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002815static 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 -03002816{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002817 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002818 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002819 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002820
2821 bt_cb(skb)->tx_seq = tx_seq;
2822 bt_cb(skb)->sar = sar;
2823
2824 next_skb = skb_peek(SREJ_QUEUE(sk));
2825 if (!next_skb) {
2826 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002827 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002828 }
2829
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002830 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002831 if (tx_seq_offset < 0)
2832 tx_seq_offset += 64;
2833
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002834 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002835 if (bt_cb(next_skb)->tx_seq == tx_seq)
2836 return -EINVAL;
2837
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002838 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002839 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002840 if (next_tx_seq_offset < 0)
2841 next_tx_seq_offset += 64;
2842
2843 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002844 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002845 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002846 }
2847
2848 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
2849 break;
2850
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002851 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002852
2853 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002854
2855 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002856}
2857
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002858static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002859{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002860 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002861 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002862 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002863
2864 switch (control & L2CAP_CTRL_SAR) {
2865 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002866 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002867 goto drop;
2868
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002869 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002870 if (!err)
2871 return err;
2872
2873 break;
2874
2875 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002876 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002877 goto drop;
2878
2879 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002880
2881 if (pi->sdu_len > pi->imtu)
2882 goto disconnect;
2883
2884 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002885 if (!pi->sdu)
2886 return -ENOMEM;
2887
2888 /* pull sdu_len bytes only after alloc, because of Local Busy
2889 * condition we have to be sure that this will be executed
2890 * only once, i.e., when alloc does not fail */
2891 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002892
2893 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2894
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002895 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002896 pi->partial_sdu_len = skb->len;
2897 break;
2898
2899 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002900 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002901 goto disconnect;
2902
2903 if (!pi->sdu)
2904 goto disconnect;
2905
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002906 pi->partial_sdu_len += skb->len;
2907 if (pi->partial_sdu_len > pi->sdu_len)
2908 goto drop;
2909
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002910 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2911
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002912 break;
2913
2914 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002915 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002916 goto disconnect;
2917
2918 if (!pi->sdu)
2919 goto disconnect;
2920
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002921 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002922 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002923
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002924 if (pi->partial_sdu_len > pi->imtu)
2925 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002926
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002927 if (pi->partial_sdu_len != pi->sdu_len)
2928 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002929
2930 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002931 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002932
2933 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002934 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002935 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002936 return -ENOMEM;
2937 }
2938
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002939 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002940 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002941 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002942 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002943 return err;
2944 }
2945
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002946 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2947 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002948
2949 kfree_skb(pi->sdu);
2950 break;
2951 }
2952
2953 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002954 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002955
2956drop:
2957 kfree_skb(pi->sdu);
2958 pi->sdu = NULL;
2959
2960disconnect:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002961 l2cap_send_disconn_req(pi->conn, chan->sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002962 kfree_skb(skb);
2963 return 0;
2964}
2965
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002966static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002967{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002968 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002969 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002970 struct sk_buff *skb;
2971 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002972 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002973
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002974 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
2975 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002976 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002977 if (err < 0) {
2978 skb_queue_head(BUSY_QUEUE(sk), skb);
2979 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002980 }
2981
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002982 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002983 }
2984
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002985 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002986 goto done;
2987
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002988 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002989 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002990 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002991 l2cap_pi(sk)->retry_count = 1;
2992
2993 del_timer(&pi->retrans_timer);
2994 __mod_monitor_timer();
2995
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002996 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002997
2998done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002999 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3000 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003001
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003002 BT_DBG("sk %p, Exit local busy", sk);
3003
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003004 return 0;
3005}
3006
3007static void l2cap_busy_work(struct work_struct *work)
3008{
3009 DECLARE_WAITQUEUE(wait, current);
3010 struct l2cap_pinfo *pi =
3011 container_of(work, struct l2cap_pinfo, busy_work);
3012 struct sock *sk = (struct sock *)pi;
3013 int n_tries = 0, timeo = HZ/5, err;
3014 struct sk_buff *skb;
3015
3016 lock_sock(sk);
3017
3018 add_wait_queue(sk_sleep(sk), &wait);
3019 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
3020 set_current_state(TASK_INTERRUPTIBLE);
3021
3022 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3023 err = -EBUSY;
3024 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
3025 break;
3026 }
3027
3028 if (!timeo)
3029 timeo = HZ/5;
3030
3031 if (signal_pending(current)) {
3032 err = sock_intr_errno(timeo);
3033 break;
3034 }
3035
3036 release_sock(sk);
3037 timeo = schedule_timeout(timeo);
3038 lock_sock(sk);
3039
3040 err = sock_error(sk);
3041 if (err)
3042 break;
3043
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003044 if (l2cap_try_push_rx_skb(l2cap_pi(sk)->chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003045 break;
3046 }
3047
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003048 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003049 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003050
3051 release_sock(sk);
3052}
3053
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003054static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003055{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003056 struct sock *sk = chan->sk;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003057 struct l2cap_pinfo *pi = l2cap_pi(sk);
3058 int sctrl, err;
3059
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003060 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003061 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3062 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003063 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003064
3065
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003066 }
3067
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003068 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003069 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003070 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003071 return err;
3072 }
3073
3074 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003075 BT_DBG("sk %p, Enter local busy", sk);
3076
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003077 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003078 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3079 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3080
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003081 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003082 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003083 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003084
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003085 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003086
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003087 del_timer(&pi->ack_timer);
3088
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003089 queue_work(_busy_wq, &pi->busy_work);
3090
3091 return err;
3092}
3093
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003094static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003095{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003096 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003097 struct sk_buff *_skb;
3098 int err = -EINVAL;
3099
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003100 /*
3101 * TODO: We have to notify the userland if some data is lost with the
3102 * Streaming Mode.
3103 */
3104
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003105 switch (control & L2CAP_CTRL_SAR) {
3106 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003107 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003108 kfree_skb(pi->sdu);
3109 break;
3110 }
3111
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003112 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003113 if (!err)
3114 return 0;
3115
3116 break;
3117
3118 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003119 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003120 kfree_skb(pi->sdu);
3121 break;
3122 }
3123
3124 pi->sdu_len = get_unaligned_le16(skb->data);
3125 skb_pull(skb, 2);
3126
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003127 if (pi->sdu_len > pi->imtu) {
3128 err = -EMSGSIZE;
3129 break;
3130 }
3131
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003132 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3133 if (!pi->sdu) {
3134 err = -ENOMEM;
3135 break;
3136 }
3137
3138 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3139
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003140 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003141 pi->partial_sdu_len = skb->len;
3142 err = 0;
3143 break;
3144
3145 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003146 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003147 break;
3148
3149 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3150
3151 pi->partial_sdu_len += skb->len;
3152 if (pi->partial_sdu_len > pi->sdu_len)
3153 kfree_skb(pi->sdu);
3154 else
3155 err = 0;
3156
3157 break;
3158
3159 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003160 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003161 break;
3162
3163 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3164
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003165 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003166 pi->partial_sdu_len += skb->len;
3167
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003168 if (pi->partial_sdu_len > pi->imtu)
3169 goto drop;
3170
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003171 if (pi->partial_sdu_len == pi->sdu_len) {
3172 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003173 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003174 if (err < 0)
3175 kfree_skb(_skb);
3176 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003177 err = 0;
3178
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003179drop:
3180 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003181 break;
3182 }
3183
3184 kfree_skb(skb);
3185 return err;
3186}
3187
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003188static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003189{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003190 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003191 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003192 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003193
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003194 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003195 if (bt_cb(skb)->tx_seq != tx_seq)
3196 break;
3197
3198 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003199 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003200 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003201 chan->buffer_seq_srej =
3202 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003203 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003204 }
3205}
3206
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003207static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003208{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003209 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003210 struct srej_list *l, *tmp;
3211 u16 control;
3212
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003213 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003214 if (l->tx_seq == tx_seq) {
3215 list_del(&l->list);
3216 kfree(l);
3217 return;
3218 }
3219 control = L2CAP_SUPER_SELECT_REJECT;
3220 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003221 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003222 list_del(&l->list);
3223 list_add_tail(&l->list, SREJ_LIST(sk));
3224 }
3225}
3226
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003227static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003228{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003229 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003230 struct srej_list *new;
3231 u16 control;
3232
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003233 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003234 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003235 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003236 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003237
3238 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003239 new->tx_seq = chan->expected_tx_seq;
3240 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003241 list_add_tail(&new->list, SREJ_LIST(sk));
3242 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003243 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003244}
3245
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003246static 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 -03003247{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003248 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003249 struct l2cap_pinfo *pi = l2cap_pi(sk);
3250 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003251 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003252 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003253 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003254 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003255 int err = 0;
3256
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003257 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3258 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003259
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003260 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003261 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003262 del_timer(&pi->monitor_timer);
3263 if (pi->unacked_frames > 0)
3264 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003265 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003266 }
3267
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003268 chan->expected_ack_seq = req_seq;
3269 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003270
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003271 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003272 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003273
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003274 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003275 if (tx_seq_offset < 0)
3276 tx_seq_offset += 64;
3277
3278 /* invalid tx_seq */
3279 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003280 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003281 goto drop;
3282 }
3283
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003284 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003285 goto drop;
3286
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003287 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003288 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003289
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003290 first = list_first_entry(SREJ_LIST(sk),
3291 struct srej_list, list);
3292 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003293 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003294 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003295
3296 list_del(&first->list);
3297 kfree(first);
3298
3299 if (list_empty(SREJ_LIST(sk))) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003300 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003301 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3302 l2cap_send_ack(chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003303 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003304 }
3305 } else {
3306 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003307
3308 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003309 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003310 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003311
3312 list_for_each_entry(l, SREJ_LIST(sk), list) {
3313 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003314 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003315 return 0;
3316 }
3317 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003318 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003319 }
3320 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003321 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003322 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003323 if (expected_tx_seq_offset < 0)
3324 expected_tx_seq_offset += 64;
3325
3326 /* duplicated tx_seq */
3327 if (tx_seq_offset < expected_tx_seq_offset)
3328 goto drop;
3329
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003330 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003331
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003332 BT_DBG("sk %p, Enter SREJ", sk);
3333
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003334 INIT_LIST_HEAD(SREJ_LIST(sk));
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003335 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003336
3337 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003338 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003339 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003340
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003341 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003342
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003343 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003344
3345 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003346 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003347 return 0;
3348
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003349expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003350 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003351
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003352 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003353 bt_cb(skb)->tx_seq = tx_seq;
3354 bt_cb(skb)->sar = sar;
3355 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003356 return 0;
3357 }
3358
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003359 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003360 if (err < 0)
3361 return 0;
3362
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003363 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003364 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3365 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003366 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003367 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003368 }
3369
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003370 __mod_ack_timer();
3371
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003372 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
3373 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003374 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003375
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003376 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003377
3378drop:
3379 kfree_skb(skb);
3380 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003381}
3382
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003383static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003384{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003385 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003386 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003387
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003388 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3389 rx_control);
3390
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003391 chan->expected_ack_seq = __get_reqseq(rx_control);
3392 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003393
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003394 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003395 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3396 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3397 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003398 (pi->unacked_frames > 0))
3399 __mod_retrans_timer();
3400
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003401 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3402 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003403 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003404 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003405 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003406
3407 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003408 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003409
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003410 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3411 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003412 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003413 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003414
3415 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003416 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003417 (pi->unacked_frames > 0))
3418 __mod_retrans_timer();
3419
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003420 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3421 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3422 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003423 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003424 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003425 }
3426}
3427
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003428static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003429{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003430 u8 tx_seq = __get_reqseq(rx_control);
3431
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003432 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003433
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003434 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003435
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003436 chan->expected_ack_seq = tx_seq;
3437 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003438
3439 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003440 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3441 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003442 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003443 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003444 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003445 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003446
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003447 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3448 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003449 }
3450}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003451static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003452{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003453 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003454 u8 tx_seq = __get_reqseq(rx_control);
3455
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003456 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003457
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003458 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003459
3460 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003461 chan->expected_ack_seq = tx_seq;
3462 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003463
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003464 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3465 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003466
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003467 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003468
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003469 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003470 pi->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003471 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003472 }
3473 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003474 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003475 pi->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003476 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003477 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003478 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003479 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003480 l2cap_retransmit_one_frame(chan, tx_seq);
3481 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003482 pi->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003483 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003484 }
3485 }
3486}
3487
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003488static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003489{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003490 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003491 u8 tx_seq = __get_reqseq(rx_control);
3492
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003493 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003494
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003495 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003496 chan->expected_ack_seq = tx_seq;
3497 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003498
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003499 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003500 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003501
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003502 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003503 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003504 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003505 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003506 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003507 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003508
3509 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003510 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003511 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003512 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003513}
3514
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003515static 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 -03003516{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003517 struct sock *sk = chan->sk;
3518
3519 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003520
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003521 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003522 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003523 del_timer(&l2cap_pi(sk)->monitor_timer);
3524 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003525 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003526 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003527 }
3528
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003529 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3530 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003531 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003532 break;
3533
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003534 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003535 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003536 break;
3537
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003538 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003539 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003540 break;
3541
3542 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003543 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003544 break;
3545 }
3546
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003547 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003548 return 0;
3549}
3550
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003551static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3552{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003553 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003554 struct l2cap_pinfo *pi = l2cap_pi(sk);
3555 u16 control;
3556 u8 req_seq;
3557 int len, next_tx_seq_offset, req_seq_offset;
3558
3559 control = get_unaligned_le16(skb->data);
3560 skb_pull(skb, 2);
3561 len = skb->len;
3562
3563 /*
3564 * We can just drop the corrupted I-frame here.
3565 * Receiver will miss it and start proper recovery
3566 * procedures and ask retransmission.
3567 */
3568 if (l2cap_check_fcs(pi, skb))
3569 goto drop;
3570
3571 if (__is_sar_start(control) && __is_iframe(control))
3572 len -= 2;
3573
3574 if (pi->fcs == L2CAP_FCS_CRC16)
3575 len -= 2;
3576
3577 if (len > pi->mps) {
3578 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3579 goto drop;
3580 }
3581
3582 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003583 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003584 if (req_seq_offset < 0)
3585 req_seq_offset += 64;
3586
3587 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003588 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003589 if (next_tx_seq_offset < 0)
3590 next_tx_seq_offset += 64;
3591
3592 /* check for invalid req-seq */
3593 if (req_seq_offset > next_tx_seq_offset) {
3594 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3595 goto drop;
3596 }
3597
3598 if (__is_iframe(control)) {
3599 if (len < 0) {
3600 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3601 goto drop;
3602 }
3603
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003604 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003605 } else {
3606 if (len != 0) {
3607 BT_ERR("%d", len);
3608 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3609 goto drop;
3610 }
3611
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003612 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003613 }
3614
3615 return 0;
3616
3617drop:
3618 kfree_skb(skb);
3619 return 0;
3620}
3621
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3623{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003624 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003626 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003627 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003628 u8 tx_seq;
3629 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003631 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003632 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633 BT_DBG("unknown cid 0x%4.4x", cid);
3634 goto drop;
3635 }
3636
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003637 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003638 pi = l2cap_pi(sk);
3639
Linus Torvalds1da177e2005-04-16 15:20:36 -07003640 BT_DBG("sk %p, len %d", sk, skb->len);
3641
3642 if (sk->sk_state != BT_CONNECTED)
3643 goto drop;
3644
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003645 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003646 case L2CAP_MODE_BASIC:
3647 /* If socket recv buffers overflows we drop data here
3648 * which is *bad* because L2CAP has to be reliable.
3649 * But we don't have any other choice. L2CAP doesn't
3650 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003652 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003653 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003654
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003655 if (!sock_queue_rcv_skb(sk, skb))
3656 goto done;
3657 break;
3658
3659 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003660 if (!sock_owned_by_user(sk)) {
3661 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003662 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003663 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003664 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003665 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003666
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003667 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003668
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003669 case L2CAP_MODE_STREAMING:
3670 control = get_unaligned_le16(skb->data);
3671 skb_pull(skb, 2);
3672 len = skb->len;
3673
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003674 if (l2cap_check_fcs(pi, skb))
3675 goto drop;
3676
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003677 if (__is_sar_start(control))
3678 len -= 2;
3679
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003680 if (pi->fcs == L2CAP_FCS_CRC16)
3681 len -= 2;
3682
Nathan Holstein51893f82010-06-09 15:46:25 -04003683 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003684 goto drop;
3685
3686 tx_seq = __get_txseq(control);
3687
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003688 if (chan->expected_tx_seq == tx_seq)
3689 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003690 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003691 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003692
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003693 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003694
3695 goto done;
3696
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003697 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003698 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003699 break;
3700 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701
3702drop:
3703 kfree_skb(skb);
3704
3705done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003706 if (sk)
3707 bh_unlock_sock(sk);
3708
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709 return 0;
3710}
3711
Al Viro8e036fc2007-07-29 00:16:36 -07003712static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713{
3714 struct sock *sk;
3715
3716 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3717 if (!sk)
3718 goto drop;
3719
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003720 bh_lock_sock(sk);
3721
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722 BT_DBG("sk %p, len %d", sk, skb->len);
3723
3724 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3725 goto drop;
3726
3727 if (l2cap_pi(sk)->imtu < skb->len)
3728 goto drop;
3729
3730 if (!sock_queue_rcv_skb(sk, skb))
3731 goto done;
3732
3733drop:
3734 kfree_skb(skb);
3735
3736done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003737 if (sk)
3738 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003739 return 0;
3740}
3741
3742static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3743{
3744 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003745 u16 cid, len;
3746 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747
3748 skb_pull(skb, L2CAP_HDR_SIZE);
3749 cid = __le16_to_cpu(lh->cid);
3750 len = __le16_to_cpu(lh->len);
3751
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003752 if (len != skb->len) {
3753 kfree_skb(skb);
3754 return;
3755 }
3756
Linus Torvalds1da177e2005-04-16 15:20:36 -07003757 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3758
3759 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003760 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003761 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003762 l2cap_sig_channel(conn, skb);
3763 break;
3764
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003765 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003766 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003767 skb_pull(skb, 2);
3768 l2cap_conless_channel(conn, psm, skb);
3769 break;
3770
3771 default:
3772 l2cap_data_channel(conn, cid, skb);
3773 break;
3774 }
3775}
3776
3777/* ---- L2CAP interface with lower layer (HCI) ---- */
3778
3779static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3780{
3781 int exact = 0, lm1 = 0, lm2 = 0;
3782 register struct sock *sk;
3783 struct hlist_node *node;
3784
3785 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003786 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003787
3788 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3789
3790 /* Find listening sockets and check their link_mode */
3791 read_lock(&l2cap_sk_list.lock);
3792 sk_for_each(sk, node, &l2cap_sk_list.head) {
3793 if (sk->sk_state != BT_LISTEN)
3794 continue;
3795
3796 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003797 lm1 |= HCI_LM_ACCEPT;
3798 if (l2cap_pi(sk)->role_switch)
3799 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003801 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3802 lm2 |= HCI_LM_ACCEPT;
3803 if (l2cap_pi(sk)->role_switch)
3804 lm2 |= HCI_LM_MASTER;
3805 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806 }
3807 read_unlock(&l2cap_sk_list.lock);
3808
3809 return exact ? lm1 : lm2;
3810}
3811
3812static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3813{
Marcel Holtmann01394182006-07-03 10:02:46 +02003814 struct l2cap_conn *conn;
3815
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3817
Ville Tervoacd7d372011-02-10 22:38:49 -03003818 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003819 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003820
3821 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822 conn = l2cap_conn_add(hcon, status);
3823 if (conn)
3824 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003825 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826 l2cap_conn_del(hcon, bt_err(status));
3827
3828 return 0;
3829}
3830
Marcel Holtmann2950f212009-02-12 14:02:50 +01003831static int l2cap_disconn_ind(struct hci_conn *hcon)
3832{
3833 struct l2cap_conn *conn = hcon->l2cap_data;
3834
3835 BT_DBG("hcon %p", hcon);
3836
3837 if (hcon->type != ACL_LINK || !conn)
3838 return 0x13;
3839
3840 return conn->disc_reason;
3841}
3842
3843static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844{
3845 BT_DBG("hcon %p reason %d", hcon, reason);
3846
Ville Tervoacd7d372011-02-10 22:38:49 -03003847 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003848 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003849
3850 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003851
Linus Torvalds1da177e2005-04-16 15:20:36 -07003852 return 0;
3853}
3854
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003855static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3856{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003857 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003858 return;
3859
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003860 if (encrypt == 0x00) {
3861 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3862 l2cap_sock_clear_timer(sk);
3863 l2cap_sock_set_timer(sk, HZ * 5);
3864 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3865 __l2cap_sock_close(sk, ECONNREFUSED);
3866 } else {
3867 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3868 l2cap_sock_clear_timer(sk);
3869 }
3870}
3871
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003872static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003874 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003875 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876
Marcel Holtmann01394182006-07-03 10:02:46 +02003877 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003879
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880 BT_DBG("conn %p", conn);
3881
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003882 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003884 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003885 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003886
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887 bh_lock_sock(sk);
3888
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003889 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3890 bh_unlock_sock(sk);
3891 continue;
3892 }
3893
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003894 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003895 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003896 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003897 bh_unlock_sock(sk);
3898 continue;
3899 }
3900
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003901 if (sk->sk_state == BT_CONNECT) {
3902 if (!status) {
3903 struct l2cap_conn_req req;
3904 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3905 req.psm = l2cap_pi(sk)->psm;
3906
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003907 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003908 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003909
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003910 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003911 L2CAP_CONN_REQ, sizeof(req), &req);
3912 } else {
3913 l2cap_sock_clear_timer(sk);
3914 l2cap_sock_set_timer(sk, HZ / 10);
3915 }
3916 } else if (sk->sk_state == BT_CONNECT2) {
3917 struct l2cap_conn_rsp rsp;
3918 __u16 result;
3919
3920 if (!status) {
3921 sk->sk_state = BT_CONFIG;
3922 result = L2CAP_CR_SUCCESS;
3923 } else {
3924 sk->sk_state = BT_DISCONN;
3925 l2cap_sock_set_timer(sk, HZ / 10);
3926 result = L2CAP_CR_SEC_BLOCK;
3927 }
3928
3929 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3930 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3931 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003932 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003933 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
3934 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003935 }
3936
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937 bh_unlock_sock(sk);
3938 }
3939
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003940 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003941
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942 return 0;
3943}
3944
3945static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3946{
3947 struct l2cap_conn *conn = hcon->l2cap_data;
3948
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003949 if (!conn)
3950 conn = l2cap_conn_add(hcon, 0);
3951
3952 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953 goto drop;
3954
3955 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3956
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003957 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003959 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003960 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961 int len;
3962
3963 if (conn->rx_len) {
3964 BT_ERR("Unexpected start frame (len %d)", skb->len);
3965 kfree_skb(conn->rx_skb);
3966 conn->rx_skb = NULL;
3967 conn->rx_len = 0;
3968 l2cap_conn_unreliable(conn, ECOMM);
3969 }
3970
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003971 /* Start fragment always begin with Basic L2CAP header */
3972 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973 BT_ERR("Frame is too short (len %d)", skb->len);
3974 l2cap_conn_unreliable(conn, ECOMM);
3975 goto drop;
3976 }
3977
3978 hdr = (struct l2cap_hdr *) skb->data;
3979 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003980 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981
3982 if (len == skb->len) {
3983 /* Complete frame received */
3984 l2cap_recv_frame(conn, skb);
3985 return 0;
3986 }
3987
3988 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3989
3990 if (skb->len > len) {
3991 BT_ERR("Frame is too long (len %d, expected len %d)",
3992 skb->len, len);
3993 l2cap_conn_unreliable(conn, ECOMM);
3994 goto drop;
3995 }
3996
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003997 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003998
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003999 if (chan && chan->sk) {
4000 struct sock *sk = chan->sk;
4001
4002 if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
4003 BT_ERR("Frame exceeding recv MTU (len %d, "
4004 "MTU %d)", len,
4005 l2cap_pi(sk)->imtu);
4006 bh_unlock_sock(sk);
4007 l2cap_conn_unreliable(conn, ECOMM);
4008 goto drop;
4009 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004010 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004011 }
4012
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004014 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4015 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016 goto drop;
4017
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004018 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004019 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020 conn->rx_len = len - skb->len;
4021 } else {
4022 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4023
4024 if (!conn->rx_len) {
4025 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4026 l2cap_conn_unreliable(conn, ECOMM);
4027 goto drop;
4028 }
4029
4030 if (skb->len > conn->rx_len) {
4031 BT_ERR("Fragment is too long (len %d, expected %d)",
4032 skb->len, conn->rx_len);
4033 kfree_skb(conn->rx_skb);
4034 conn->rx_skb = NULL;
4035 conn->rx_len = 0;
4036 l2cap_conn_unreliable(conn, ECOMM);
4037 goto drop;
4038 }
4039
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004040 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004041 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042 conn->rx_len -= skb->len;
4043
4044 if (!conn->rx_len) {
4045 /* Complete frame received */
4046 l2cap_recv_frame(conn, conn->rx_skb);
4047 conn->rx_skb = NULL;
4048 }
4049 }
4050
4051drop:
4052 kfree_skb(skb);
4053 return 0;
4054}
4055
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004056static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057{
4058 struct sock *sk;
4059 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060
4061 read_lock_bh(&l2cap_sk_list.lock);
4062
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004063 sk_for_each(sk, node, &l2cap_sk_list.head) {
4064 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004066 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 +01004067 batostr(&bt_sk(sk)->src),
4068 batostr(&bt_sk(sk)->dst),
4069 sk->sk_state, __le16_to_cpu(pi->psm),
4070 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004071 pi->imtu, pi->omtu, pi->sec_level,
4072 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004073 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004076
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004077 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078}
4079
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004080static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4081{
4082 return single_open(file, l2cap_debugfs_show, inode->i_private);
4083}
4084
4085static const struct file_operations l2cap_debugfs_fops = {
4086 .open = l2cap_debugfs_open,
4087 .read = seq_read,
4088 .llseek = seq_lseek,
4089 .release = single_release,
4090};
4091
4092static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094static struct hci_proto l2cap_hci_proto = {
4095 .name = "L2CAP",
4096 .id = HCI_PROTO_L2CAP,
4097 .connect_ind = l2cap_connect_ind,
4098 .connect_cfm = l2cap_connect_cfm,
4099 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004100 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004101 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102 .recv_acldata = l2cap_recv_acldata
4103};
4104
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004105int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106{
4107 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004108
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004109 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110 if (err < 0)
4111 return err;
4112
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004113 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004114 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004115 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116 goto error;
4117 }
4118
4119 err = hci_register_proto(&l2cap_hci_proto);
4120 if (err < 0) {
4121 BT_ERR("L2CAP protocol registration failed");
4122 bt_sock_unregister(BTPROTO_L2CAP);
4123 goto error;
4124 }
4125
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004126 if (bt_debugfs) {
4127 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4128 bt_debugfs, NULL, &l2cap_debugfs_fops);
4129 if (!l2cap_debugfs)
4130 BT_ERR("Failed to create L2CAP debug file");
4131 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133 return 0;
4134
4135error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004136 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004137 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138 return err;
4139}
4140
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004141void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004143 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004145 flush_workqueue(_busy_wq);
4146 destroy_workqueue(_busy_wq);
4147
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4149 BT_ERR("L2CAP protocol unregistration failed");
4150
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004151 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152}
4153
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004154module_param(disable_ertm, bool, 0644);
4155MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");