blob: b0aaaa9cf00e22f8c516cc691f1262155327cc07 [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);
73
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030074static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
75
Marcel Holtmann01394182006-07-03 10:02:46 +020076/* ---- L2CAP channels ---- */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030077static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020078{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030079 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030080
81 list_for_each_entry(c, &conn->chan_l, list) {
82 struct sock *s = c->sk;
83 if (l2cap_pi(s)->dcid == cid)
84 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020085 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030086 return NULL;
87
Marcel Holtmann01394182006-07-03 10:02:46 +020088}
89
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030090static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020091{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030092 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030093
94 list_for_each_entry(c, &conn->chan_l, list) {
95 struct sock *s = c->sk;
96 if (l2cap_pi(s)->scid == cid)
97 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020098 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030099 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200100}
101
102/* Find channel with given SCID.
103 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300104static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200105{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300106 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300107
108 read_lock(&conn->chan_lock);
109 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300110 if (c)
111 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300112 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300113 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200114}
115
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300116static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200117{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300118 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300119
120 list_for_each_entry(c, &conn->chan_l, list) {
121 struct sock *s = c->sk;
122 if (l2cap_pi(s)->ident == ident)
123 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. Padovan9a9c6a32010-05-01 16:15:43 -0300343static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300344{
345 struct sk_buff *skb;
346 struct l2cap_hdr *lh;
347 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300348 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300349 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200350 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300351
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300352 if (sk->sk_state != BT_CONNECTED)
353 return;
354
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300355 if (pi->fcs == L2CAP_FCS_CRC16)
356 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300357
358 BT_DBG("pi %p, control 0x%2.2x", pi, control);
359
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300360 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300361 control |= L2CAP_CTRL_FRAME_TYPE;
362
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300363 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
364 control |= L2CAP_CTRL_FINAL;
365 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
366 }
367
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300368 if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
369 control |= L2CAP_CTRL_POLL;
370 pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
371 }
372
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300373 skb = bt_skb_alloc(count, GFP_ATOMIC);
374 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300375 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300376
377 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300378 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300379 lh->cid = cpu_to_le16(pi->dcid);
380 put_unaligned_le16(control, skb_put(skb, 2));
381
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300382 if (pi->fcs == L2CAP_FCS_CRC16) {
383 u16 fcs = crc16(0, (u8 *)lh, count - 2);
384 put_unaligned_le16(fcs, skb_put(skb, 2));
385 }
386
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200387 if (lmp_no_flush_capable(conn->hcon->hdev))
388 flags = ACL_START_NO_FLUSH;
389 else
390 flags = ACL_START;
391
392 hci_send_acl(pi->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300393}
394
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300395static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300396{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300397 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300398 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300399 pi->conn_state |= L2CAP_CONN_RNR_SENT;
400 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300401 control |= L2CAP_SUPER_RCV_READY;
402
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300403 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
404
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300405 l2cap_send_sframe(pi, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300406}
407
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300408static inline int __l2cap_no_conn_pending(struct sock *sk)
409{
410 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
411}
412
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200413static void l2cap_do_start(struct sock *sk)
414{
415 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
416
417 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100418 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
419 return;
420
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300421 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200422 struct l2cap_conn_req req;
423 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
424 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200425
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200426 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300427 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200428
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200429 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200430 L2CAP_CONN_REQ, sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200431 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200432 } else {
433 struct l2cap_info_req req;
434 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
435
436 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
437 conn->info_ident = l2cap_get_ident(conn);
438
439 mod_timer(&conn->info_timer, jiffies +
440 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
441
442 l2cap_send_cmd(conn, conn->info_ident,
443 L2CAP_INFO_REQ, sizeof(req), &req);
444 }
445}
446
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300447static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
448{
449 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300450 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300451 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
452
453 switch (mode) {
454 case L2CAP_MODE_ERTM:
455 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
456 case L2CAP_MODE_STREAMING:
457 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
458 default:
459 return 0x00;
460 }
461}
462
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200463void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300464{
465 struct l2cap_disconn_req req;
466
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300467 if (!conn)
468 return;
469
470 skb_queue_purge(TX_QUEUE(sk));
471
472 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
473 del_timer(&l2cap_pi(sk)->retrans_timer);
474 del_timer(&l2cap_pi(sk)->monitor_timer);
475 del_timer(&l2cap_pi(sk)->ack_timer);
476 }
477
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300478 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
479 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
480 l2cap_send_cmd(conn, l2cap_get_ident(conn),
481 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300482
483 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300484 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300485}
486
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200488static void l2cap_conn_start(struct l2cap_conn *conn)
489{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300490 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200491
492 BT_DBG("conn %p", conn);
493
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300494 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200495
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300496 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300497 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300498
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200499 bh_lock_sock(sk);
500
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300501 if (sk->sk_type != SOCK_SEQPACKET &&
502 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200503 bh_unlock_sock(sk);
504 continue;
505 }
506
507 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300508 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300509
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300510 if (!l2cap_check_security(sk) ||
511 !__l2cap_no_conn_pending(sk)) {
512 bh_unlock_sock(sk);
513 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200514 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300515
516 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
517 conn->feat_mask)
518 && l2cap_pi(sk)->conf_state &
519 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300520 /* __l2cap_sock_close() calls list_del(chan)
521 * so release the lock */
522 read_unlock_bh(&conn->chan_lock);
523 __l2cap_sock_close(sk, ECONNRESET);
524 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300525 bh_unlock_sock(sk);
526 continue;
527 }
528
529 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
530 req.psm = l2cap_pi(sk)->psm;
531
532 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
533 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
534
535 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
536 L2CAP_CONN_REQ, sizeof(req), &req);
537
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200538 } else if (sk->sk_state == BT_CONNECT2) {
539 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300540 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200541 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
542 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
543
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100544 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100545 if (bt_sk(sk)->defer_setup) {
546 struct sock *parent = bt_sk(sk)->parent;
547 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
548 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
549 parent->sk_data_ready(parent, 0);
550
551 } else {
552 sk->sk_state = BT_CONFIG;
553 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
554 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
555 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200556 } else {
557 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
558 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
559 }
560
561 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
562 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300563
564 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
565 rsp.result != L2CAP_CR_SUCCESS) {
566 bh_unlock_sock(sk);
567 continue;
568 }
569
570 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
571 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
572 l2cap_build_conf_req(sk, buf), buf);
573 l2cap_pi(sk)->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200574 }
575
576 bh_unlock_sock(sk);
577 }
578
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300579 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200580}
581
Ville Tervob62f3282011-02-10 22:38:50 -0300582/* Find socket with cid and source bdaddr.
583 * Returns closest match, locked.
584 */
585static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
586{
587 struct sock *s, *sk = NULL, *sk1 = NULL;
588 struct hlist_node *node;
589
590 read_lock(&l2cap_sk_list.lock);
591
592 sk_for_each(sk, node, &l2cap_sk_list.head) {
593 if (state && sk->sk_state != state)
594 continue;
595
596 if (l2cap_pi(sk)->scid == cid) {
597 /* Exact match. */
598 if (!bacmp(&bt_sk(sk)->src, src))
599 break;
600
601 /* Closest match */
602 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
603 sk1 = sk;
604 }
605 }
606 s = node ? sk : sk1;
607 if (s)
608 bh_lock_sock(s);
609 read_unlock(&l2cap_sk_list.lock);
610
611 return s;
612}
613
614static void l2cap_le_conn_ready(struct l2cap_conn *conn)
615{
Ville Tervob62f3282011-02-10 22:38:50 -0300616 struct sock *parent, *uninitialized_var(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300617 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300618
619 BT_DBG("");
620
621 /* Check if we have socket listening on cid */
622 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
623 conn->src);
624 if (!parent)
625 return;
626
627 /* Check for backlog size */
628 if (sk_acceptq_is_full(parent)) {
629 BT_DBG("backlog full %d", parent->sk_ack_backlog);
630 goto clean;
631 }
632
633 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
634 if (!sk)
635 goto clean;
636
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300637 chan = l2cap_chan_alloc(sk);
638 if (!chan) {
639 l2cap_sock_kill(sk);
640 goto clean;
641 }
642
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300643 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300644
645 hci_conn_hold(conn->hcon);
646
647 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300648
Ville Tervob62f3282011-02-10 22:38:50 -0300649 bacpy(&bt_sk(sk)->src, conn->src);
650 bacpy(&bt_sk(sk)->dst, conn->dst);
651
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300652 bt_accept_enqueue(parent, sk);
653
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300654 __l2cap_chan_add(conn, chan);
655
656 l2cap_pi(sk)->chan = chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300657
658 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
659
660 sk->sk_state = BT_CONNECTED;
661 parent->sk_data_ready(parent, 0);
662
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300663 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300664
665clean:
666 bh_unlock_sock(parent);
667}
668
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200669static void l2cap_conn_ready(struct l2cap_conn *conn)
670{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300671 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200672
673 BT_DBG("conn %p", conn);
674
Ville Tervob62f3282011-02-10 22:38:50 -0300675 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
676 l2cap_le_conn_ready(conn);
677
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300678 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200679
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300680 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300681 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300682
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200683 bh_lock_sock(sk);
684
Ville Tervoacd7d372011-02-10 22:38:49 -0300685 if (conn->hcon->type == LE_LINK) {
686 l2cap_sock_clear_timer(sk);
687 sk->sk_state = BT_CONNECTED;
688 sk->sk_state_change(sk);
689 }
690
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300691 if (sk->sk_type != SOCK_SEQPACKET &&
692 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200693 l2cap_sock_clear_timer(sk);
694 sk->sk_state = BT_CONNECTED;
695 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200696 } else if (sk->sk_state == BT_CONNECT)
697 l2cap_do_start(sk);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200698
699 bh_unlock_sock(sk);
700 }
701
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300702 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200703}
704
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200705/* Notify sockets that we cannot guaranty reliability anymore */
706static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
707{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300708 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200709
710 BT_DBG("conn %p", conn);
711
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300712 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200713
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300714 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300715 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300716
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100717 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200718 sk->sk_err = err;
719 }
720
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300721 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200722}
723
724static void l2cap_info_timeout(unsigned long arg)
725{
726 struct l2cap_conn *conn = (void *) arg;
727
Marcel Holtmann984947d2009-02-06 23:35:19 +0100728 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100729 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100730
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200731 l2cap_conn_start(conn);
732}
733
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
735{
Marcel Holtmann01394182006-07-03 10:02:46 +0200736 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
Marcel Holtmann01394182006-07-03 10:02:46 +0200738 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 return conn;
740
Marcel Holtmann01394182006-07-03 10:02:46 +0200741 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
742 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744
745 hcon->l2cap_data = conn;
746 conn->hcon = hcon;
747
Marcel Holtmann01394182006-07-03 10:02:46 +0200748 BT_DBG("hcon %p conn %p", hcon, conn);
749
Ville Tervoacd7d372011-02-10 22:38:49 -0300750 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
751 conn->mtu = hcon->hdev->le_mtu;
752 else
753 conn->mtu = hcon->hdev->acl_mtu;
754
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 conn->src = &hcon->hdev->bdaddr;
756 conn->dst = &hcon->dst;
757
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200758 conn->feat_mask = 0;
759
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300761 rwlock_init(&conn->chan_lock);
762
763 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764
Ville Tervob62f3282011-02-10 22:38:50 -0300765 if (hcon->type != LE_LINK)
766 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000767 (unsigned long) conn);
768
Marcel Holtmann2950f212009-02-12 14:02:50 +0100769 conn->disc_reason = 0x13;
770
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 return conn;
772}
773
Marcel Holtmann01394182006-07-03 10:02:46 +0200774static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775{
Marcel Holtmann01394182006-07-03 10:02:46 +0200776 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300777 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 struct sock *sk;
779
Marcel Holtmann01394182006-07-03 10:02:46 +0200780 if (!conn)
781 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782
783 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
784
Wei Yongjun7585b972009-02-25 18:29:52 +0800785 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786
787 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300788 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300789 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300791 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 bh_unlock_sock(sk);
793 l2cap_sock_kill(sk);
794 }
795
Dave Young8e8440f2008-03-03 12:18:55 -0800796 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
797 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800798
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 hcon->l2cap_data = NULL;
800 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801}
802
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300803static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300805 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300806 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300807 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808}
809
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811
812/* Find socket with psm and source bdaddr.
813 * Returns closest match.
814 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000815static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816{
817 struct sock *sk = NULL, *sk1 = NULL;
818 struct hlist_node *node;
819
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000820 read_lock(&l2cap_sk_list.lock);
821
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 sk_for_each(sk, node, &l2cap_sk_list.head) {
823 if (state && sk->sk_state != state)
824 continue;
825
826 if (l2cap_pi(sk)->psm == psm) {
827 /* Exact match. */
828 if (!bacmp(&bt_sk(sk)->src, src))
829 break;
830
831 /* Closest match */
832 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
833 sk1 = sk;
834 }
835 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000838
839 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840}
841
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200842int l2cap_do_connect(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843{
844 bdaddr_t *src = &bt_sk(sk)->src;
845 bdaddr_t *dst = &bt_sk(sk)->dst;
846 struct l2cap_conn *conn;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300847 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 struct hci_conn *hcon;
849 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200850 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200851 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100853 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
854 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300856 hdev = hci_get_route(dst, src);
857 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 return -EHOSTUNREACH;
859
860 hci_dev_lock_bh(hdev);
861
Johan Hedberg8556edd32011-01-19 12:06:50 +0530862 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200863
Ville Tervoacd7d372011-02-10 22:38:49 -0300864 if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
865 hcon = hci_connect(hdev, LE_LINK, dst,
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100866 l2cap_pi(sk)->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300867 else
868 hcon = hci_connect(hdev, ACL_LINK, dst,
869 l2cap_pi(sk)->sec_level, auth_type);
870
Ville Tervo30e76272011-02-22 16:10:53 -0300871 if (IS_ERR(hcon)) {
872 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300874 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875
876 conn = l2cap_conn_add(hcon, 0);
877 if (!conn) {
878 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300879 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 goto done;
881 }
882
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300883 chan = l2cap_chan_alloc(sk);
884 if (!chan) {
885 hci_conn_put(hcon);
886 err = -ENOMEM;
887 goto done;
888 }
889
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 /* Update source addr of the socket */
891 bacpy(src, conn->src);
892
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300893 l2cap_chan_add(conn, chan);
894
895 l2cap_pi(sk)->chan = chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896
897 sk->sk_state = BT_CONNECT;
898 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
899
900 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300901 if (sk->sk_type != SOCK_SEQPACKET &&
902 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530904 if (l2cap_check_security(sk))
905 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200906 } else
907 l2cap_do_start(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 }
909
Ville Tervo30e76272011-02-22 16:10:53 -0300910 err = 0;
911
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912done:
913 hci_dev_unlock_bh(hdev);
914 hci_dev_put(hdev);
915 return err;
916}
917
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200918int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300919{
920 DECLARE_WAITQUEUE(wait, current);
921 int err = 0;
922 int timeo = HZ/5;
923
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200924 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300925 while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
926 set_current_state(TASK_INTERRUPTIBLE);
927
928 if (!timeo)
929 timeo = HZ/5;
930
931 if (signal_pending(current)) {
932 err = sock_intr_errno(timeo);
933 break;
934 }
935
936 release_sock(sk);
937 timeo = schedule_timeout(timeo);
938 lock_sock(sk);
939
940 err = sock_error(sk);
941 if (err)
942 break;
943 }
944 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200945 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300946 return err;
947}
948
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300949static void l2cap_monitor_timeout(unsigned long arg)
950{
951 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300952
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300953 BT_DBG("sk %p", sk);
954
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300955 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300956 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300957 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200958 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300959 return;
960 }
961
962 l2cap_pi(sk)->retry_count++;
963 __mod_monitor_timer();
964
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -0300965 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300966 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300967}
968
969static void l2cap_retrans_timeout(unsigned long arg)
970{
971 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300972
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300973 BT_DBG("sk %p", sk);
974
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300975 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300976 l2cap_pi(sk)->retry_count = 1;
977 __mod_monitor_timer();
978
979 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
980
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -0300981 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300982 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300983}
984
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300985static void l2cap_drop_acked_frames(struct sock *sk)
986{
987 struct sk_buff *skb;
988
Gustavo F. Padovan812e7372010-05-01 16:15:42 -0300989 while ((skb = skb_peek(TX_QUEUE(sk))) &&
990 l2cap_pi(sk)->unacked_frames) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300991 if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
992 break;
993
994 skb = skb_dequeue(TX_QUEUE(sk));
995 kfree_skb(skb);
996
997 l2cap_pi(sk)->unacked_frames--;
998 }
999
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001000 if (!l2cap_pi(sk)->unacked_frames)
1001 del_timer(&l2cap_pi(sk)->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001002}
1003
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001004void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001005{
1006 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001007 struct hci_conn *hcon = pi->conn->hcon;
1008 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001009
1010 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1011
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001012 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
1013 flags = ACL_START_NO_FLUSH;
1014 else
1015 flags = ACL_START;
1016
1017 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001018}
1019
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001020void l2cap_streaming_send(struct sock *sk)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001021{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001022 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001023 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001024 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001025
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001026 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
1027 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001028 control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001029 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001030
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001031 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001032 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1033 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001034 }
1035
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001036 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001037
1038 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001039 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001040}
1041
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001042static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001043{
1044 struct l2cap_pinfo *pi = l2cap_pi(sk);
1045 struct sk_buff *skb, *tx_skb;
1046 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001047
1048 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001049 if (!skb)
1050 return;
1051
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001052 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001053 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001054 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001055
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001056 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1057 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001058
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001059 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001060
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001061 if (pi->remote_max_tx &&
1062 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001063 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001064 return;
1065 }
1066
1067 tx_skb = skb_clone(skb, GFP_ATOMIC);
1068 bt_cb(skb)->retries++;
1069 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001070
1071 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1072 control |= L2CAP_CTRL_FINAL;
1073 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1074 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001075
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001076 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1077 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001078
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001079 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1080
1081 if (pi->fcs == L2CAP_FCS_CRC16) {
1082 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1083 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1084 }
1085
1086 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001087}
1088
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001089int l2cap_ertm_send(struct sock *sk)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001090{
1091 struct sk_buff *skb, *tx_skb;
1092 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001093 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001094 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001095
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001096 if (sk->sk_state != BT_CONNECTED)
1097 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001098
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001099 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001100
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001101 if (pi->remote_max_tx &&
1102 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001103 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001104 break;
1105 }
1106
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001107 tx_skb = skb_clone(skb, GFP_ATOMIC);
1108
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001109 bt_cb(skb)->retries++;
1110
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001111 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001112 control &= L2CAP_CTRL_SAR;
1113
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001114 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1115 control |= L2CAP_CTRL_FINAL;
1116 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1117 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001118 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001119 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1120 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1121
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001122
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001123 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001124 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1125 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1126 }
1127
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001128 l2cap_do_send(sk, tx_skb);
1129
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001130 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001131
1132 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1133 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1134
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301135 if (bt_cb(skb)->retries == 1)
1136 pi->unacked_frames++;
1137
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001138 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001139
1140 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1141 sk->sk_send_head = NULL;
1142 else
1143 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001144
1145 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001146 }
1147
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001148 return nsent;
1149}
1150
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001151static int l2cap_retransmit_frames(struct sock *sk)
1152{
1153 struct l2cap_pinfo *pi = l2cap_pi(sk);
1154 int ret;
1155
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001156 if (!skb_queue_empty(TX_QUEUE(sk)))
1157 sk->sk_send_head = TX_QUEUE(sk)->next;
1158
1159 pi->next_tx_seq = pi->expected_ack_seq;
1160 ret = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001161 return ret;
1162}
1163
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001164static void l2cap_send_ack(struct l2cap_pinfo *pi)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001165{
1166 struct sock *sk = (struct sock *)pi;
1167 u16 control = 0;
1168
1169 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1170
1171 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1172 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001173 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001174 l2cap_send_sframe(pi, control);
1175 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001176 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001177
Gustavo F. Padovane0f66212010-06-21 18:50:49 -03001178 if (l2cap_ertm_send(sk) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001179 return;
1180
1181 control |= L2CAP_SUPER_RCV_READY;
1182 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001183}
1184
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001185static void l2cap_send_srejtail(struct sock *sk)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001186{
1187 struct srej_list *tail;
1188 u16 control;
1189
1190 control = L2CAP_SUPER_SELECT_REJECT;
1191 control |= L2CAP_CTRL_FINAL;
1192
1193 tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
1194 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1195
1196 l2cap_send_sframe(l2cap_pi(sk), control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001197}
1198
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001199static 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 -07001200{
1201 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001202 struct sk_buff **frag;
1203 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001205 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001206 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207
1208 sent += count;
1209 len -= count;
1210
1211 /* Continuation fragments (no L2CAP header) */
1212 frag = &skb_shinfo(skb)->frag_list;
1213 while (len) {
1214 count = min_t(unsigned int, conn->mtu, len);
1215
1216 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1217 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001218 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001219 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1220 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221
1222 sent += count;
1223 len -= count;
1224
1225 frag = &(*frag)->next;
1226 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227
1228 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001229}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001231struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001232{
1233 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1234 struct sk_buff *skb;
1235 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1236 struct l2cap_hdr *lh;
1237
1238 BT_DBG("sk %p len %d", sk, (int)len);
1239
1240 count = min_t(unsigned int, (conn->mtu - hlen), len);
1241 skb = bt_skb_send_alloc(sk, count + hlen,
1242 msg->msg_flags & MSG_DONTWAIT, &err);
1243 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001244 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001245
1246 /* Create L2CAP header */
1247 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1248 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1249 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1250 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1251
1252 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1253 if (unlikely(err < 0)) {
1254 kfree_skb(skb);
1255 return ERR_PTR(err);
1256 }
1257 return skb;
1258}
1259
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001260struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001261{
1262 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1263 struct sk_buff *skb;
1264 int err, count, hlen = L2CAP_HDR_SIZE;
1265 struct l2cap_hdr *lh;
1266
1267 BT_DBG("sk %p len %d", sk, (int)len);
1268
1269 count = min_t(unsigned int, (conn->mtu - hlen), len);
1270 skb = bt_skb_send_alloc(sk, count + hlen,
1271 msg->msg_flags & MSG_DONTWAIT, &err);
1272 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001273 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001274
1275 /* Create L2CAP header */
1276 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1277 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1278 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1279
1280 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1281 if (unlikely(err < 0)) {
1282 kfree_skb(skb);
1283 return ERR_PTR(err);
1284 }
1285 return skb;
1286}
1287
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001288struct 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 -03001289{
1290 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1291 struct sk_buff *skb;
1292 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1293 struct l2cap_hdr *lh;
1294
1295 BT_DBG("sk %p len %d", sk, (int)len);
1296
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001297 if (!conn)
1298 return ERR_PTR(-ENOTCONN);
1299
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001300 if (sdulen)
1301 hlen += 2;
1302
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001303 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1304 hlen += 2;
1305
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001306 count = min_t(unsigned int, (conn->mtu - hlen), len);
1307 skb = bt_skb_send_alloc(sk, count + hlen,
1308 msg->msg_flags & MSG_DONTWAIT, &err);
1309 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001310 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001311
1312 /* Create L2CAP header */
1313 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1314 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1315 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1316 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001317 if (sdulen)
1318 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001319
1320 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1321 if (unlikely(err < 0)) {
1322 kfree_skb(skb);
1323 return ERR_PTR(err);
1324 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001325
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001326 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1327 put_unaligned_le16(0, skb_put(skb, 2));
1328
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001329 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001330 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331}
1332
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001333int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001334{
1335 struct l2cap_pinfo *pi = l2cap_pi(sk);
1336 struct sk_buff *skb;
1337 struct sk_buff_head sar_queue;
1338 u16 control;
1339 size_t size = 0;
1340
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001341 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001342 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001343 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001344 if (IS_ERR(skb))
1345 return PTR_ERR(skb);
1346
1347 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001348 len -= pi->remote_mps;
1349 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001350
1351 while (len > 0) {
1352 size_t buflen;
1353
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001354 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001355 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001356 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001357 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001358 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001359 buflen = len;
1360 }
1361
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001362 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001363 if (IS_ERR(skb)) {
1364 skb_queue_purge(&sar_queue);
1365 return PTR_ERR(skb);
1366 }
1367
1368 __skb_queue_tail(&sar_queue, skb);
1369 len -= buflen;
1370 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001371 }
1372 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1373 if (sk->sk_send_head == NULL)
1374 sk->sk_send_head = sar_queue.next;
1375
1376 return size;
1377}
1378
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379static void l2cap_chan_ready(struct sock *sk)
1380{
1381 struct sock *parent = bt_sk(sk)->parent;
1382
1383 BT_DBG("sk %p, parent %p", sk, parent);
1384
1385 l2cap_pi(sk)->conf_state = 0;
1386 l2cap_sock_clear_timer(sk);
1387
1388 if (!parent) {
1389 /* Outgoing channel.
1390 * Wake up socket sleeping on connect.
1391 */
1392 sk->sk_state = BT_CONNECTED;
1393 sk->sk_state_change(sk);
1394 } else {
1395 /* Incoming channel.
1396 * Wake up socket sleeping on accept.
1397 */
1398 parent->sk_data_ready(parent, 0);
1399 }
1400}
1401
1402/* Copy frame to all raw sockets on that connection */
1403static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1404{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001406 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407
1408 BT_DBG("conn %p", conn);
1409
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001410 read_lock(&conn->chan_lock);
1411 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001412 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 if (sk->sk_type != SOCK_RAW)
1414 continue;
1415
1416 /* Don't send frame to the socket it came from */
1417 if (skb->sk == sk)
1418 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001419 nskb = skb_clone(skb, GFP_ATOMIC);
1420 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 continue;
1422
1423 if (sock_queue_rcv_skb(sk, nskb))
1424 kfree_skb(nskb);
1425 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001426 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427}
1428
1429/* ---- L2CAP signalling commands ---- */
1430static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1431 u8 code, u8 ident, u16 dlen, void *data)
1432{
1433 struct sk_buff *skb, **frag;
1434 struct l2cap_cmd_hdr *cmd;
1435 struct l2cap_hdr *lh;
1436 int len, count;
1437
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001438 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1439 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440
1441 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1442 count = min_t(unsigned int, conn->mtu, len);
1443
1444 skb = bt_skb_alloc(count, GFP_ATOMIC);
1445 if (!skb)
1446 return NULL;
1447
1448 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001449 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001450
1451 if (conn->hcon->type == LE_LINK)
1452 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1453 else
1454 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455
1456 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1457 cmd->code = code;
1458 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001459 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460
1461 if (dlen) {
1462 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1463 memcpy(skb_put(skb, count), data, count);
1464 data += count;
1465 }
1466
1467 len -= skb->len;
1468
1469 /* Continuation fragments (no L2CAP header) */
1470 frag = &skb_shinfo(skb)->frag_list;
1471 while (len) {
1472 count = min_t(unsigned int, conn->mtu, len);
1473
1474 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1475 if (!*frag)
1476 goto fail;
1477
1478 memcpy(skb_put(*frag, count), data, count);
1479
1480 len -= count;
1481 data += count;
1482
1483 frag = &(*frag)->next;
1484 }
1485
1486 return skb;
1487
1488fail:
1489 kfree_skb(skb);
1490 return NULL;
1491}
1492
1493static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1494{
1495 struct l2cap_conf_opt *opt = *ptr;
1496 int len;
1497
1498 len = L2CAP_CONF_OPT_SIZE + opt->len;
1499 *ptr += len;
1500
1501 *type = opt->type;
1502 *olen = opt->len;
1503
1504 switch (opt->len) {
1505 case 1:
1506 *val = *((u8 *) opt->val);
1507 break;
1508
1509 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001510 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 break;
1512
1513 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001514 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 break;
1516
1517 default:
1518 *val = (unsigned long) opt->val;
1519 break;
1520 }
1521
1522 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1523 return len;
1524}
1525
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1527{
1528 struct l2cap_conf_opt *opt = *ptr;
1529
1530 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1531
1532 opt->type = type;
1533 opt->len = len;
1534
1535 switch (len) {
1536 case 1:
1537 *((u8 *) opt->val) = val;
1538 break;
1539
1540 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001541 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 break;
1543
1544 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001545 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 break;
1547
1548 default:
1549 memcpy(opt->val, (void *) val, len);
1550 break;
1551 }
1552
1553 *ptr += L2CAP_CONF_OPT_SIZE + len;
1554}
1555
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001556static void l2cap_ack_timeout(unsigned long arg)
1557{
1558 struct sock *sk = (void *) arg;
1559
1560 bh_lock_sock(sk);
1561 l2cap_send_ack(l2cap_pi(sk));
1562 bh_unlock_sock(sk);
1563}
1564
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001565static inline void l2cap_ertm_init(struct sock *sk)
1566{
1567 l2cap_pi(sk)->expected_ack_seq = 0;
1568 l2cap_pi(sk)->unacked_frames = 0;
1569 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03001570 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001571 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001572
1573 setup_timer(&l2cap_pi(sk)->retrans_timer,
1574 l2cap_retrans_timeout, (unsigned long) sk);
1575 setup_timer(&l2cap_pi(sk)->monitor_timer,
1576 l2cap_monitor_timeout, (unsigned long) sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001577 setup_timer(&l2cap_pi(sk)->ack_timer,
1578 l2cap_ack_timeout, (unsigned long) sk);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001579
1580 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001581 __skb_queue_head_init(BUSY_QUEUE(sk));
1582
1583 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001584
1585 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001586}
1587
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001588static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1589{
1590 switch (mode) {
1591 case L2CAP_MODE_STREAMING:
1592 case L2CAP_MODE_ERTM:
1593 if (l2cap_mode_supported(mode, remote_feat_mask))
1594 return mode;
1595 /* fall through */
1596 default:
1597 return L2CAP_MODE_BASIC;
1598 }
1599}
1600
Gustavo F. Padovan68983252011-02-04 03:02:31 -02001601int l2cap_build_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602{
1603 struct l2cap_pinfo *pi = l2cap_pi(sk);
1604 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001605 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 void *ptr = req->data;
1607
1608 BT_DBG("sk %p", sk);
1609
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001610 if (pi->num_conf_req || pi->num_conf_rsp)
1611 goto done;
1612
1613 switch (pi->mode) {
1614 case L2CAP_MODE_STREAMING:
1615 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001616 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001617 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001618
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001619 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001620 default:
1621 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1622 break;
1623 }
1624
1625done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001626 if (pi->imtu != L2CAP_DEFAULT_MTU)
1627 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1628
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001629 switch (pi->mode) {
1630 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001631 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1632 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1633 break;
1634
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001635 rfc.mode = L2CAP_MODE_BASIC;
1636 rfc.txwin_size = 0;
1637 rfc.max_transmit = 0;
1638 rfc.retrans_timeout = 0;
1639 rfc.monitor_timeout = 0;
1640 rfc.max_pdu_size = 0;
1641
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001642 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1643 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001644 break;
1645
1646 case L2CAP_MODE_ERTM:
1647 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001648 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001649 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001650 rfc.retrans_timeout = 0;
1651 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001652 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001653 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001654 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001655
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001656 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1657 (unsigned long) &rfc);
1658
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001659 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1660 break;
1661
1662 if (pi->fcs == L2CAP_FCS_NONE ||
1663 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1664 pi->fcs = L2CAP_FCS_NONE;
1665 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1666 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001667 break;
1668
1669 case L2CAP_MODE_STREAMING:
1670 rfc.mode = L2CAP_MODE_STREAMING;
1671 rfc.txwin_size = 0;
1672 rfc.max_transmit = 0;
1673 rfc.retrans_timeout = 0;
1674 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001675 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001676 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001677 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001678
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001679 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1680 (unsigned long) &rfc);
1681
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001682 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1683 break;
1684
1685 if (pi->fcs == L2CAP_FCS_NONE ||
1686 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1687 pi->fcs = L2CAP_FCS_NONE;
1688 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1689 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001690 break;
1691 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001693 req->dcid = cpu_to_le16(pi->dcid);
1694 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695
1696 return ptr - data;
1697}
1698
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001699static int l2cap_parse_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700{
1701 struct l2cap_pinfo *pi = l2cap_pi(sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001702 struct l2cap_conf_rsp *rsp = data;
1703 void *ptr = rsp->data;
1704 void *req = pi->conf_req;
1705 int len = pi->conf_len;
1706 int type, hint, olen;
1707 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001708 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001709 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001710 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001712 BT_DBG("sk %p", sk);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001713
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001714 while (len >= L2CAP_CONF_OPT_SIZE) {
1715 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001717 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001718 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001719
1720 switch (type) {
1721 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001722 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001723 break;
1724
1725 case L2CAP_CONF_FLUSH_TO:
1726 pi->flush_to = val;
1727 break;
1728
1729 case L2CAP_CONF_QOS:
1730 break;
1731
Marcel Holtmann6464f352007-10-20 13:39:51 +02001732 case L2CAP_CONF_RFC:
1733 if (olen == sizeof(rfc))
1734 memcpy(&rfc, (void *) val, olen);
1735 break;
1736
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001737 case L2CAP_CONF_FCS:
1738 if (val == L2CAP_FCS_NONE)
1739 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1740
1741 break;
1742
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001743 default:
1744 if (hint)
1745 break;
1746
1747 result = L2CAP_CONF_UNKNOWN;
1748 *((u8 *) ptr++) = type;
1749 break;
1750 }
1751 }
1752
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001753 if (pi->num_conf_rsp || pi->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001754 goto done;
1755
1756 switch (pi->mode) {
1757 case L2CAP_MODE_STREAMING:
1758 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001759 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1760 pi->mode = l2cap_select_mode(rfc.mode,
1761 pi->conn->feat_mask);
1762 break;
1763 }
1764
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001765 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001766 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001767
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001768 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001769 }
1770
1771done:
1772 if (pi->mode != rfc.mode) {
1773 result = L2CAP_CONF_UNACCEPT;
1774 rfc.mode = pi->mode;
1775
1776 if (pi->num_conf_rsp == 1)
1777 return -ECONNREFUSED;
1778
1779 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1780 sizeof(rfc), (unsigned long) &rfc);
1781 }
1782
1783
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001784 if (result == L2CAP_CONF_SUCCESS) {
1785 /* Configure output options and let the other side know
1786 * which ones we don't like. */
1787
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001788 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1789 result = L2CAP_CONF_UNACCEPT;
1790 else {
1791 pi->omtu = mtu;
1792 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1793 }
1794 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001795
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001796 switch (rfc.mode) {
1797 case L2CAP_MODE_BASIC:
1798 pi->fcs = L2CAP_FCS_NONE;
1799 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1800 break;
1801
1802 case L2CAP_MODE_ERTM:
1803 pi->remote_tx_win = rfc.txwin_size;
1804 pi->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001805
1806 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1807 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001808
1809 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001810
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001811 rfc.retrans_timeout =
1812 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1813 rfc.monitor_timeout =
1814 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001815
1816 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001817
1818 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1819 sizeof(rfc), (unsigned long) &rfc);
1820
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001821 break;
1822
1823 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001824 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1825 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001826
1827 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001828
1829 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001830
1831 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1832 sizeof(rfc), (unsigned long) &rfc);
1833
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001834 break;
1835
1836 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001837 result = L2CAP_CONF_UNACCEPT;
1838
1839 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001840 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001841 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001842
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001843 if (result == L2CAP_CONF_SUCCESS)
1844 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1845 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001846 rsp->scid = cpu_to_le16(pi->dcid);
1847 rsp->result = cpu_to_le16(result);
1848 rsp->flags = cpu_to_le16(0x0000);
1849
1850 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851}
1852
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001853static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1854{
1855 struct l2cap_pinfo *pi = l2cap_pi(sk);
1856 struct l2cap_conf_req *req = data;
1857 void *ptr = req->data;
1858 int type, olen;
1859 unsigned long val;
1860 struct l2cap_conf_rfc rfc;
1861
1862 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1863
1864 while (len >= L2CAP_CONF_OPT_SIZE) {
1865 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1866
1867 switch (type) {
1868 case L2CAP_CONF_MTU:
1869 if (val < L2CAP_DEFAULT_MIN_MTU) {
1870 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001871 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001872 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001873 pi->imtu = val;
1874 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001875 break;
1876
1877 case L2CAP_CONF_FLUSH_TO:
1878 pi->flush_to = val;
1879 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1880 2, pi->flush_to);
1881 break;
1882
1883 case L2CAP_CONF_RFC:
1884 if (olen == sizeof(rfc))
1885 memcpy(&rfc, (void *)val, olen);
1886
1887 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1888 rfc.mode != pi->mode)
1889 return -ECONNREFUSED;
1890
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001891 pi->fcs = 0;
1892
1893 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1894 sizeof(rfc), (unsigned long) &rfc);
1895 break;
1896 }
1897 }
1898
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001899 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1900 return -ECONNREFUSED;
1901
1902 pi->mode = rfc.mode;
1903
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001904 if (*result == L2CAP_CONF_SUCCESS) {
1905 switch (rfc.mode) {
1906 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001907 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1908 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001909 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001910 break;
1911 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001912 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001913 }
1914 }
1915
1916 req->dcid = cpu_to_le16(pi->dcid);
1917 req->flags = cpu_to_le16(0x0000);
1918
1919 return ptr - data;
1920}
1921
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001922static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923{
1924 struct l2cap_conf_rsp *rsp = data;
1925 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001927 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001929 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001930 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001931 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932
1933 return ptr - data;
1934}
1935
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001936static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1937{
1938 struct l2cap_pinfo *pi = l2cap_pi(sk);
1939 int type, olen;
1940 unsigned long val;
1941 struct l2cap_conf_rfc rfc;
1942
1943 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1944
1945 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1946 return;
1947
1948 while (len >= L2CAP_CONF_OPT_SIZE) {
1949 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1950
1951 switch (type) {
1952 case L2CAP_CONF_RFC:
1953 if (olen == sizeof(rfc))
1954 memcpy(&rfc, (void *)val, olen);
1955 goto done;
1956 }
1957 }
1958
1959done:
1960 switch (rfc.mode) {
1961 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001962 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1963 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001964 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1965 break;
1966 case L2CAP_MODE_STREAMING:
1967 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1968 }
1969}
1970
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001971static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1972{
1973 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
1974
1975 if (rej->reason != 0x0000)
1976 return 0;
1977
1978 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
1979 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001980 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01001981
1982 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01001983 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01001984
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001985 l2cap_conn_start(conn);
1986 }
1987
1988 return 0;
1989}
1990
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1992{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
1994 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001995 struct l2cap_chan *chan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04001996 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001997 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998
1999 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002000 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001
2002 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2003
2004 /* Check if we have socket listening on psm */
2005 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2006 if (!parent) {
2007 result = L2CAP_CR_BAD_PSM;
2008 goto sendresp;
2009 }
2010
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002011 bh_lock_sock(parent);
2012
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002013 /* Check if the ACL is secure enough (if not SDP) */
2014 if (psm != cpu_to_le16(0x0001) &&
2015 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002016 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002017 result = L2CAP_CR_SEC_BLOCK;
2018 goto response;
2019 }
2020
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021 result = L2CAP_CR_NO_MEM;
2022
2023 /* Check for backlog size */
2024 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002025 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026 goto response;
2027 }
2028
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002029 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 if (!sk)
2031 goto response;
2032
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002033 chan = l2cap_chan_alloc(sk);
2034 if (!chan) {
2035 l2cap_sock_kill(sk);
2036 goto response;
2037 }
2038
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002039 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040
2041 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002042 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2043 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044 sock_set_flag(sk, SOCK_ZAPPED);
2045 l2cap_sock_kill(sk);
2046 goto response;
2047 }
2048
2049 hci_conn_hold(conn->hcon);
2050
2051 l2cap_sock_init(sk, parent);
2052 bacpy(&bt_sk(sk)->src, conn->src);
2053 bacpy(&bt_sk(sk)->dst, conn->dst);
2054 l2cap_pi(sk)->psm = psm;
2055 l2cap_pi(sk)->dcid = scid;
2056
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002057 bt_accept_enqueue(parent, sk);
2058
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002059 __l2cap_chan_add(conn, chan);
2060
2061 l2cap_pi(sk)->chan = chan;
2062
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 dcid = l2cap_pi(sk)->scid;
2064
2065 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2066
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 l2cap_pi(sk)->ident = cmd->ident;
2068
Marcel Holtmann984947d2009-02-06 23:35:19 +01002069 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002070 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002071 if (bt_sk(sk)->defer_setup) {
2072 sk->sk_state = BT_CONNECT2;
2073 result = L2CAP_CR_PEND;
2074 status = L2CAP_CS_AUTHOR_PEND;
2075 parent->sk_data_ready(parent, 0);
2076 } else {
2077 sk->sk_state = BT_CONFIG;
2078 result = L2CAP_CR_SUCCESS;
2079 status = L2CAP_CS_NO_INFO;
2080 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002081 } else {
2082 sk->sk_state = BT_CONNECT2;
2083 result = L2CAP_CR_PEND;
2084 status = L2CAP_CS_AUTHEN_PEND;
2085 }
2086 } else {
2087 sk->sk_state = BT_CONNECT2;
2088 result = L2CAP_CR_PEND;
2089 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 }
2091
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002092 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093
2094response:
2095 bh_unlock_sock(parent);
2096
2097sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002098 rsp.scid = cpu_to_le16(scid);
2099 rsp.dcid = cpu_to_le16(dcid);
2100 rsp.result = cpu_to_le16(result);
2101 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002103
2104 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2105 struct l2cap_info_req info;
2106 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2107
2108 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2109 conn->info_ident = l2cap_get_ident(conn);
2110
2111 mod_timer(&conn->info_timer, jiffies +
2112 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2113
2114 l2cap_send_cmd(conn, conn->info_ident,
2115 L2CAP_INFO_REQ, sizeof(info), &info);
2116 }
2117
Nathan Holsteind793fe82010-10-15 11:54:02 -04002118 if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002119 result == L2CAP_CR_SUCCESS) {
2120 u8 buf[128];
2121 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2122 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2123 l2cap_build_conf_req(sk, buf), buf);
2124 l2cap_pi(sk)->num_conf_req++;
2125 }
2126
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 return 0;
2128}
2129
2130static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2131{
2132 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2133 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002134 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 struct sock *sk;
2136 u8 req[128];
2137
2138 scid = __le16_to_cpu(rsp->scid);
2139 dcid = __le16_to_cpu(rsp->dcid);
2140 result = __le16_to_cpu(rsp->result);
2141 status = __le16_to_cpu(rsp->status);
2142
2143 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2144
2145 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002146 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002147 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002148 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002150 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002151 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002152 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 }
2154
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002155 sk = chan->sk;
2156
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157 switch (result) {
2158 case L2CAP_CR_SUCCESS:
2159 sk->sk_state = BT_CONFIG;
2160 l2cap_pi(sk)->ident = 0;
2161 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002162 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2163
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002164 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2165 break;
2166
2167 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2168
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2170 l2cap_build_conf_req(sk, req), req);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002171 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 break;
2173
2174 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002175 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 break;
2177
2178 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002179 /* don't delete l2cap channel if sk is owned by user */
2180 if (sock_owned_by_user(sk)) {
2181 sk->sk_state = BT_DISCONN;
2182 l2cap_sock_clear_timer(sk);
2183 l2cap_sock_set_timer(sk, HZ / 5);
2184 break;
2185 }
2186
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002187 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 break;
2189 }
2190
2191 bh_unlock_sock(sk);
2192 return 0;
2193}
2194
Mat Martineau8c462b62010-08-24 15:35:42 -07002195static inline void set_default_fcs(struct l2cap_pinfo *pi)
2196{
2197 /* FCS is enabled only in ERTM or streaming mode, if one or both
2198 * sides request it.
2199 */
2200 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2201 pi->fcs = L2CAP_FCS_NONE;
2202 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2203 pi->fcs = L2CAP_FCS_CRC16;
2204}
2205
Al Viro88219a02007-07-29 00:17:25 -07002206static 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 -07002207{
2208 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2209 u16 dcid, flags;
2210 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002211 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002213 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214
2215 dcid = __le16_to_cpu(req->dcid);
2216 flags = __le16_to_cpu(req->flags);
2217
2218 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2219
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002220 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002221 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222 return -ENOENT;
2223
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002224 sk = chan->sk;
2225
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002226 if (sk->sk_state != BT_CONFIG) {
2227 struct l2cap_cmd_rej rej;
2228
2229 rej.reason = cpu_to_le16(0x0002);
2230 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2231 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002232 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002233 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002234
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002235 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002236 len = cmd_len - sizeof(*req);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002237 if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
2238 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2239 l2cap_build_conf_rsp(sk, rsp,
2240 L2CAP_CONF_REJECT, flags), rsp);
2241 goto unlock;
2242 }
2243
2244 /* Store config. */
2245 memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
2246 l2cap_pi(sk)->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247
2248 if (flags & 0x0001) {
2249 /* Incomplete config. Send empty response. */
2250 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002251 l2cap_build_conf_rsp(sk, rsp,
2252 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253 goto unlock;
2254 }
2255
2256 /* Complete config. */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002257 len = l2cap_parse_conf_req(sk, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002258 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002259 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002261 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002263 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002264 l2cap_pi(sk)->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002265
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002266 /* Reset config buffer. */
2267 l2cap_pi(sk)->conf_len = 0;
2268
Marcel Holtmann876d9482007-10-20 13:35:42 +02002269 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2270 goto unlock;
2271
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002273 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002274
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002276
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002277 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002278 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002279 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002280 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2281 l2cap_ertm_init(sk);
2282
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002284 goto unlock;
2285 }
2286
2287 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002288 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002289 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002291 l2cap_build_conf_req(sk, buf), buf);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002292 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293 }
2294
2295unlock:
2296 bh_unlock_sock(sk);
2297 return 0;
2298}
2299
2300static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2301{
2302 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2303 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002304 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002306 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307
2308 scid = __le16_to_cpu(rsp->scid);
2309 flags = __le16_to_cpu(rsp->flags);
2310 result = __le16_to_cpu(rsp->result);
2311
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002312 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2313 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002315 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002316 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 return 0;
2318
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002319 sk = chan->sk;
2320
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 switch (result) {
2322 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002323 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 break;
2325
2326 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002327 if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002328 char req[64];
2329
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002330 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002331 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002332 goto done;
2333 }
2334
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002335 /* throw out any old stored conf requests */
2336 result = L2CAP_CONF_SUCCESS;
2337 len = l2cap_parse_conf_rsp(sk, rsp->data,
2338 len, req, &result);
2339 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002340 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002341 goto done;
2342 }
2343
2344 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2345 L2CAP_CONF_REQ, len, req);
2346 l2cap_pi(sk)->num_conf_req++;
2347 if (result != L2CAP_CONF_SUCCESS)
2348 goto done;
2349 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 }
2351
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002352 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002353 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002355 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 goto done;
2357 }
2358
2359 if (flags & 0x01)
2360 goto done;
2361
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2363
2364 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002365 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002366
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002368 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002369 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002370 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002371 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2372 l2cap_ertm_init(sk);
2373
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374 l2cap_chan_ready(sk);
2375 }
2376
2377done:
2378 bh_unlock_sock(sk);
2379 return 0;
2380}
2381
2382static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2383{
2384 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2385 struct l2cap_disconn_rsp rsp;
2386 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002387 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 struct sock *sk;
2389
2390 scid = __le16_to_cpu(req->scid);
2391 dcid = __le16_to_cpu(req->dcid);
2392
2393 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2394
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002395 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002396 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397 return 0;
2398
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002399 sk = chan->sk;
2400
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002401 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2402 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2404
2405 sk->sk_shutdown = SHUTDOWN_MASK;
2406
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002407 /* don't delete l2cap channel if sk is owned by user */
2408 if (sock_owned_by_user(sk)) {
2409 sk->sk_state = BT_DISCONN;
2410 l2cap_sock_clear_timer(sk);
2411 l2cap_sock_set_timer(sk, HZ / 5);
2412 bh_unlock_sock(sk);
2413 return 0;
2414 }
2415
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002416 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 bh_unlock_sock(sk);
2418
2419 l2cap_sock_kill(sk);
2420 return 0;
2421}
2422
2423static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2424{
2425 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2426 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002427 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 struct sock *sk;
2429
2430 scid = __le16_to_cpu(rsp->scid);
2431 dcid = __le16_to_cpu(rsp->dcid);
2432
2433 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2434
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002435 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002436 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437 return 0;
2438
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002439 sk = chan->sk;
2440
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002441 /* don't delete l2cap channel if sk is owned by user */
2442 if (sock_owned_by_user(sk)) {
2443 sk->sk_state = BT_DISCONN;
2444 l2cap_sock_clear_timer(sk);
2445 l2cap_sock_set_timer(sk, HZ / 5);
2446 bh_unlock_sock(sk);
2447 return 0;
2448 }
2449
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002450 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 bh_unlock_sock(sk);
2452
2453 l2cap_sock_kill(sk);
2454 return 0;
2455}
2456
2457static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2458{
2459 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460 u16 type;
2461
2462 type = __le16_to_cpu(req->type);
2463
2464 BT_DBG("type 0x%4.4x", type);
2465
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002466 if (type == L2CAP_IT_FEAT_MASK) {
2467 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002468 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002469 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2470 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2471 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002472 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002473 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2474 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002475 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002476 l2cap_send_cmd(conn, cmd->ident,
2477 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002478 } else if (type == L2CAP_IT_FIXED_CHAN) {
2479 u8 buf[12];
2480 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2481 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2482 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2483 memcpy(buf + 4, l2cap_fixed_chan, 8);
2484 l2cap_send_cmd(conn, cmd->ident,
2485 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002486 } else {
2487 struct l2cap_info_rsp rsp;
2488 rsp.type = cpu_to_le16(type);
2489 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2490 l2cap_send_cmd(conn, cmd->ident,
2491 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2492 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493
2494 return 0;
2495}
2496
2497static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2498{
2499 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2500 u16 type, result;
2501
2502 type = __le16_to_cpu(rsp->type);
2503 result = __le16_to_cpu(rsp->result);
2504
2505 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2506
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002507 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2508 if (cmd->ident != conn->info_ident ||
2509 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2510 return 0;
2511
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002512 del_timer(&conn->info_timer);
2513
Ville Tervoadb08ed2010-08-04 09:43:33 +03002514 if (result != L2CAP_IR_SUCCESS) {
2515 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2516 conn->info_ident = 0;
2517
2518 l2cap_conn_start(conn);
2519
2520 return 0;
2521 }
2522
Marcel Holtmann984947d2009-02-06 23:35:19 +01002523 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002524 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002525
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002526 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002527 struct l2cap_info_req req;
2528 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2529
2530 conn->info_ident = l2cap_get_ident(conn);
2531
2532 l2cap_send_cmd(conn, conn->info_ident,
2533 L2CAP_INFO_REQ, sizeof(req), &req);
2534 } else {
2535 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2536 conn->info_ident = 0;
2537
2538 l2cap_conn_start(conn);
2539 }
2540 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002541 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002542 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002543
2544 l2cap_conn_start(conn);
2545 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002546
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547 return 0;
2548}
2549
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002550static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002551 u16 to_multiplier)
2552{
2553 u16 max_latency;
2554
2555 if (min > max || min < 6 || max > 3200)
2556 return -EINVAL;
2557
2558 if (to_multiplier < 10 || to_multiplier > 3200)
2559 return -EINVAL;
2560
2561 if (max >= to_multiplier * 8)
2562 return -EINVAL;
2563
2564 max_latency = (to_multiplier * 8 / max) - 1;
2565 if (latency > 499 || latency > max_latency)
2566 return -EINVAL;
2567
2568 return 0;
2569}
2570
2571static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2572 struct l2cap_cmd_hdr *cmd, u8 *data)
2573{
2574 struct hci_conn *hcon = conn->hcon;
2575 struct l2cap_conn_param_update_req *req;
2576 struct l2cap_conn_param_update_rsp rsp;
2577 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002578 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002579
2580 if (!(hcon->link_mode & HCI_LM_MASTER))
2581 return -EINVAL;
2582
2583 cmd_len = __le16_to_cpu(cmd->len);
2584 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2585 return -EPROTO;
2586
2587 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002588 min = __le16_to_cpu(req->min);
2589 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002590 latency = __le16_to_cpu(req->latency);
2591 to_multiplier = __le16_to_cpu(req->to_multiplier);
2592
2593 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2594 min, max, latency, to_multiplier);
2595
2596 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002597
2598 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2599 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002600 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2601 else
2602 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2603
2604 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2605 sizeof(rsp), &rsp);
2606
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002607 if (!err)
2608 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2609
Claudio Takahaside731152011-02-11 19:28:55 -02002610 return 0;
2611}
2612
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002613static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2614 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2615{
2616 int err = 0;
2617
2618 switch (cmd->code) {
2619 case L2CAP_COMMAND_REJ:
2620 l2cap_command_rej(conn, cmd, data);
2621 break;
2622
2623 case L2CAP_CONN_REQ:
2624 err = l2cap_connect_req(conn, cmd, data);
2625 break;
2626
2627 case L2CAP_CONN_RSP:
2628 err = l2cap_connect_rsp(conn, cmd, data);
2629 break;
2630
2631 case L2CAP_CONF_REQ:
2632 err = l2cap_config_req(conn, cmd, cmd_len, data);
2633 break;
2634
2635 case L2CAP_CONF_RSP:
2636 err = l2cap_config_rsp(conn, cmd, data);
2637 break;
2638
2639 case L2CAP_DISCONN_REQ:
2640 err = l2cap_disconnect_req(conn, cmd, data);
2641 break;
2642
2643 case L2CAP_DISCONN_RSP:
2644 err = l2cap_disconnect_rsp(conn, cmd, data);
2645 break;
2646
2647 case L2CAP_ECHO_REQ:
2648 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2649 break;
2650
2651 case L2CAP_ECHO_RSP:
2652 break;
2653
2654 case L2CAP_INFO_REQ:
2655 err = l2cap_information_req(conn, cmd, data);
2656 break;
2657
2658 case L2CAP_INFO_RSP:
2659 err = l2cap_information_rsp(conn, cmd, data);
2660 break;
2661
2662 default:
2663 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2664 err = -EINVAL;
2665 break;
2666 }
2667
2668 return err;
2669}
2670
2671static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2672 struct l2cap_cmd_hdr *cmd, u8 *data)
2673{
2674 switch (cmd->code) {
2675 case L2CAP_COMMAND_REJ:
2676 return 0;
2677
2678 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002679 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002680
2681 case L2CAP_CONN_PARAM_UPDATE_RSP:
2682 return 0;
2683
2684 default:
2685 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2686 return -EINVAL;
2687 }
2688}
2689
2690static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2691 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692{
2693 u8 *data = skb->data;
2694 int len = skb->len;
2695 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002696 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697
2698 l2cap_raw_recv(conn, skb);
2699
2700 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002701 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2703 data += L2CAP_CMD_HDR_SIZE;
2704 len -= L2CAP_CMD_HDR_SIZE;
2705
Al Viro88219a02007-07-29 00:17:25 -07002706 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707
Al Viro88219a02007-07-29 00:17:25 -07002708 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 -07002709
Al Viro88219a02007-07-29 00:17:25 -07002710 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711 BT_DBG("corrupted command");
2712 break;
2713 }
2714
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002715 if (conn->hcon->type == LE_LINK)
2716 err = l2cap_le_sig_cmd(conn, &cmd, data);
2717 else
2718 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719
2720 if (err) {
2721 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002722
2723 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724
2725 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002726 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2728 }
2729
Al Viro88219a02007-07-29 00:17:25 -07002730 data += cmd_len;
2731 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732 }
2733
2734 kfree_skb(skb);
2735}
2736
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002737static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2738{
2739 u16 our_fcs, rcv_fcs;
2740 int hdr_size = L2CAP_HDR_SIZE + 2;
2741
2742 if (pi->fcs == L2CAP_FCS_CRC16) {
2743 skb_trim(skb, skb->len - 2);
2744 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2745 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2746
2747 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002748 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002749 }
2750 return 0;
2751}
2752
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002753static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
2754{
2755 struct l2cap_pinfo *pi = l2cap_pi(sk);
2756 u16 control = 0;
2757
2758 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002759
2760 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2761
2762 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002763 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002764 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002765 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002766 }
2767
Gustavo F. Padovan4ea727e2010-06-03 16:34:20 -03002768 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
2769 l2cap_retransmit_frames(sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002770
2771 l2cap_ertm_send(sk);
2772
2773 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
2774 pi->frames_sent == 0) {
2775 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002776 l2cap_send_sframe(pi, control);
2777 }
2778}
2779
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002780static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002781{
2782 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002783 struct l2cap_pinfo *pi = l2cap_pi(sk);
2784 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002785
2786 bt_cb(skb)->tx_seq = tx_seq;
2787 bt_cb(skb)->sar = sar;
2788
2789 next_skb = skb_peek(SREJ_QUEUE(sk));
2790 if (!next_skb) {
2791 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002792 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002793 }
2794
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002795 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
2796 if (tx_seq_offset < 0)
2797 tx_seq_offset += 64;
2798
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002799 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002800 if (bt_cb(next_skb)->tx_seq == tx_seq)
2801 return -EINVAL;
2802
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002803 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
2804 pi->buffer_seq) % 64;
2805 if (next_tx_seq_offset < 0)
2806 next_tx_seq_offset += 64;
2807
2808 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002809 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002810 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002811 }
2812
2813 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
2814 break;
2815
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002816 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002817
2818 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002819
2820 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002821}
2822
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002823static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
2824{
2825 struct l2cap_pinfo *pi = l2cap_pi(sk);
2826 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002827 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002828
2829 switch (control & L2CAP_CTRL_SAR) {
2830 case L2CAP_SDU_UNSEGMENTED:
2831 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2832 goto drop;
2833
2834 err = sock_queue_rcv_skb(sk, skb);
2835 if (!err)
2836 return err;
2837
2838 break;
2839
2840 case L2CAP_SDU_START:
2841 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2842 goto drop;
2843
2844 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002845
2846 if (pi->sdu_len > pi->imtu)
2847 goto disconnect;
2848
2849 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002850 if (!pi->sdu)
2851 return -ENOMEM;
2852
2853 /* pull sdu_len bytes only after alloc, because of Local Busy
2854 * condition we have to be sure that this will be executed
2855 * only once, i.e., when alloc does not fail */
2856 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002857
2858 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2859
2860 pi->conn_state |= L2CAP_CONN_SAR_SDU;
2861 pi->partial_sdu_len = skb->len;
2862 break;
2863
2864 case L2CAP_SDU_CONTINUE:
2865 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2866 goto disconnect;
2867
2868 if (!pi->sdu)
2869 goto disconnect;
2870
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002871 pi->partial_sdu_len += skb->len;
2872 if (pi->partial_sdu_len > pi->sdu_len)
2873 goto drop;
2874
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002875 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2876
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002877 break;
2878
2879 case L2CAP_SDU_END:
2880 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2881 goto disconnect;
2882
2883 if (!pi->sdu)
2884 goto disconnect;
2885
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002886 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002887 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002888
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002889 if (pi->partial_sdu_len > pi->imtu)
2890 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002891
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002892 if (pi->partial_sdu_len != pi->sdu_len)
2893 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002894
2895 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002896 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002897
2898 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002899 if (!_skb) {
2900 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2901 return -ENOMEM;
2902 }
2903
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002904 err = sock_queue_rcv_skb(sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002905 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002906 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002907 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2908 return err;
2909 }
2910
2911 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2912 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002913
2914 kfree_skb(pi->sdu);
2915 break;
2916 }
2917
2918 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002919 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002920
2921drop:
2922 kfree_skb(pi->sdu);
2923 pi->sdu = NULL;
2924
2925disconnect:
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002926 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002927 kfree_skb(skb);
2928 return 0;
2929}
2930
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002931static int l2cap_try_push_rx_skb(struct sock *sk)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002932{
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002933 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002934 struct sk_buff *skb;
2935 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002936 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002937
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002938 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
2939 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
2940 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
2941 if (err < 0) {
2942 skb_queue_head(BUSY_QUEUE(sk), skb);
2943 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002944 }
2945
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002946 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002947 }
2948
2949 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
2950 goto done;
2951
2952 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2953 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
2954 l2cap_send_sframe(pi, control);
2955 l2cap_pi(sk)->retry_count = 1;
2956
2957 del_timer(&pi->retrans_timer);
2958 __mod_monitor_timer();
2959
2960 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
2961
2962done:
2963 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2964 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
2965
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002966 BT_DBG("sk %p, Exit local busy", sk);
2967
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002968 return 0;
2969}
2970
2971static void l2cap_busy_work(struct work_struct *work)
2972{
2973 DECLARE_WAITQUEUE(wait, current);
2974 struct l2cap_pinfo *pi =
2975 container_of(work, struct l2cap_pinfo, busy_work);
2976 struct sock *sk = (struct sock *)pi;
2977 int n_tries = 0, timeo = HZ/5, err;
2978 struct sk_buff *skb;
2979
2980 lock_sock(sk);
2981
2982 add_wait_queue(sk_sleep(sk), &wait);
2983 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
2984 set_current_state(TASK_INTERRUPTIBLE);
2985
2986 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
2987 err = -EBUSY;
2988 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
2989 break;
2990 }
2991
2992 if (!timeo)
2993 timeo = HZ/5;
2994
2995 if (signal_pending(current)) {
2996 err = sock_intr_errno(timeo);
2997 break;
2998 }
2999
3000 release_sock(sk);
3001 timeo = schedule_timeout(timeo);
3002 lock_sock(sk);
3003
3004 err = sock_error(sk);
3005 if (err)
3006 break;
3007
3008 if (l2cap_try_push_rx_skb(sk) == 0)
3009 break;
3010 }
3011
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003012 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003013 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003014
3015 release_sock(sk);
3016}
3017
3018static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
3019{
3020 struct l2cap_pinfo *pi = l2cap_pi(sk);
3021 int sctrl, err;
3022
3023 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
3024 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3025 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003026 return l2cap_try_push_rx_skb(sk);
3027
3028
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003029 }
3030
3031 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3032 if (err >= 0) {
3033 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3034 return err;
3035 }
3036
3037 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003038 BT_DBG("sk %p, Enter local busy", sk);
3039
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003040 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
3041 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3042 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3043
3044 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3045 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
3046 l2cap_send_sframe(pi, sctrl);
3047
3048 pi->conn_state |= L2CAP_CONN_RNR_SENT;
3049
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003050 del_timer(&pi->ack_timer);
3051
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003052 queue_work(_busy_wq, &pi->busy_work);
3053
3054 return err;
3055}
3056
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003057static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003058{
3059 struct l2cap_pinfo *pi = l2cap_pi(sk);
3060 struct sk_buff *_skb;
3061 int err = -EINVAL;
3062
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003063 /*
3064 * TODO: We have to notify the userland if some data is lost with the
3065 * Streaming Mode.
3066 */
3067
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003068 switch (control & L2CAP_CTRL_SAR) {
3069 case L2CAP_SDU_UNSEGMENTED:
3070 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3071 kfree_skb(pi->sdu);
3072 break;
3073 }
3074
3075 err = sock_queue_rcv_skb(sk, skb);
3076 if (!err)
3077 return 0;
3078
3079 break;
3080
3081 case L2CAP_SDU_START:
3082 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3083 kfree_skb(pi->sdu);
3084 break;
3085 }
3086
3087 pi->sdu_len = get_unaligned_le16(skb->data);
3088 skb_pull(skb, 2);
3089
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003090 if (pi->sdu_len > pi->imtu) {
3091 err = -EMSGSIZE;
3092 break;
3093 }
3094
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003095 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3096 if (!pi->sdu) {
3097 err = -ENOMEM;
3098 break;
3099 }
3100
3101 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3102
3103 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3104 pi->partial_sdu_len = skb->len;
3105 err = 0;
3106 break;
3107
3108 case L2CAP_SDU_CONTINUE:
3109 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3110 break;
3111
3112 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3113
3114 pi->partial_sdu_len += skb->len;
3115 if (pi->partial_sdu_len > pi->sdu_len)
3116 kfree_skb(pi->sdu);
3117 else
3118 err = 0;
3119
3120 break;
3121
3122 case L2CAP_SDU_END:
3123 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3124 break;
3125
3126 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3127
3128 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
3129 pi->partial_sdu_len += skb->len;
3130
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003131 if (pi->partial_sdu_len > pi->imtu)
3132 goto drop;
3133
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003134 if (pi->partial_sdu_len == pi->sdu_len) {
3135 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
3136 err = sock_queue_rcv_skb(sk, _skb);
3137 if (err < 0)
3138 kfree_skb(_skb);
3139 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003140 err = 0;
3141
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003142drop:
3143 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003144 break;
3145 }
3146
3147 kfree_skb(skb);
3148 return err;
3149}
3150
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003151static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
3152{
3153 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003154 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003155
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003156 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003157 if (bt_cb(skb)->tx_seq != tx_seq)
3158 break;
3159
3160 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003161 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003162 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003163 l2cap_pi(sk)->buffer_seq_srej =
3164 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003165 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003166 }
3167}
3168
3169static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
3170{
3171 struct l2cap_pinfo *pi = l2cap_pi(sk);
3172 struct srej_list *l, *tmp;
3173 u16 control;
3174
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003175 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003176 if (l->tx_seq == tx_seq) {
3177 list_del(&l->list);
3178 kfree(l);
3179 return;
3180 }
3181 control = L2CAP_SUPER_SELECT_REJECT;
3182 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3183 l2cap_send_sframe(pi, control);
3184 list_del(&l->list);
3185 list_add_tail(&l->list, SREJ_LIST(sk));
3186 }
3187}
3188
3189static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3190{
3191 struct l2cap_pinfo *pi = l2cap_pi(sk);
3192 struct srej_list *new;
3193 u16 control;
3194
3195 while (tx_seq != pi->expected_tx_seq) {
3196 control = L2CAP_SUPER_SELECT_REJECT;
3197 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3198 l2cap_send_sframe(pi, control);
3199
3200 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003201 new->tx_seq = pi->expected_tx_seq;
3202 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003203 list_add_tail(&new->list, SREJ_LIST(sk));
3204 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003205 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003206}
3207
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003208static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3209{
3210 struct l2cap_pinfo *pi = l2cap_pi(sk);
3211 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003212 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003213 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003214 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003215 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003216 int err = 0;
3217
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003218 BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
3219 rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003220
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003221 if (L2CAP_CTRL_FINAL & rx_control &&
3222 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003223 del_timer(&pi->monitor_timer);
3224 if (pi->unacked_frames > 0)
3225 __mod_retrans_timer();
3226 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
3227 }
3228
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003229 pi->expected_ack_seq = req_seq;
3230 l2cap_drop_acked_frames(sk);
3231
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003232 if (tx_seq == pi->expected_tx_seq)
3233 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003234
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003235 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3236 if (tx_seq_offset < 0)
3237 tx_seq_offset += 64;
3238
3239 /* invalid tx_seq */
3240 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003241 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003242 goto drop;
3243 }
3244
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003245 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
3246 goto drop;
3247
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003248 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3249 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003250
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003251 first = list_first_entry(SREJ_LIST(sk),
3252 struct srej_list, list);
3253 if (tx_seq == first->tx_seq) {
3254 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3255 l2cap_check_srej_gap(sk, tx_seq);
3256
3257 list_del(&first->list);
3258 kfree(first);
3259
3260 if (list_empty(SREJ_LIST(sk))) {
3261 pi->buffer_seq = pi->buffer_seq_srej;
3262 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666cc2010-05-01 16:15:40 -03003263 l2cap_send_ack(pi);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003264 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003265 }
3266 } else {
3267 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003268
3269 /* duplicated tx_seq */
3270 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
3271 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003272
3273 list_for_each_entry(l, SREJ_LIST(sk), list) {
3274 if (l->tx_seq == tx_seq) {
3275 l2cap_resend_srejframe(sk, tx_seq);
3276 return 0;
3277 }
3278 }
3279 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003280 }
3281 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003282 expected_tx_seq_offset =
3283 (pi->expected_tx_seq - pi->buffer_seq) % 64;
3284 if (expected_tx_seq_offset < 0)
3285 expected_tx_seq_offset += 64;
3286
3287 /* duplicated tx_seq */
3288 if (tx_seq_offset < expected_tx_seq_offset)
3289 goto drop;
3290
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003291 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003292
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003293 BT_DBG("sk %p, Enter SREJ", sk);
3294
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003295 INIT_LIST_HEAD(SREJ_LIST(sk));
3296 pi->buffer_seq_srej = pi->buffer_seq;
3297
3298 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003299 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003300 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3301
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003302 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
3303
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003304 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003305
3306 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003307 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003308 return 0;
3309
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003310expected:
3311 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3312
3313 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003314 bt_cb(skb)->tx_seq = tx_seq;
3315 bt_cb(skb)->sar = sar;
3316 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003317 return 0;
3318 }
3319
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003320 err = l2cap_push_rx_skb(sk, skb, rx_control);
3321 if (err < 0)
3322 return 0;
3323
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003324 if (rx_control & L2CAP_CTRL_FINAL) {
3325 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3326 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003327 else
3328 l2cap_retransmit_frames(sk);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003329 }
3330
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003331 __mod_ack_timer();
3332
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003333 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
3334 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003335 l2cap_send_ack(pi);
3336
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003337 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003338
3339drop:
3340 kfree_skb(skb);
3341 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003342}
3343
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003344static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003345{
3346 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003347
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003348 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3349 rx_control);
3350
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003351 pi->expected_ack_seq = __get_reqseq(rx_control);
3352 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003353
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003354 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003355 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003356 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3357 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3358 (pi->unacked_frames > 0))
3359 __mod_retrans_timer();
3360
3361 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3362 l2cap_send_srejtail(sk);
3363 } else {
3364 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003365 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003366
3367 } else if (rx_control & L2CAP_CTRL_FINAL) {
3368 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003369
3370 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3371 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003372 else
3373 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003374
3375 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003376 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3377 (pi->unacked_frames > 0))
3378 __mod_retrans_timer();
3379
3380 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003381 if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003382 l2cap_send_ack(pi);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003383 else
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003384 l2cap_ertm_send(sk);
3385 }
3386}
3387
3388static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
3389{
3390 struct l2cap_pinfo *pi = l2cap_pi(sk);
3391 u8 tx_seq = __get_reqseq(rx_control);
3392
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003393 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3394
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003395 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3396
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03003397 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003398 l2cap_drop_acked_frames(sk);
3399
3400 if (rx_control & L2CAP_CTRL_FINAL) {
3401 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3402 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003403 else
3404 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003405 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003406 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003407
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03003408 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003409 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003410 }
3411}
3412static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
3413{
3414 struct l2cap_pinfo *pi = l2cap_pi(sk);
3415 u8 tx_seq = __get_reqseq(rx_control);
3416
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003417 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3418
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003419 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3420
3421 if (rx_control & L2CAP_CTRL_POLL) {
3422 pi->expected_ack_seq = tx_seq;
3423 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003424
3425 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003426 l2cap_retransmit_one_frame(sk, tx_seq);
3427
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003428 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003429
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003430 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3431 pi->srej_save_reqseq = tx_seq;
3432 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3433 }
3434 } else if (rx_control & L2CAP_CTRL_FINAL) {
3435 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
3436 pi->srej_save_reqseq == tx_seq)
3437 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
3438 else
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003439 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003440 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003441 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003442 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3443 pi->srej_save_reqseq = tx_seq;
3444 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3445 }
3446 }
3447}
3448
3449static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
3450{
3451 struct l2cap_pinfo *pi = l2cap_pi(sk);
3452 u8 tx_seq = __get_reqseq(rx_control);
3453
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003454 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3455
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003456 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
3457 pi->expected_ack_seq = tx_seq;
3458 l2cap_drop_acked_frames(sk);
3459
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003460 if (rx_control & L2CAP_CTRL_POLL)
3461 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
3462
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003463 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
3464 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003465 if (rx_control & L2CAP_CTRL_POLL)
3466 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003467 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003468 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003469
3470 if (rx_control & L2CAP_CTRL_POLL)
3471 l2cap_send_srejtail(sk);
3472 else
3473 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003474}
3475
3476static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3477{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003478 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3479
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003480 if (L2CAP_CTRL_FINAL & rx_control &&
3481 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003482 del_timer(&l2cap_pi(sk)->monitor_timer);
3483 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003484 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003485 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003486 }
3487
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003488 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3489 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003490 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003491 break;
3492
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003493 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003494 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003495 break;
3496
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003497 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003498 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003499 break;
3500
3501 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003502 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003503 break;
3504 }
3505
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003506 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003507 return 0;
3508}
3509
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003510static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3511{
3512 struct l2cap_pinfo *pi = l2cap_pi(sk);
3513 u16 control;
3514 u8 req_seq;
3515 int len, next_tx_seq_offset, req_seq_offset;
3516
3517 control = get_unaligned_le16(skb->data);
3518 skb_pull(skb, 2);
3519 len = skb->len;
3520
3521 /*
3522 * We can just drop the corrupted I-frame here.
3523 * Receiver will miss it and start proper recovery
3524 * procedures and ask retransmission.
3525 */
3526 if (l2cap_check_fcs(pi, skb))
3527 goto drop;
3528
3529 if (__is_sar_start(control) && __is_iframe(control))
3530 len -= 2;
3531
3532 if (pi->fcs == L2CAP_FCS_CRC16)
3533 len -= 2;
3534
3535 if (len > pi->mps) {
3536 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3537 goto drop;
3538 }
3539
3540 req_seq = __get_reqseq(control);
3541 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
3542 if (req_seq_offset < 0)
3543 req_seq_offset += 64;
3544
3545 next_tx_seq_offset =
3546 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
3547 if (next_tx_seq_offset < 0)
3548 next_tx_seq_offset += 64;
3549
3550 /* check for invalid req-seq */
3551 if (req_seq_offset > next_tx_seq_offset) {
3552 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3553 goto drop;
3554 }
3555
3556 if (__is_iframe(control)) {
3557 if (len < 0) {
3558 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3559 goto drop;
3560 }
3561
3562 l2cap_data_channel_iframe(sk, control, skb);
3563 } else {
3564 if (len != 0) {
3565 BT_ERR("%d", len);
3566 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3567 goto drop;
3568 }
3569
3570 l2cap_data_channel_sframe(sk, control, skb);
3571 }
3572
3573 return 0;
3574
3575drop:
3576 kfree_skb(skb);
3577 return 0;
3578}
3579
Linus Torvalds1da177e2005-04-16 15:20:36 -07003580static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3581{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003582 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003583 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003584 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003585 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003586 u8 tx_seq;
3587 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003589 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003590 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591 BT_DBG("unknown cid 0x%4.4x", cid);
3592 goto drop;
3593 }
3594
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003595 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003596 pi = l2cap_pi(sk);
3597
Linus Torvalds1da177e2005-04-16 15:20:36 -07003598 BT_DBG("sk %p, len %d", sk, skb->len);
3599
3600 if (sk->sk_state != BT_CONNECTED)
3601 goto drop;
3602
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003603 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003604 case L2CAP_MODE_BASIC:
3605 /* If socket recv buffers overflows we drop data here
3606 * which is *bad* because L2CAP has to be reliable.
3607 * But we don't have any other choice. L2CAP doesn't
3608 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003610 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003611 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003613 if (!sock_queue_rcv_skb(sk, skb))
3614 goto done;
3615 break;
3616
3617 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003618 if (!sock_owned_by_user(sk)) {
3619 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003620 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003621 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003622 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003623 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003624
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003625 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003626
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003627 case L2CAP_MODE_STREAMING:
3628 control = get_unaligned_le16(skb->data);
3629 skb_pull(skb, 2);
3630 len = skb->len;
3631
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003632 if (l2cap_check_fcs(pi, skb))
3633 goto drop;
3634
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003635 if (__is_sar_start(control))
3636 len -= 2;
3637
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003638 if (pi->fcs == L2CAP_FCS_CRC16)
3639 len -= 2;
3640
Nathan Holstein51893f82010-06-09 15:46:25 -04003641 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003642 goto drop;
3643
3644 tx_seq = __get_txseq(control);
3645
3646 if (pi->expected_tx_seq == tx_seq)
3647 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3648 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03003649 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003650
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003651 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003652
3653 goto done;
3654
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003655 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003656 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003657 break;
3658 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659
3660drop:
3661 kfree_skb(skb);
3662
3663done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003664 if (sk)
3665 bh_unlock_sock(sk);
3666
Linus Torvalds1da177e2005-04-16 15:20:36 -07003667 return 0;
3668}
3669
Al Viro8e036fc2007-07-29 00:16:36 -07003670static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671{
3672 struct sock *sk;
3673
3674 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3675 if (!sk)
3676 goto drop;
3677
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003678 bh_lock_sock(sk);
3679
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680 BT_DBG("sk %p, len %d", sk, skb->len);
3681
3682 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3683 goto drop;
3684
3685 if (l2cap_pi(sk)->imtu < skb->len)
3686 goto drop;
3687
3688 if (!sock_queue_rcv_skb(sk, skb))
3689 goto done;
3690
3691drop:
3692 kfree_skb(skb);
3693
3694done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003695 if (sk)
3696 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697 return 0;
3698}
3699
3700static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3701{
3702 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003703 u16 cid, len;
3704 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705
3706 skb_pull(skb, L2CAP_HDR_SIZE);
3707 cid = __le16_to_cpu(lh->cid);
3708 len = __le16_to_cpu(lh->len);
3709
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003710 if (len != skb->len) {
3711 kfree_skb(skb);
3712 return;
3713 }
3714
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3716
3717 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003718 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003719 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720 l2cap_sig_channel(conn, skb);
3721 break;
3722
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003723 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003724 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725 skb_pull(skb, 2);
3726 l2cap_conless_channel(conn, psm, skb);
3727 break;
3728
3729 default:
3730 l2cap_data_channel(conn, cid, skb);
3731 break;
3732 }
3733}
3734
3735/* ---- L2CAP interface with lower layer (HCI) ---- */
3736
3737static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3738{
3739 int exact = 0, lm1 = 0, lm2 = 0;
3740 register struct sock *sk;
3741 struct hlist_node *node;
3742
3743 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003744 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003745
3746 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3747
3748 /* Find listening sockets and check their link_mode */
3749 read_lock(&l2cap_sk_list.lock);
3750 sk_for_each(sk, node, &l2cap_sk_list.head) {
3751 if (sk->sk_state != BT_LISTEN)
3752 continue;
3753
3754 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003755 lm1 |= HCI_LM_ACCEPT;
3756 if (l2cap_pi(sk)->role_switch)
3757 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003759 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3760 lm2 |= HCI_LM_ACCEPT;
3761 if (l2cap_pi(sk)->role_switch)
3762 lm2 |= HCI_LM_MASTER;
3763 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764 }
3765 read_unlock(&l2cap_sk_list.lock);
3766
3767 return exact ? lm1 : lm2;
3768}
3769
3770static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3771{
Marcel Holtmann01394182006-07-03 10:02:46 +02003772 struct l2cap_conn *conn;
3773
Linus Torvalds1da177e2005-04-16 15:20:36 -07003774 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3775
Ville Tervoacd7d372011-02-10 22:38:49 -03003776 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003777 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778
3779 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003780 conn = l2cap_conn_add(hcon, status);
3781 if (conn)
3782 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003783 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784 l2cap_conn_del(hcon, bt_err(status));
3785
3786 return 0;
3787}
3788
Marcel Holtmann2950f212009-02-12 14:02:50 +01003789static int l2cap_disconn_ind(struct hci_conn *hcon)
3790{
3791 struct l2cap_conn *conn = hcon->l2cap_data;
3792
3793 BT_DBG("hcon %p", hcon);
3794
3795 if (hcon->type != ACL_LINK || !conn)
3796 return 0x13;
3797
3798 return conn->disc_reason;
3799}
3800
3801static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802{
3803 BT_DBG("hcon %p reason %d", hcon, reason);
3804
Ville Tervoacd7d372011-02-10 22:38:49 -03003805 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003806 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807
3808 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003809
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 return 0;
3811}
3812
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003813static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3814{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003815 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003816 return;
3817
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003818 if (encrypt == 0x00) {
3819 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3820 l2cap_sock_clear_timer(sk);
3821 l2cap_sock_set_timer(sk, HZ * 5);
3822 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3823 __l2cap_sock_close(sk, ECONNREFUSED);
3824 } else {
3825 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3826 l2cap_sock_clear_timer(sk);
3827 }
3828}
3829
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003830static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003832 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003833 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003834
Marcel Holtmann01394182006-07-03 10:02:46 +02003835 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003837
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838 BT_DBG("conn %p", conn);
3839
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003840 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003842 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003843 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003844
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845 bh_lock_sock(sk);
3846
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003847 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3848 bh_unlock_sock(sk);
3849 continue;
3850 }
3851
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003852 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003853 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003854 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003855 bh_unlock_sock(sk);
3856 continue;
3857 }
3858
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003859 if (sk->sk_state == BT_CONNECT) {
3860 if (!status) {
3861 struct l2cap_conn_req req;
3862 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3863 req.psm = l2cap_pi(sk)->psm;
3864
3865 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003866 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003867
3868 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3869 L2CAP_CONN_REQ, sizeof(req), &req);
3870 } else {
3871 l2cap_sock_clear_timer(sk);
3872 l2cap_sock_set_timer(sk, HZ / 10);
3873 }
3874 } else if (sk->sk_state == BT_CONNECT2) {
3875 struct l2cap_conn_rsp rsp;
3876 __u16 result;
3877
3878 if (!status) {
3879 sk->sk_state = BT_CONFIG;
3880 result = L2CAP_CR_SUCCESS;
3881 } else {
3882 sk->sk_state = BT_DISCONN;
3883 l2cap_sock_set_timer(sk, HZ / 10);
3884 result = L2CAP_CR_SEC_BLOCK;
3885 }
3886
3887 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3888 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3889 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003890 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003891 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3892 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893 }
3894
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895 bh_unlock_sock(sk);
3896 }
3897
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003898 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003899
Linus Torvalds1da177e2005-04-16 15:20:36 -07003900 return 0;
3901}
3902
3903static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3904{
3905 struct l2cap_conn *conn = hcon->l2cap_data;
3906
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003907 if (!conn)
3908 conn = l2cap_conn_add(hcon, 0);
3909
3910 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911 goto drop;
3912
3913 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3914
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003915 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003917 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003918 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919 int len;
3920
3921 if (conn->rx_len) {
3922 BT_ERR("Unexpected start frame (len %d)", skb->len);
3923 kfree_skb(conn->rx_skb);
3924 conn->rx_skb = NULL;
3925 conn->rx_len = 0;
3926 l2cap_conn_unreliable(conn, ECOMM);
3927 }
3928
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003929 /* Start fragment always begin with Basic L2CAP header */
3930 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931 BT_ERR("Frame is too short (len %d)", skb->len);
3932 l2cap_conn_unreliable(conn, ECOMM);
3933 goto drop;
3934 }
3935
3936 hdr = (struct l2cap_hdr *) skb->data;
3937 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003938 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939
3940 if (len == skb->len) {
3941 /* Complete frame received */
3942 l2cap_recv_frame(conn, skb);
3943 return 0;
3944 }
3945
3946 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3947
3948 if (skb->len > len) {
3949 BT_ERR("Frame is too long (len %d, expected len %d)",
3950 skb->len, len);
3951 l2cap_conn_unreliable(conn, ECOMM);
3952 goto drop;
3953 }
3954
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003955 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003956
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003957 if (chan && chan->sk) {
3958 struct sock *sk = chan->sk;
3959
3960 if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
3961 BT_ERR("Frame exceeding recv MTU (len %d, "
3962 "MTU %d)", len,
3963 l2cap_pi(sk)->imtu);
3964 bh_unlock_sock(sk);
3965 l2cap_conn_unreliable(conn, ECOMM);
3966 goto drop;
3967 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003968 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003969 }
3970
Linus Torvalds1da177e2005-04-16 15:20:36 -07003971 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003972 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
3973 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974 goto drop;
3975
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003976 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003977 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003978 conn->rx_len = len - skb->len;
3979 } else {
3980 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
3981
3982 if (!conn->rx_len) {
3983 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
3984 l2cap_conn_unreliable(conn, ECOMM);
3985 goto drop;
3986 }
3987
3988 if (skb->len > conn->rx_len) {
3989 BT_ERR("Fragment is too long (len %d, expected %d)",
3990 skb->len, conn->rx_len);
3991 kfree_skb(conn->rx_skb);
3992 conn->rx_skb = NULL;
3993 conn->rx_len = 0;
3994 l2cap_conn_unreliable(conn, ECOMM);
3995 goto drop;
3996 }
3997
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003998 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003999 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004000 conn->rx_len -= skb->len;
4001
4002 if (!conn->rx_len) {
4003 /* Complete frame received */
4004 l2cap_recv_frame(conn, conn->rx_skb);
4005 conn->rx_skb = NULL;
4006 }
4007 }
4008
4009drop:
4010 kfree_skb(skb);
4011 return 0;
4012}
4013
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004014static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004015{
4016 struct sock *sk;
4017 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018
4019 read_lock_bh(&l2cap_sk_list.lock);
4020
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004021 sk_for_each(sk, node, &l2cap_sk_list.head) {
4022 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004024 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 +01004025 batostr(&bt_sk(sk)->src),
4026 batostr(&bt_sk(sk)->dst),
4027 sk->sk_state, __le16_to_cpu(pi->psm),
4028 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004029 pi->imtu, pi->omtu, pi->sec_level,
4030 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004031 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004034
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004035 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036}
4037
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004038static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4039{
4040 return single_open(file, l2cap_debugfs_show, inode->i_private);
4041}
4042
4043static const struct file_operations l2cap_debugfs_fops = {
4044 .open = l2cap_debugfs_open,
4045 .read = seq_read,
4046 .llseek = seq_lseek,
4047 .release = single_release,
4048};
4049
4050static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052static struct hci_proto l2cap_hci_proto = {
4053 .name = "L2CAP",
4054 .id = HCI_PROTO_L2CAP,
4055 .connect_ind = l2cap_connect_ind,
4056 .connect_cfm = l2cap_connect_cfm,
4057 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004058 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004059 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 .recv_acldata = l2cap_recv_acldata
4061};
4062
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004063int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064{
4065 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004066
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004067 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068 if (err < 0)
4069 return err;
4070
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004071 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004072 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004073 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074 goto error;
4075 }
4076
4077 err = hci_register_proto(&l2cap_hci_proto);
4078 if (err < 0) {
4079 BT_ERR("L2CAP protocol registration failed");
4080 bt_sock_unregister(BTPROTO_L2CAP);
4081 goto error;
4082 }
4083
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004084 if (bt_debugfs) {
4085 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4086 bt_debugfs, NULL, &l2cap_debugfs_fops);
4087 if (!l2cap_debugfs)
4088 BT_ERR("Failed to create L2CAP debug file");
4089 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091 return 0;
4092
4093error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004094 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004095 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096 return err;
4097}
4098
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004099void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004101 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004103 flush_workqueue(_busy_wq);
4104 destroy_workqueue(_busy_wq);
4105
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4107 BT_ERR("L2CAP protocol unregistration failed");
4108
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004109 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110}
4111
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004112module_param(disable_ertm, bool, 0644);
4113MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");