blob: 3f601d1c164acb3a2ae4b8569f360db3b027bdcc [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. Padovan6a026612011-04-01 00:38:50 -0300927 while ((l2cap_pi(sk)->chan->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300928 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. Padovan6a026612011-04-01 00:38:50 -0300959 if (chan->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
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300965 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300966 __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. Padovan6a026612011-04-01 00:38:50 -0300980 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300981 __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))) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300995 chan->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
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001002 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001003 }
1004
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001005 if (!chan->unacked_frames)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001006 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)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001144 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301145
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001146 chan->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. Padovan6a026612011-04-01 00:38:50 -03001577 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001578 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001579 chan->num_acked = 0;
1580 chan->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. Padovand5392c82010-05-01 16:15:36 -03002790 u16 control = 0;
2791
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002792 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002793
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002794 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002795
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002796 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002797 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002798 l2cap_send_sframe(chan, control);
2799 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002800 }
2801
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002802 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2803 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002804
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002805 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002806
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002807 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002808 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002809 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002810 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002811 }
2812}
2813
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002814static 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 -03002815{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002816 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002817 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002818 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002819
2820 bt_cb(skb)->tx_seq = tx_seq;
2821 bt_cb(skb)->sar = sar;
2822
2823 next_skb = skb_peek(SREJ_QUEUE(sk));
2824 if (!next_skb) {
2825 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002826 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002827 }
2828
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002829 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002830 if (tx_seq_offset < 0)
2831 tx_seq_offset += 64;
2832
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002833 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002834 if (bt_cb(next_skb)->tx_seq == tx_seq)
2835 return -EINVAL;
2836
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002837 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002838 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002839 if (next_tx_seq_offset < 0)
2840 next_tx_seq_offset += 64;
2841
2842 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002843 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002844 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002845 }
2846
2847 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
2848 break;
2849
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002850 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002851
2852 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002853
2854 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002855}
2856
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002857static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002858{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002859 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002860 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002861 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002862
2863 switch (control & L2CAP_CTRL_SAR) {
2864 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002865 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002866 goto drop;
2867
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002868 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002869 if (!err)
2870 return err;
2871
2872 break;
2873
2874 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002875 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002876 goto drop;
2877
2878 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002879
2880 if (pi->sdu_len > pi->imtu)
2881 goto disconnect;
2882
2883 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002884 if (!pi->sdu)
2885 return -ENOMEM;
2886
2887 /* pull sdu_len bytes only after alloc, because of Local Busy
2888 * condition we have to be sure that this will be executed
2889 * only once, i.e., when alloc does not fail */
2890 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002891
2892 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2893
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002894 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002895 pi->partial_sdu_len = skb->len;
2896 break;
2897
2898 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002899 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002900 goto disconnect;
2901
2902 if (!pi->sdu)
2903 goto disconnect;
2904
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002905 pi->partial_sdu_len += skb->len;
2906 if (pi->partial_sdu_len > pi->sdu_len)
2907 goto drop;
2908
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002909 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2910
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002911 break;
2912
2913 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002914 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002915 goto disconnect;
2916
2917 if (!pi->sdu)
2918 goto disconnect;
2919
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002920 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002921 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002922
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002923 if (pi->partial_sdu_len > pi->imtu)
2924 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002925
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002926 if (pi->partial_sdu_len != pi->sdu_len)
2927 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002928
2929 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002930 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002931
2932 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002933 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002934 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002935 return -ENOMEM;
2936 }
2937
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002938 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002939 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002940 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002941 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002942 return err;
2943 }
2944
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002945 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2946 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002947
2948 kfree_skb(pi->sdu);
2949 break;
2950 }
2951
2952 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002953 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002954
2955drop:
2956 kfree_skb(pi->sdu);
2957 pi->sdu = NULL;
2958
2959disconnect:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002960 l2cap_send_disconn_req(pi->conn, chan->sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002961 kfree_skb(skb);
2962 return 0;
2963}
2964
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002965static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002966{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002967 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002968 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002969 struct sk_buff *skb;
2970 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002971 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002972
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002973 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
2974 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002975 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002976 if (err < 0) {
2977 skb_queue_head(BUSY_QUEUE(sk), skb);
2978 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002979 }
2980
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002981 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002982 }
2983
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002984 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002985 goto done;
2986
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002987 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002988 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002989 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002990 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002991
2992 del_timer(&pi->retrans_timer);
2993 __mod_monitor_timer();
2994
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002995 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002996
2997done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002998 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2999 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003000
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003001 BT_DBG("sk %p, Exit local busy", sk);
3002
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003003 return 0;
3004}
3005
3006static void l2cap_busy_work(struct work_struct *work)
3007{
3008 DECLARE_WAITQUEUE(wait, current);
3009 struct l2cap_pinfo *pi =
3010 container_of(work, struct l2cap_pinfo, busy_work);
3011 struct sock *sk = (struct sock *)pi;
3012 int n_tries = 0, timeo = HZ/5, err;
3013 struct sk_buff *skb;
3014
3015 lock_sock(sk);
3016
3017 add_wait_queue(sk_sleep(sk), &wait);
3018 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
3019 set_current_state(TASK_INTERRUPTIBLE);
3020
3021 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3022 err = -EBUSY;
3023 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
3024 break;
3025 }
3026
3027 if (!timeo)
3028 timeo = HZ/5;
3029
3030 if (signal_pending(current)) {
3031 err = sock_intr_errno(timeo);
3032 break;
3033 }
3034
3035 release_sock(sk);
3036 timeo = schedule_timeout(timeo);
3037 lock_sock(sk);
3038
3039 err = sock_error(sk);
3040 if (err)
3041 break;
3042
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003043 if (l2cap_try_push_rx_skb(l2cap_pi(sk)->chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003044 break;
3045 }
3046
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003047 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003048 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003049
3050 release_sock(sk);
3051}
3052
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003053static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003054{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003055 struct sock *sk = chan->sk;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003056 struct l2cap_pinfo *pi = l2cap_pi(sk);
3057 int sctrl, err;
3058
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003059 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003060 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3061 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003062 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003063
3064
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003065 }
3066
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003067 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003068 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003069 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003070 return err;
3071 }
3072
3073 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003074 BT_DBG("sk %p, Enter local busy", sk);
3075
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003076 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003077 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3078 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3079
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003080 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003081 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003082 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003083
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003084 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003085
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003086 del_timer(&pi->ack_timer);
3087
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003088 queue_work(_busy_wq, &pi->busy_work);
3089
3090 return err;
3091}
3092
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003093static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003094{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003095 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003096 struct sk_buff *_skb;
3097 int err = -EINVAL;
3098
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003099 /*
3100 * TODO: We have to notify the userland if some data is lost with the
3101 * Streaming Mode.
3102 */
3103
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003104 switch (control & L2CAP_CTRL_SAR) {
3105 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003106 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003107 kfree_skb(pi->sdu);
3108 break;
3109 }
3110
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003111 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003112 if (!err)
3113 return 0;
3114
3115 break;
3116
3117 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003118 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003119 kfree_skb(pi->sdu);
3120 break;
3121 }
3122
3123 pi->sdu_len = get_unaligned_le16(skb->data);
3124 skb_pull(skb, 2);
3125
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003126 if (pi->sdu_len > pi->imtu) {
3127 err = -EMSGSIZE;
3128 break;
3129 }
3130
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003131 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3132 if (!pi->sdu) {
3133 err = -ENOMEM;
3134 break;
3135 }
3136
3137 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3138
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003139 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003140 pi->partial_sdu_len = skb->len;
3141 err = 0;
3142 break;
3143
3144 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003145 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003146 break;
3147
3148 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3149
3150 pi->partial_sdu_len += skb->len;
3151 if (pi->partial_sdu_len > pi->sdu_len)
3152 kfree_skb(pi->sdu);
3153 else
3154 err = 0;
3155
3156 break;
3157
3158 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003159 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003160 break;
3161
3162 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3163
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003164 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003165 pi->partial_sdu_len += skb->len;
3166
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003167 if (pi->partial_sdu_len > pi->imtu)
3168 goto drop;
3169
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003170 if (pi->partial_sdu_len == pi->sdu_len) {
3171 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003172 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003173 if (err < 0)
3174 kfree_skb(_skb);
3175 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003176 err = 0;
3177
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003178drop:
3179 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003180 break;
3181 }
3182
3183 kfree_skb(skb);
3184 return err;
3185}
3186
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003187static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003188{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003189 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003190 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003191 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003192
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003193 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003194 if (bt_cb(skb)->tx_seq != tx_seq)
3195 break;
3196
3197 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003198 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003199 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003200 chan->buffer_seq_srej =
3201 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003202 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003203 }
3204}
3205
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003206static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003207{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003208 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003209 struct srej_list *l, *tmp;
3210 u16 control;
3211
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003212 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003213 if (l->tx_seq == tx_seq) {
3214 list_del(&l->list);
3215 kfree(l);
3216 return;
3217 }
3218 control = L2CAP_SUPER_SELECT_REJECT;
3219 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003220 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003221 list_del(&l->list);
3222 list_add_tail(&l->list, SREJ_LIST(sk));
3223 }
3224}
3225
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003226static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003227{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003228 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003229 struct srej_list *new;
3230 u16 control;
3231
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003232 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003233 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003234 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003235 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003236
3237 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003238 new->tx_seq = chan->expected_tx_seq;
3239 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003240 list_add_tail(&new->list, SREJ_LIST(sk));
3241 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003242 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003243}
3244
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003245static 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 -03003246{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003247 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003248 struct l2cap_pinfo *pi = l2cap_pi(sk);
3249 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003250 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003251 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003252 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003253 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003254 int err = 0;
3255
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003256 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3257 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003258
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003259 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003260 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003261 del_timer(&pi->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003262 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003263 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003264 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003265 }
3266
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003267 chan->expected_ack_seq = req_seq;
3268 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003269
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003270 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003271 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003272
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003273 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003274 if (tx_seq_offset < 0)
3275 tx_seq_offset += 64;
3276
3277 /* invalid tx_seq */
3278 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003279 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003280 goto drop;
3281 }
3282
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003283 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003284 goto drop;
3285
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003286 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003287 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003288
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003289 first = list_first_entry(SREJ_LIST(sk),
3290 struct srej_list, list);
3291 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003292 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003293 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003294
3295 list_del(&first->list);
3296 kfree(first);
3297
3298 if (list_empty(SREJ_LIST(sk))) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003299 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003300 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3301 l2cap_send_ack(chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003302 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003303 }
3304 } else {
3305 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003306
3307 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003308 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003309 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003310
3311 list_for_each_entry(l, SREJ_LIST(sk), list) {
3312 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003313 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003314 return 0;
3315 }
3316 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003317 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003318 }
3319 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003320 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003321 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003322 if (expected_tx_seq_offset < 0)
3323 expected_tx_seq_offset += 64;
3324
3325 /* duplicated tx_seq */
3326 if (tx_seq_offset < expected_tx_seq_offset)
3327 goto drop;
3328
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003329 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003330
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003331 BT_DBG("sk %p, Enter SREJ", sk);
3332
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003333 INIT_LIST_HEAD(SREJ_LIST(sk));
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003334 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003335
3336 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003337 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003338 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003339
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003340 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003341
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003342 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003343
3344 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003345 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003346 return 0;
3347
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003348expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003349 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003350
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003351 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003352 bt_cb(skb)->tx_seq = tx_seq;
3353 bt_cb(skb)->sar = sar;
3354 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003355 return 0;
3356 }
3357
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003358 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003359 if (err < 0)
3360 return 0;
3361
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003362 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003363 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3364 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003365 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003366 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003367 }
3368
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003369 __mod_ack_timer();
3370
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003371 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3372 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003373 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003374
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003375 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003376
3377drop:
3378 kfree_skb(skb);
3379 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003380}
3381
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003382static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003383{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003384 struct sock *sk = chan->sk;
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003385
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003386 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3387 rx_control);
3388
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003389 chan->expected_ack_seq = __get_reqseq(rx_control);
3390 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003391
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003392 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003393 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3394 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3395 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003396 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003397 __mod_retrans_timer();
3398
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003399 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3400 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003401 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003402 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003403 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003404
3405 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003406 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003407
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003408 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3409 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003410 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003411 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003412
3413 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003414 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003415 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003416 __mod_retrans_timer();
3417
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003418 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3419 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3420 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003421 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003422 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003423 }
3424}
3425
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003426static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003427{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003428 u8 tx_seq = __get_reqseq(rx_control);
3429
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003430 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003431
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003432 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003433
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003434 chan->expected_ack_seq = tx_seq;
3435 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003436
3437 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003438 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3439 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003440 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003441 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003442 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003443 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003444
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003445 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3446 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003447 }
3448}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003449static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003450{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003451 u8 tx_seq = __get_reqseq(rx_control);
3452
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003453 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003454
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003455 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003456
3457 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003458 chan->expected_ack_seq = tx_seq;
3459 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003460
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003461 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3462 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003463
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003464 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003465
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003466 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003467 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003468 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003469 }
3470 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003471 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003472 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003473 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003474 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003475 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003476 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003477 l2cap_retransmit_one_frame(chan, tx_seq);
3478 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003479 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003480 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003481 }
3482 }
3483}
3484
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003485static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003486{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003487 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003488 u8 tx_seq = __get_reqseq(rx_control);
3489
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003490 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003491
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003492 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003493 chan->expected_ack_seq = tx_seq;
3494 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003495
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003496 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003497 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003498
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003499 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003500 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003501 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003502 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003503 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003504 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003505
3506 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003507 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003508 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003509 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003510}
3511
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003512static 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 -03003513{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003514 struct sock *sk = chan->sk;
3515
3516 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003517
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003518 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003519 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003520 del_timer(&l2cap_pi(sk)->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003521 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003522 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003523 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003524 }
3525
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003526 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3527 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003528 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003529 break;
3530
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003531 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003532 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003533 break;
3534
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003535 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003536 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003537 break;
3538
3539 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003540 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003541 break;
3542 }
3543
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003544 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003545 return 0;
3546}
3547
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003548static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3549{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003550 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003551 struct l2cap_pinfo *pi = l2cap_pi(sk);
3552 u16 control;
3553 u8 req_seq;
3554 int len, next_tx_seq_offset, req_seq_offset;
3555
3556 control = get_unaligned_le16(skb->data);
3557 skb_pull(skb, 2);
3558 len = skb->len;
3559
3560 /*
3561 * We can just drop the corrupted I-frame here.
3562 * Receiver will miss it and start proper recovery
3563 * procedures and ask retransmission.
3564 */
3565 if (l2cap_check_fcs(pi, skb))
3566 goto drop;
3567
3568 if (__is_sar_start(control) && __is_iframe(control))
3569 len -= 2;
3570
3571 if (pi->fcs == L2CAP_FCS_CRC16)
3572 len -= 2;
3573
3574 if (len > pi->mps) {
3575 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3576 goto drop;
3577 }
3578
3579 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003580 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003581 if (req_seq_offset < 0)
3582 req_seq_offset += 64;
3583
3584 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003585 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003586 if (next_tx_seq_offset < 0)
3587 next_tx_seq_offset += 64;
3588
3589 /* check for invalid req-seq */
3590 if (req_seq_offset > next_tx_seq_offset) {
3591 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3592 goto drop;
3593 }
3594
3595 if (__is_iframe(control)) {
3596 if (len < 0) {
3597 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3598 goto drop;
3599 }
3600
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003601 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003602 } else {
3603 if (len != 0) {
3604 BT_ERR("%d", len);
3605 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3606 goto drop;
3607 }
3608
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003609 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003610 }
3611
3612 return 0;
3613
3614drop:
3615 kfree_skb(skb);
3616 return 0;
3617}
3618
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3620{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003621 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003623 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003624 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003625 u8 tx_seq;
3626 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003628 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003629 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630 BT_DBG("unknown cid 0x%4.4x", cid);
3631 goto drop;
3632 }
3633
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003634 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003635 pi = l2cap_pi(sk);
3636
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637 BT_DBG("sk %p, len %d", sk, skb->len);
3638
3639 if (sk->sk_state != BT_CONNECTED)
3640 goto drop;
3641
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003642 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003643 case L2CAP_MODE_BASIC:
3644 /* If socket recv buffers overflows we drop data here
3645 * which is *bad* because L2CAP has to be reliable.
3646 * But we don't have any other choice. L2CAP doesn't
3647 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003648
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003649 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003650 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003652 if (!sock_queue_rcv_skb(sk, skb))
3653 goto done;
3654 break;
3655
3656 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003657 if (!sock_owned_by_user(sk)) {
3658 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003659 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003660 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003661 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003662 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003663
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003664 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003665
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003666 case L2CAP_MODE_STREAMING:
3667 control = get_unaligned_le16(skb->data);
3668 skb_pull(skb, 2);
3669 len = skb->len;
3670
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003671 if (l2cap_check_fcs(pi, skb))
3672 goto drop;
3673
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003674 if (__is_sar_start(control))
3675 len -= 2;
3676
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003677 if (pi->fcs == L2CAP_FCS_CRC16)
3678 len -= 2;
3679
Nathan Holstein51893f82010-06-09 15:46:25 -04003680 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003681 goto drop;
3682
3683 tx_seq = __get_txseq(control);
3684
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003685 if (chan->expected_tx_seq == tx_seq)
3686 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003687 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003688 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003689
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003690 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003691
3692 goto done;
3693
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003694 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003695 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003696 break;
3697 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698
3699drop:
3700 kfree_skb(skb);
3701
3702done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003703 if (sk)
3704 bh_unlock_sock(sk);
3705
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706 return 0;
3707}
3708
Al Viro8e036fc2007-07-29 00:16:36 -07003709static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710{
3711 struct sock *sk;
3712
3713 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3714 if (!sk)
3715 goto drop;
3716
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003717 bh_lock_sock(sk);
3718
Linus Torvalds1da177e2005-04-16 15:20:36 -07003719 BT_DBG("sk %p, len %d", sk, skb->len);
3720
3721 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3722 goto drop;
3723
3724 if (l2cap_pi(sk)->imtu < skb->len)
3725 goto drop;
3726
3727 if (!sock_queue_rcv_skb(sk, skb))
3728 goto done;
3729
3730drop:
3731 kfree_skb(skb);
3732
3733done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003734 if (sk)
3735 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736 return 0;
3737}
3738
3739static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3740{
3741 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003742 u16 cid, len;
3743 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003744
3745 skb_pull(skb, L2CAP_HDR_SIZE);
3746 cid = __le16_to_cpu(lh->cid);
3747 len = __le16_to_cpu(lh->len);
3748
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003749 if (len != skb->len) {
3750 kfree_skb(skb);
3751 return;
3752 }
3753
Linus Torvalds1da177e2005-04-16 15:20:36 -07003754 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3755
3756 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003757 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003758 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003759 l2cap_sig_channel(conn, skb);
3760 break;
3761
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003762 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003763 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764 skb_pull(skb, 2);
3765 l2cap_conless_channel(conn, psm, skb);
3766 break;
3767
3768 default:
3769 l2cap_data_channel(conn, cid, skb);
3770 break;
3771 }
3772}
3773
3774/* ---- L2CAP interface with lower layer (HCI) ---- */
3775
3776static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3777{
3778 int exact = 0, lm1 = 0, lm2 = 0;
3779 register struct sock *sk;
3780 struct hlist_node *node;
3781
3782 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003783 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784
3785 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3786
3787 /* Find listening sockets and check their link_mode */
3788 read_lock(&l2cap_sk_list.lock);
3789 sk_for_each(sk, node, &l2cap_sk_list.head) {
3790 if (sk->sk_state != BT_LISTEN)
3791 continue;
3792
3793 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003794 lm1 |= HCI_LM_ACCEPT;
3795 if (l2cap_pi(sk)->role_switch)
3796 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003798 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3799 lm2 |= HCI_LM_ACCEPT;
3800 if (l2cap_pi(sk)->role_switch)
3801 lm2 |= HCI_LM_MASTER;
3802 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003803 }
3804 read_unlock(&l2cap_sk_list.lock);
3805
3806 return exact ? lm1 : lm2;
3807}
3808
3809static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3810{
Marcel Holtmann01394182006-07-03 10:02:46 +02003811 struct l2cap_conn *conn;
3812
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3814
Ville Tervoacd7d372011-02-10 22:38:49 -03003815 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003816 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817
3818 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819 conn = l2cap_conn_add(hcon, status);
3820 if (conn)
3821 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003822 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003823 l2cap_conn_del(hcon, bt_err(status));
3824
3825 return 0;
3826}
3827
Marcel Holtmann2950f212009-02-12 14:02:50 +01003828static int l2cap_disconn_ind(struct hci_conn *hcon)
3829{
3830 struct l2cap_conn *conn = hcon->l2cap_data;
3831
3832 BT_DBG("hcon %p", hcon);
3833
3834 if (hcon->type != ACL_LINK || !conn)
3835 return 0x13;
3836
3837 return conn->disc_reason;
3838}
3839
3840static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841{
3842 BT_DBG("hcon %p reason %d", hcon, reason);
3843
Ville Tervoacd7d372011-02-10 22:38:49 -03003844 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003845 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846
3847 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003848
Linus Torvalds1da177e2005-04-16 15:20:36 -07003849 return 0;
3850}
3851
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003852static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3853{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003854 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003855 return;
3856
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003857 if (encrypt == 0x00) {
3858 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3859 l2cap_sock_clear_timer(sk);
3860 l2cap_sock_set_timer(sk, HZ * 5);
3861 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3862 __l2cap_sock_close(sk, ECONNREFUSED);
3863 } else {
3864 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3865 l2cap_sock_clear_timer(sk);
3866 }
3867}
3868
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003869static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003871 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003872 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873
Marcel Holtmann01394182006-07-03 10:02:46 +02003874 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003876
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877 BT_DBG("conn %p", conn);
3878
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003879 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003881 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003882 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003883
Linus Torvalds1da177e2005-04-16 15:20:36 -07003884 bh_lock_sock(sk);
3885
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003886 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3887 bh_unlock_sock(sk);
3888 continue;
3889 }
3890
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003891 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003892 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003893 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003894 bh_unlock_sock(sk);
3895 continue;
3896 }
3897
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003898 if (sk->sk_state == BT_CONNECT) {
3899 if (!status) {
3900 struct l2cap_conn_req req;
3901 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3902 req.psm = l2cap_pi(sk)->psm;
3903
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003904 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003905 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003906
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003907 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003908 L2CAP_CONN_REQ, sizeof(req), &req);
3909 } else {
3910 l2cap_sock_clear_timer(sk);
3911 l2cap_sock_set_timer(sk, HZ / 10);
3912 }
3913 } else if (sk->sk_state == BT_CONNECT2) {
3914 struct l2cap_conn_rsp rsp;
3915 __u16 result;
3916
3917 if (!status) {
3918 sk->sk_state = BT_CONFIG;
3919 result = L2CAP_CR_SUCCESS;
3920 } else {
3921 sk->sk_state = BT_DISCONN;
3922 l2cap_sock_set_timer(sk, HZ / 10);
3923 result = L2CAP_CR_SEC_BLOCK;
3924 }
3925
3926 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3927 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3928 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003929 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003930 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
3931 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932 }
3933
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934 bh_unlock_sock(sk);
3935 }
3936
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003937 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003938
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939 return 0;
3940}
3941
3942static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3943{
3944 struct l2cap_conn *conn = hcon->l2cap_data;
3945
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003946 if (!conn)
3947 conn = l2cap_conn_add(hcon, 0);
3948
3949 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950 goto drop;
3951
3952 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3953
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003954 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003955 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003956 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003957 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 int len;
3959
3960 if (conn->rx_len) {
3961 BT_ERR("Unexpected start frame (len %d)", skb->len);
3962 kfree_skb(conn->rx_skb);
3963 conn->rx_skb = NULL;
3964 conn->rx_len = 0;
3965 l2cap_conn_unreliable(conn, ECOMM);
3966 }
3967
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003968 /* Start fragment always begin with Basic L2CAP header */
3969 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970 BT_ERR("Frame is too short (len %d)", skb->len);
3971 l2cap_conn_unreliable(conn, ECOMM);
3972 goto drop;
3973 }
3974
3975 hdr = (struct l2cap_hdr *) skb->data;
3976 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003977 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003978
3979 if (len == skb->len) {
3980 /* Complete frame received */
3981 l2cap_recv_frame(conn, skb);
3982 return 0;
3983 }
3984
3985 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3986
3987 if (skb->len > len) {
3988 BT_ERR("Frame is too long (len %d, expected len %d)",
3989 skb->len, len);
3990 l2cap_conn_unreliable(conn, ECOMM);
3991 goto drop;
3992 }
3993
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003994 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003995
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003996 if (chan && chan->sk) {
3997 struct sock *sk = chan->sk;
3998
3999 if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
4000 BT_ERR("Frame exceeding recv MTU (len %d, "
4001 "MTU %d)", len,
4002 l2cap_pi(sk)->imtu);
4003 bh_unlock_sock(sk);
4004 l2cap_conn_unreliable(conn, ECOMM);
4005 goto drop;
4006 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004007 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004008 }
4009
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004011 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4012 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013 goto drop;
4014
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004015 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004016 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017 conn->rx_len = len - skb->len;
4018 } else {
4019 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4020
4021 if (!conn->rx_len) {
4022 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4023 l2cap_conn_unreliable(conn, ECOMM);
4024 goto drop;
4025 }
4026
4027 if (skb->len > conn->rx_len) {
4028 BT_ERR("Fragment is too long (len %d, expected %d)",
4029 skb->len, conn->rx_len);
4030 kfree_skb(conn->rx_skb);
4031 conn->rx_skb = NULL;
4032 conn->rx_len = 0;
4033 l2cap_conn_unreliable(conn, ECOMM);
4034 goto drop;
4035 }
4036
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004037 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004038 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039 conn->rx_len -= skb->len;
4040
4041 if (!conn->rx_len) {
4042 /* Complete frame received */
4043 l2cap_recv_frame(conn, conn->rx_skb);
4044 conn->rx_skb = NULL;
4045 }
4046 }
4047
4048drop:
4049 kfree_skb(skb);
4050 return 0;
4051}
4052
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004053static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054{
4055 struct sock *sk;
4056 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057
4058 read_lock_bh(&l2cap_sk_list.lock);
4059
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004060 sk_for_each(sk, node, &l2cap_sk_list.head) {
4061 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004062
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004063 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 +01004064 batostr(&bt_sk(sk)->src),
4065 batostr(&bt_sk(sk)->dst),
4066 sk->sk_state, __le16_to_cpu(pi->psm),
4067 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004068 pi->imtu, pi->omtu, pi->sec_level,
4069 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004070 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004073
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004074 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075}
4076
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004077static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4078{
4079 return single_open(file, l2cap_debugfs_show, inode->i_private);
4080}
4081
4082static const struct file_operations l2cap_debugfs_fops = {
4083 .open = l2cap_debugfs_open,
4084 .read = seq_read,
4085 .llseek = seq_lseek,
4086 .release = single_release,
4087};
4088
4089static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091static struct hci_proto l2cap_hci_proto = {
4092 .name = "L2CAP",
4093 .id = HCI_PROTO_L2CAP,
4094 .connect_ind = l2cap_connect_ind,
4095 .connect_cfm = l2cap_connect_cfm,
4096 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004097 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004098 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099 .recv_acldata = l2cap_recv_acldata
4100};
4101
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004102int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103{
4104 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004105
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004106 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107 if (err < 0)
4108 return err;
4109
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004110 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004111 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004112 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113 goto error;
4114 }
4115
4116 err = hci_register_proto(&l2cap_hci_proto);
4117 if (err < 0) {
4118 BT_ERR("L2CAP protocol registration failed");
4119 bt_sock_unregister(BTPROTO_L2CAP);
4120 goto error;
4121 }
4122
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004123 if (bt_debugfs) {
4124 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4125 bt_debugfs, NULL, &l2cap_debugfs_fops);
4126 if (!l2cap_debugfs)
4127 BT_ERR("Failed to create L2CAP debug file");
4128 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130 return 0;
4131
4132error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004133 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004134 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135 return err;
4136}
4137
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004138void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004139{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004140 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004141
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004142 flush_workqueue(_busy_wq);
4143 destroy_workqueue(_busy_wq);
4144
Linus Torvalds1da177e2005-04-16 15:20:36 -07004145 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4146 BT_ERR("L2CAP protocol unregistration failed");
4147
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004148 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149}
4150
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004151module_param(disable_ertm, bool, 0644);
4152MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");