blob: 0dbbaf394c1397a00647088f8c2fc03741f34c27 [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. Padovancf6c2c02010-06-07 20:54:45 -0300490 struct sock_del_list del, *tmp1, *tmp2;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300491 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200492
493 BT_DBG("conn %p", conn);
494
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300495 INIT_LIST_HEAD(&del.list);
496
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300497 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200498
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300499 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300500 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300501
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200502 bh_lock_sock(sk);
503
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300504 if (sk->sk_type != SOCK_SEQPACKET &&
505 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200506 bh_unlock_sock(sk);
507 continue;
508 }
509
510 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300511 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300512
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300513 if (!l2cap_check_security(sk) ||
514 !__l2cap_no_conn_pending(sk)) {
515 bh_unlock_sock(sk);
516 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200517 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300518
519 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
520 conn->feat_mask)
521 && l2cap_pi(sk)->conf_state &
522 L2CAP_CONF_STATE2_DEVICE) {
523 tmp1 = kzalloc(sizeof(struct sock_del_list),
524 GFP_ATOMIC);
525 tmp1->sk = sk;
526 list_add_tail(&tmp1->list, &del.list);
527 bh_unlock_sock(sk);
528 continue;
529 }
530
531 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
532 req.psm = l2cap_pi(sk)->psm;
533
534 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
535 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
536
537 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
538 L2CAP_CONN_REQ, sizeof(req), &req);
539
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200540 } else if (sk->sk_state == BT_CONNECT2) {
541 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300542 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200543 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
544 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
545
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100546 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100547 if (bt_sk(sk)->defer_setup) {
548 struct sock *parent = bt_sk(sk)->parent;
549 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
550 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
551 parent->sk_data_ready(parent, 0);
552
553 } else {
554 sk->sk_state = BT_CONFIG;
555 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
556 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
557 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200558 } else {
559 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
560 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
561 }
562
563 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
564 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300565
566 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
567 rsp.result != L2CAP_CR_SUCCESS) {
568 bh_unlock_sock(sk);
569 continue;
570 }
571
572 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
573 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
574 l2cap_build_conf_req(sk, buf), buf);
575 l2cap_pi(sk)->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200576 }
577
578 bh_unlock_sock(sk);
579 }
580
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300581 read_unlock(&conn->chan_lock);
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300582
583 list_for_each_entry_safe(tmp1, tmp2, &del.list, list) {
584 bh_lock_sock(tmp1->sk);
585 __l2cap_sock_close(tmp1->sk, ECONNRESET);
586 bh_unlock_sock(tmp1->sk);
587 list_del(&tmp1->list);
588 kfree(tmp1);
589 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200590}
591
Ville Tervob62f3282011-02-10 22:38:50 -0300592/* Find socket with cid and source bdaddr.
593 * Returns closest match, locked.
594 */
595static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
596{
597 struct sock *s, *sk = NULL, *sk1 = NULL;
598 struct hlist_node *node;
599
600 read_lock(&l2cap_sk_list.lock);
601
602 sk_for_each(sk, node, &l2cap_sk_list.head) {
603 if (state && sk->sk_state != state)
604 continue;
605
606 if (l2cap_pi(sk)->scid == cid) {
607 /* Exact match. */
608 if (!bacmp(&bt_sk(sk)->src, src))
609 break;
610
611 /* Closest match */
612 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
613 sk1 = sk;
614 }
615 }
616 s = node ? sk : sk1;
617 if (s)
618 bh_lock_sock(s);
619 read_unlock(&l2cap_sk_list.lock);
620
621 return s;
622}
623
624static void l2cap_le_conn_ready(struct l2cap_conn *conn)
625{
Ville Tervob62f3282011-02-10 22:38:50 -0300626 struct sock *parent, *uninitialized_var(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300627 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300628
629 BT_DBG("");
630
631 /* Check if we have socket listening on cid */
632 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
633 conn->src);
634 if (!parent)
635 return;
636
637 /* Check for backlog size */
638 if (sk_acceptq_is_full(parent)) {
639 BT_DBG("backlog full %d", parent->sk_ack_backlog);
640 goto clean;
641 }
642
643 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
644 if (!sk)
645 goto clean;
646
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300647 chan = l2cap_chan_alloc(sk);
648 if (!chan) {
649 l2cap_sock_kill(sk);
650 goto clean;
651 }
652
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300653 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300654
655 hci_conn_hold(conn->hcon);
656
657 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300658
Ville Tervob62f3282011-02-10 22:38:50 -0300659 bacpy(&bt_sk(sk)->src, conn->src);
660 bacpy(&bt_sk(sk)->dst, conn->dst);
661
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300662 bt_accept_enqueue(parent, sk);
663
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300664 __l2cap_chan_add(conn, chan);
665
666 l2cap_pi(sk)->chan = chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300667
668 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
669
670 sk->sk_state = BT_CONNECTED;
671 parent->sk_data_ready(parent, 0);
672
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300673 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300674
675clean:
676 bh_unlock_sock(parent);
677}
678
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200679static void l2cap_conn_ready(struct l2cap_conn *conn)
680{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300681 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200682
683 BT_DBG("conn %p", conn);
684
Ville Tervob62f3282011-02-10 22:38:50 -0300685 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
686 l2cap_le_conn_ready(conn);
687
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300688 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200689
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300690 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300691 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300692
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200693 bh_lock_sock(sk);
694
Ville Tervoacd7d372011-02-10 22:38:49 -0300695 if (conn->hcon->type == LE_LINK) {
696 l2cap_sock_clear_timer(sk);
697 sk->sk_state = BT_CONNECTED;
698 sk->sk_state_change(sk);
699 }
700
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300701 if (sk->sk_type != SOCK_SEQPACKET &&
702 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200703 l2cap_sock_clear_timer(sk);
704 sk->sk_state = BT_CONNECTED;
705 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200706 } else if (sk->sk_state == BT_CONNECT)
707 l2cap_do_start(sk);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200708
709 bh_unlock_sock(sk);
710 }
711
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300712 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200713}
714
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200715/* Notify sockets that we cannot guaranty reliability anymore */
716static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
717{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300718 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200719
720 BT_DBG("conn %p", conn);
721
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300722 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200723
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300724 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300725 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300726
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100727 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200728 sk->sk_err = err;
729 }
730
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300731 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200732}
733
734static void l2cap_info_timeout(unsigned long arg)
735{
736 struct l2cap_conn *conn = (void *) arg;
737
Marcel Holtmann984947d2009-02-06 23:35:19 +0100738 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100739 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100740
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200741 l2cap_conn_start(conn);
742}
743
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
745{
Marcel Holtmann01394182006-07-03 10:02:46 +0200746 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
Marcel Holtmann01394182006-07-03 10:02:46 +0200748 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 return conn;
750
Marcel Holtmann01394182006-07-03 10:02:46 +0200751 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
752 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
755 hcon->l2cap_data = conn;
756 conn->hcon = hcon;
757
Marcel Holtmann01394182006-07-03 10:02:46 +0200758 BT_DBG("hcon %p conn %p", hcon, conn);
759
Ville Tervoacd7d372011-02-10 22:38:49 -0300760 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
761 conn->mtu = hcon->hdev->le_mtu;
762 else
763 conn->mtu = hcon->hdev->acl_mtu;
764
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 conn->src = &hcon->hdev->bdaddr;
766 conn->dst = &hcon->dst;
767
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200768 conn->feat_mask = 0;
769
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300771 rwlock_init(&conn->chan_lock);
772
773 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774
Ville Tervob62f3282011-02-10 22:38:50 -0300775 if (hcon->type != LE_LINK)
776 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000777 (unsigned long) conn);
778
Marcel Holtmann2950f212009-02-12 14:02:50 +0100779 conn->disc_reason = 0x13;
780
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 return conn;
782}
783
Marcel Holtmann01394182006-07-03 10:02:46 +0200784static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785{
Marcel Holtmann01394182006-07-03 10:02:46 +0200786 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300787 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 struct sock *sk;
789
Marcel Holtmann01394182006-07-03 10:02:46 +0200790 if (!conn)
791 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
793 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
794
Wei Yongjun7585b972009-02-25 18:29:52 +0800795 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796
797 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300798 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300799 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300801 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 bh_unlock_sock(sk);
803 l2cap_sock_kill(sk);
804 }
805
Dave Young8e8440f2008-03-03 12:18:55 -0800806 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
807 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800808
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 hcon->l2cap_data = NULL;
810 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811}
812
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300813static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300815 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300816 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300817 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818}
819
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
822/* Find socket with psm and source bdaddr.
823 * Returns closest match.
824 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000825static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826{
827 struct sock *sk = NULL, *sk1 = NULL;
828 struct hlist_node *node;
829
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000830 read_lock(&l2cap_sk_list.lock);
831
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 sk_for_each(sk, node, &l2cap_sk_list.head) {
833 if (state && sk->sk_state != state)
834 continue;
835
836 if (l2cap_pi(sk)->psm == psm) {
837 /* Exact match. */
838 if (!bacmp(&bt_sk(sk)->src, src))
839 break;
840
841 /* Closest match */
842 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
843 sk1 = sk;
844 }
845 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000848
849 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850}
851
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200852int l2cap_do_connect(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853{
854 bdaddr_t *src = &bt_sk(sk)->src;
855 bdaddr_t *dst = &bt_sk(sk)->dst;
856 struct l2cap_conn *conn;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300857 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 struct hci_conn *hcon;
859 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200860 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200861 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100863 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
864 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300866 hdev = hci_get_route(dst, src);
867 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 return -EHOSTUNREACH;
869
870 hci_dev_lock_bh(hdev);
871
Johan Hedberg8556edd32011-01-19 12:06:50 +0530872 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200873
Ville Tervoacd7d372011-02-10 22:38:49 -0300874 if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
875 hcon = hci_connect(hdev, LE_LINK, dst,
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100876 l2cap_pi(sk)->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300877 else
878 hcon = hci_connect(hdev, ACL_LINK, dst,
879 l2cap_pi(sk)->sec_level, auth_type);
880
Ville Tervo30e76272011-02-22 16:10:53 -0300881 if (IS_ERR(hcon)) {
882 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300884 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885
886 conn = l2cap_conn_add(hcon, 0);
887 if (!conn) {
888 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300889 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 goto done;
891 }
892
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300893 chan = l2cap_chan_alloc(sk);
894 if (!chan) {
895 hci_conn_put(hcon);
896 err = -ENOMEM;
897 goto done;
898 }
899
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 /* Update source addr of the socket */
901 bacpy(src, conn->src);
902
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300903 l2cap_chan_add(conn, chan);
904
905 l2cap_pi(sk)->chan = chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906
907 sk->sk_state = BT_CONNECT;
908 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
909
910 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300911 if (sk->sk_type != SOCK_SEQPACKET &&
912 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530914 if (l2cap_check_security(sk))
915 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200916 } else
917 l2cap_do_start(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 }
919
Ville Tervo30e76272011-02-22 16:10:53 -0300920 err = 0;
921
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922done:
923 hci_dev_unlock_bh(hdev);
924 hci_dev_put(hdev);
925 return err;
926}
927
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200928int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300929{
930 DECLARE_WAITQUEUE(wait, current);
931 int err = 0;
932 int timeo = HZ/5;
933
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200934 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300935 while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
936 set_current_state(TASK_INTERRUPTIBLE);
937
938 if (!timeo)
939 timeo = HZ/5;
940
941 if (signal_pending(current)) {
942 err = sock_intr_errno(timeo);
943 break;
944 }
945
946 release_sock(sk);
947 timeo = schedule_timeout(timeo);
948 lock_sock(sk);
949
950 err = sock_error(sk);
951 if (err)
952 break;
953 }
954 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200955 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300956 return err;
957}
958
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300959static void l2cap_monitor_timeout(unsigned long arg)
960{
961 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300962
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300963 BT_DBG("sk %p", sk);
964
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300965 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300966 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300967 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200968 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300969 return;
970 }
971
972 l2cap_pi(sk)->retry_count++;
973 __mod_monitor_timer();
974
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -0300975 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300976 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300977}
978
979static void l2cap_retrans_timeout(unsigned long arg)
980{
981 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300982
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300983 BT_DBG("sk %p", sk);
984
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300985 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300986 l2cap_pi(sk)->retry_count = 1;
987 __mod_monitor_timer();
988
989 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
990
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -0300991 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300992 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300993}
994
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300995static void l2cap_drop_acked_frames(struct sock *sk)
996{
997 struct sk_buff *skb;
998
Gustavo F. Padovan812e7372010-05-01 16:15:42 -0300999 while ((skb = skb_peek(TX_QUEUE(sk))) &&
1000 l2cap_pi(sk)->unacked_frames) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001001 if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
1002 break;
1003
1004 skb = skb_dequeue(TX_QUEUE(sk));
1005 kfree_skb(skb);
1006
1007 l2cap_pi(sk)->unacked_frames--;
1008 }
1009
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001010 if (!l2cap_pi(sk)->unacked_frames)
1011 del_timer(&l2cap_pi(sk)->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001012}
1013
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001014void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001015{
1016 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001017 struct hci_conn *hcon = pi->conn->hcon;
1018 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001019
1020 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1021
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001022 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
1023 flags = ACL_START_NO_FLUSH;
1024 else
1025 flags = ACL_START;
1026
1027 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001028}
1029
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001030void l2cap_streaming_send(struct sock *sk)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001031{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001032 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001033 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001034 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001035
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001036 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
1037 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001038 control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001039 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001040
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001041 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001042 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1043 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001044 }
1045
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001046 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001047
1048 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001049 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001050}
1051
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001052static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001053{
1054 struct l2cap_pinfo *pi = l2cap_pi(sk);
1055 struct sk_buff *skb, *tx_skb;
1056 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001057
1058 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001059 if (!skb)
1060 return;
1061
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001062 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001063 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001064 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001065
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001066 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1067 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001068
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001069 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001070
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001071 if (pi->remote_max_tx &&
1072 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001073 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001074 return;
1075 }
1076
1077 tx_skb = skb_clone(skb, GFP_ATOMIC);
1078 bt_cb(skb)->retries++;
1079 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001080
1081 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1082 control |= L2CAP_CTRL_FINAL;
1083 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1084 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001085
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001086 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1087 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001088
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001089 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1090
1091 if (pi->fcs == L2CAP_FCS_CRC16) {
1092 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1093 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1094 }
1095
1096 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001097}
1098
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001099int l2cap_ertm_send(struct sock *sk)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001100{
1101 struct sk_buff *skb, *tx_skb;
1102 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001103 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001104 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001105
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001106 if (sk->sk_state != BT_CONNECTED)
1107 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001108
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001109 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001110
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001111 if (pi->remote_max_tx &&
1112 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001113 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001114 break;
1115 }
1116
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001117 tx_skb = skb_clone(skb, GFP_ATOMIC);
1118
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001119 bt_cb(skb)->retries++;
1120
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001121 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001122 control &= L2CAP_CTRL_SAR;
1123
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001124 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1125 control |= L2CAP_CTRL_FINAL;
1126 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1127 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001128 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001129 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1130 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1131
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001132
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001133 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001134 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1135 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1136 }
1137
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001138 l2cap_do_send(sk, tx_skb);
1139
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001140 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001141
1142 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1143 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1144
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301145 if (bt_cb(skb)->retries == 1)
1146 pi->unacked_frames++;
1147
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001148 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001149
1150 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1151 sk->sk_send_head = NULL;
1152 else
1153 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001154
1155 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001156 }
1157
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001158 return nsent;
1159}
1160
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001161static int l2cap_retransmit_frames(struct sock *sk)
1162{
1163 struct l2cap_pinfo *pi = l2cap_pi(sk);
1164 int ret;
1165
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001166 if (!skb_queue_empty(TX_QUEUE(sk)))
1167 sk->sk_send_head = TX_QUEUE(sk)->next;
1168
1169 pi->next_tx_seq = pi->expected_ack_seq;
1170 ret = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001171 return ret;
1172}
1173
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001174static void l2cap_send_ack(struct l2cap_pinfo *pi)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001175{
1176 struct sock *sk = (struct sock *)pi;
1177 u16 control = 0;
1178
1179 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1180
1181 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1182 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001183 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001184 l2cap_send_sframe(pi, control);
1185 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001186 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001187
Gustavo F. Padovane0f66212010-06-21 18:50:49 -03001188 if (l2cap_ertm_send(sk) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001189 return;
1190
1191 control |= L2CAP_SUPER_RCV_READY;
1192 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001193}
1194
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001195static void l2cap_send_srejtail(struct sock *sk)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001196{
1197 struct srej_list *tail;
1198 u16 control;
1199
1200 control = L2CAP_SUPER_SELECT_REJECT;
1201 control |= L2CAP_CTRL_FINAL;
1202
1203 tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
1204 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1205
1206 l2cap_send_sframe(l2cap_pi(sk), control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001207}
1208
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001209static 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 -07001210{
1211 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001212 struct sk_buff **frag;
1213 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001215 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001216 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217
1218 sent += count;
1219 len -= count;
1220
1221 /* Continuation fragments (no L2CAP header) */
1222 frag = &skb_shinfo(skb)->frag_list;
1223 while (len) {
1224 count = min_t(unsigned int, conn->mtu, len);
1225
1226 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1227 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001228 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001229 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1230 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231
1232 sent += count;
1233 len -= count;
1234
1235 frag = &(*frag)->next;
1236 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237
1238 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001239}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001241struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001242{
1243 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1244 struct sk_buff *skb;
1245 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1246 struct l2cap_hdr *lh;
1247
1248 BT_DBG("sk %p len %d", sk, (int)len);
1249
1250 count = min_t(unsigned int, (conn->mtu - hlen), len);
1251 skb = bt_skb_send_alloc(sk, count + hlen,
1252 msg->msg_flags & MSG_DONTWAIT, &err);
1253 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001254 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001255
1256 /* Create L2CAP header */
1257 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1258 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1259 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1260 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1261
1262 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1263 if (unlikely(err < 0)) {
1264 kfree_skb(skb);
1265 return ERR_PTR(err);
1266 }
1267 return skb;
1268}
1269
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001270struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001271{
1272 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1273 struct sk_buff *skb;
1274 int err, count, hlen = L2CAP_HDR_SIZE;
1275 struct l2cap_hdr *lh;
1276
1277 BT_DBG("sk %p len %d", sk, (int)len);
1278
1279 count = min_t(unsigned int, (conn->mtu - hlen), len);
1280 skb = bt_skb_send_alloc(sk, count + hlen,
1281 msg->msg_flags & MSG_DONTWAIT, &err);
1282 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001283 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001284
1285 /* Create L2CAP header */
1286 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1287 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1288 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1289
1290 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1291 if (unlikely(err < 0)) {
1292 kfree_skb(skb);
1293 return ERR_PTR(err);
1294 }
1295 return skb;
1296}
1297
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001298struct 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 -03001299{
1300 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1301 struct sk_buff *skb;
1302 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1303 struct l2cap_hdr *lh;
1304
1305 BT_DBG("sk %p len %d", sk, (int)len);
1306
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001307 if (!conn)
1308 return ERR_PTR(-ENOTCONN);
1309
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001310 if (sdulen)
1311 hlen += 2;
1312
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001313 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1314 hlen += 2;
1315
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001316 count = min_t(unsigned int, (conn->mtu - hlen), len);
1317 skb = bt_skb_send_alloc(sk, count + hlen,
1318 msg->msg_flags & MSG_DONTWAIT, &err);
1319 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001320 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001321
1322 /* Create L2CAP header */
1323 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1324 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1325 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1326 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001327 if (sdulen)
1328 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001329
1330 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1331 if (unlikely(err < 0)) {
1332 kfree_skb(skb);
1333 return ERR_PTR(err);
1334 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001335
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001336 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1337 put_unaligned_le16(0, skb_put(skb, 2));
1338
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001339 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001340 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341}
1342
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001343int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001344{
1345 struct l2cap_pinfo *pi = l2cap_pi(sk);
1346 struct sk_buff *skb;
1347 struct sk_buff_head sar_queue;
1348 u16 control;
1349 size_t size = 0;
1350
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001351 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001352 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001353 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001354 if (IS_ERR(skb))
1355 return PTR_ERR(skb);
1356
1357 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001358 len -= pi->remote_mps;
1359 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001360
1361 while (len > 0) {
1362 size_t buflen;
1363
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001364 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001365 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001366 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001367 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001368 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001369 buflen = len;
1370 }
1371
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001372 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001373 if (IS_ERR(skb)) {
1374 skb_queue_purge(&sar_queue);
1375 return PTR_ERR(skb);
1376 }
1377
1378 __skb_queue_tail(&sar_queue, skb);
1379 len -= buflen;
1380 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001381 }
1382 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1383 if (sk->sk_send_head == NULL)
1384 sk->sk_send_head = sar_queue.next;
1385
1386 return size;
1387}
1388
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389static void l2cap_chan_ready(struct sock *sk)
1390{
1391 struct sock *parent = bt_sk(sk)->parent;
1392
1393 BT_DBG("sk %p, parent %p", sk, parent);
1394
1395 l2cap_pi(sk)->conf_state = 0;
1396 l2cap_sock_clear_timer(sk);
1397
1398 if (!parent) {
1399 /* Outgoing channel.
1400 * Wake up socket sleeping on connect.
1401 */
1402 sk->sk_state = BT_CONNECTED;
1403 sk->sk_state_change(sk);
1404 } else {
1405 /* Incoming channel.
1406 * Wake up socket sleeping on accept.
1407 */
1408 parent->sk_data_ready(parent, 0);
1409 }
1410}
1411
1412/* Copy frame to all raw sockets on that connection */
1413static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1414{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001416 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417
1418 BT_DBG("conn %p", conn);
1419
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001420 read_lock(&conn->chan_lock);
1421 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001422 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 if (sk->sk_type != SOCK_RAW)
1424 continue;
1425
1426 /* Don't send frame to the socket it came from */
1427 if (skb->sk == sk)
1428 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001429 nskb = skb_clone(skb, GFP_ATOMIC);
1430 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 continue;
1432
1433 if (sock_queue_rcv_skb(sk, nskb))
1434 kfree_skb(nskb);
1435 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001436 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437}
1438
1439/* ---- L2CAP signalling commands ---- */
1440static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1441 u8 code, u8 ident, u16 dlen, void *data)
1442{
1443 struct sk_buff *skb, **frag;
1444 struct l2cap_cmd_hdr *cmd;
1445 struct l2cap_hdr *lh;
1446 int len, count;
1447
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001448 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1449 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450
1451 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1452 count = min_t(unsigned int, conn->mtu, len);
1453
1454 skb = bt_skb_alloc(count, GFP_ATOMIC);
1455 if (!skb)
1456 return NULL;
1457
1458 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001459 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001460
1461 if (conn->hcon->type == LE_LINK)
1462 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1463 else
1464 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465
1466 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1467 cmd->code = code;
1468 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001469 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
1471 if (dlen) {
1472 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1473 memcpy(skb_put(skb, count), data, count);
1474 data += count;
1475 }
1476
1477 len -= skb->len;
1478
1479 /* Continuation fragments (no L2CAP header) */
1480 frag = &skb_shinfo(skb)->frag_list;
1481 while (len) {
1482 count = min_t(unsigned int, conn->mtu, len);
1483
1484 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1485 if (!*frag)
1486 goto fail;
1487
1488 memcpy(skb_put(*frag, count), data, count);
1489
1490 len -= count;
1491 data += count;
1492
1493 frag = &(*frag)->next;
1494 }
1495
1496 return skb;
1497
1498fail:
1499 kfree_skb(skb);
1500 return NULL;
1501}
1502
1503static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1504{
1505 struct l2cap_conf_opt *opt = *ptr;
1506 int len;
1507
1508 len = L2CAP_CONF_OPT_SIZE + opt->len;
1509 *ptr += len;
1510
1511 *type = opt->type;
1512 *olen = opt->len;
1513
1514 switch (opt->len) {
1515 case 1:
1516 *val = *((u8 *) opt->val);
1517 break;
1518
1519 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001520 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 break;
1522
1523 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001524 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 break;
1526
1527 default:
1528 *val = (unsigned long) opt->val;
1529 break;
1530 }
1531
1532 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1533 return len;
1534}
1535
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1537{
1538 struct l2cap_conf_opt *opt = *ptr;
1539
1540 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1541
1542 opt->type = type;
1543 opt->len = len;
1544
1545 switch (len) {
1546 case 1:
1547 *((u8 *) opt->val) = val;
1548 break;
1549
1550 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001551 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 break;
1553
1554 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001555 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 break;
1557
1558 default:
1559 memcpy(opt->val, (void *) val, len);
1560 break;
1561 }
1562
1563 *ptr += L2CAP_CONF_OPT_SIZE + len;
1564}
1565
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001566static void l2cap_ack_timeout(unsigned long arg)
1567{
1568 struct sock *sk = (void *) arg;
1569
1570 bh_lock_sock(sk);
1571 l2cap_send_ack(l2cap_pi(sk));
1572 bh_unlock_sock(sk);
1573}
1574
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001575static inline void l2cap_ertm_init(struct sock *sk)
1576{
1577 l2cap_pi(sk)->expected_ack_seq = 0;
1578 l2cap_pi(sk)->unacked_frames = 0;
1579 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03001580 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001581 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001582
1583 setup_timer(&l2cap_pi(sk)->retrans_timer,
1584 l2cap_retrans_timeout, (unsigned long) sk);
1585 setup_timer(&l2cap_pi(sk)->monitor_timer,
1586 l2cap_monitor_timeout, (unsigned long) sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001587 setup_timer(&l2cap_pi(sk)->ack_timer,
1588 l2cap_ack_timeout, (unsigned long) sk);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001589
1590 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001591 __skb_queue_head_init(BUSY_QUEUE(sk));
1592
1593 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001594
1595 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001596}
1597
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001598static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1599{
1600 switch (mode) {
1601 case L2CAP_MODE_STREAMING:
1602 case L2CAP_MODE_ERTM:
1603 if (l2cap_mode_supported(mode, remote_feat_mask))
1604 return mode;
1605 /* fall through */
1606 default:
1607 return L2CAP_MODE_BASIC;
1608 }
1609}
1610
Gustavo F. Padovan68983252011-02-04 03:02:31 -02001611int l2cap_build_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612{
1613 struct l2cap_pinfo *pi = l2cap_pi(sk);
1614 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001615 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 void *ptr = req->data;
1617
1618 BT_DBG("sk %p", sk);
1619
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001620 if (pi->num_conf_req || pi->num_conf_rsp)
1621 goto done;
1622
1623 switch (pi->mode) {
1624 case L2CAP_MODE_STREAMING:
1625 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001626 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001627 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001628
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001629 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001630 default:
1631 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1632 break;
1633 }
1634
1635done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001636 if (pi->imtu != L2CAP_DEFAULT_MTU)
1637 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1638
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001639 switch (pi->mode) {
1640 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001641 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1642 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1643 break;
1644
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001645 rfc.mode = L2CAP_MODE_BASIC;
1646 rfc.txwin_size = 0;
1647 rfc.max_transmit = 0;
1648 rfc.retrans_timeout = 0;
1649 rfc.monitor_timeout = 0;
1650 rfc.max_pdu_size = 0;
1651
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001652 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1653 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001654 break;
1655
1656 case L2CAP_MODE_ERTM:
1657 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001658 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001659 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001660 rfc.retrans_timeout = 0;
1661 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001662 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001663 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001664 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001665
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001666 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1667 (unsigned long) &rfc);
1668
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001669 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1670 break;
1671
1672 if (pi->fcs == L2CAP_FCS_NONE ||
1673 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1674 pi->fcs = L2CAP_FCS_NONE;
1675 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1676 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001677 break;
1678
1679 case L2CAP_MODE_STREAMING:
1680 rfc.mode = L2CAP_MODE_STREAMING;
1681 rfc.txwin_size = 0;
1682 rfc.max_transmit = 0;
1683 rfc.retrans_timeout = 0;
1684 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001685 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001686 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001687 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001688
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001689 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1690 (unsigned long) &rfc);
1691
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001692 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1693 break;
1694
1695 if (pi->fcs == L2CAP_FCS_NONE ||
1696 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1697 pi->fcs = L2CAP_FCS_NONE;
1698 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1699 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001700 break;
1701 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001703 req->dcid = cpu_to_le16(pi->dcid);
1704 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705
1706 return ptr - data;
1707}
1708
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001709static int l2cap_parse_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710{
1711 struct l2cap_pinfo *pi = l2cap_pi(sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001712 struct l2cap_conf_rsp *rsp = data;
1713 void *ptr = rsp->data;
1714 void *req = pi->conf_req;
1715 int len = pi->conf_len;
1716 int type, hint, olen;
1717 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001718 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001719 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001720 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001722 BT_DBG("sk %p", sk);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001723
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001724 while (len >= L2CAP_CONF_OPT_SIZE) {
1725 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001727 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001728 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001729
1730 switch (type) {
1731 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001732 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001733 break;
1734
1735 case L2CAP_CONF_FLUSH_TO:
1736 pi->flush_to = val;
1737 break;
1738
1739 case L2CAP_CONF_QOS:
1740 break;
1741
Marcel Holtmann6464f352007-10-20 13:39:51 +02001742 case L2CAP_CONF_RFC:
1743 if (olen == sizeof(rfc))
1744 memcpy(&rfc, (void *) val, olen);
1745 break;
1746
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001747 case L2CAP_CONF_FCS:
1748 if (val == L2CAP_FCS_NONE)
1749 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1750
1751 break;
1752
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001753 default:
1754 if (hint)
1755 break;
1756
1757 result = L2CAP_CONF_UNKNOWN;
1758 *((u8 *) ptr++) = type;
1759 break;
1760 }
1761 }
1762
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001763 if (pi->num_conf_rsp || pi->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001764 goto done;
1765
1766 switch (pi->mode) {
1767 case L2CAP_MODE_STREAMING:
1768 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001769 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1770 pi->mode = l2cap_select_mode(rfc.mode,
1771 pi->conn->feat_mask);
1772 break;
1773 }
1774
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001775 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001776 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001777
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001778 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001779 }
1780
1781done:
1782 if (pi->mode != rfc.mode) {
1783 result = L2CAP_CONF_UNACCEPT;
1784 rfc.mode = pi->mode;
1785
1786 if (pi->num_conf_rsp == 1)
1787 return -ECONNREFUSED;
1788
1789 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1790 sizeof(rfc), (unsigned long) &rfc);
1791 }
1792
1793
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001794 if (result == L2CAP_CONF_SUCCESS) {
1795 /* Configure output options and let the other side know
1796 * which ones we don't like. */
1797
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001798 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1799 result = L2CAP_CONF_UNACCEPT;
1800 else {
1801 pi->omtu = mtu;
1802 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1803 }
1804 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001805
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001806 switch (rfc.mode) {
1807 case L2CAP_MODE_BASIC:
1808 pi->fcs = L2CAP_FCS_NONE;
1809 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1810 break;
1811
1812 case L2CAP_MODE_ERTM:
1813 pi->remote_tx_win = rfc.txwin_size;
1814 pi->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001815
1816 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1817 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001818
1819 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001820
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001821 rfc.retrans_timeout =
1822 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1823 rfc.monitor_timeout =
1824 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001825
1826 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001827
1828 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1829 sizeof(rfc), (unsigned long) &rfc);
1830
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001831 break;
1832
1833 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001834 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1835 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001836
1837 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001838
1839 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001840
1841 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1842 sizeof(rfc), (unsigned long) &rfc);
1843
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001844 break;
1845
1846 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001847 result = L2CAP_CONF_UNACCEPT;
1848
1849 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001850 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001851 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001852
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001853 if (result == L2CAP_CONF_SUCCESS)
1854 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1855 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001856 rsp->scid = cpu_to_le16(pi->dcid);
1857 rsp->result = cpu_to_le16(result);
1858 rsp->flags = cpu_to_le16(0x0000);
1859
1860 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861}
1862
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001863static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1864{
1865 struct l2cap_pinfo *pi = l2cap_pi(sk);
1866 struct l2cap_conf_req *req = data;
1867 void *ptr = req->data;
1868 int type, olen;
1869 unsigned long val;
1870 struct l2cap_conf_rfc rfc;
1871
1872 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1873
1874 while (len >= L2CAP_CONF_OPT_SIZE) {
1875 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1876
1877 switch (type) {
1878 case L2CAP_CONF_MTU:
1879 if (val < L2CAP_DEFAULT_MIN_MTU) {
1880 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001881 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001882 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001883 pi->imtu = val;
1884 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001885 break;
1886
1887 case L2CAP_CONF_FLUSH_TO:
1888 pi->flush_to = val;
1889 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1890 2, pi->flush_to);
1891 break;
1892
1893 case L2CAP_CONF_RFC:
1894 if (olen == sizeof(rfc))
1895 memcpy(&rfc, (void *)val, olen);
1896
1897 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1898 rfc.mode != pi->mode)
1899 return -ECONNREFUSED;
1900
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001901 pi->fcs = 0;
1902
1903 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1904 sizeof(rfc), (unsigned long) &rfc);
1905 break;
1906 }
1907 }
1908
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001909 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1910 return -ECONNREFUSED;
1911
1912 pi->mode = rfc.mode;
1913
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001914 if (*result == L2CAP_CONF_SUCCESS) {
1915 switch (rfc.mode) {
1916 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001917 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1918 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001919 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001920 break;
1921 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001922 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001923 }
1924 }
1925
1926 req->dcid = cpu_to_le16(pi->dcid);
1927 req->flags = cpu_to_le16(0x0000);
1928
1929 return ptr - data;
1930}
1931
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001932static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933{
1934 struct l2cap_conf_rsp *rsp = data;
1935 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001937 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001939 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001940 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001941 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942
1943 return ptr - data;
1944}
1945
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001946static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1947{
1948 struct l2cap_pinfo *pi = l2cap_pi(sk);
1949 int type, olen;
1950 unsigned long val;
1951 struct l2cap_conf_rfc rfc;
1952
1953 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1954
1955 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1956 return;
1957
1958 while (len >= L2CAP_CONF_OPT_SIZE) {
1959 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1960
1961 switch (type) {
1962 case L2CAP_CONF_RFC:
1963 if (olen == sizeof(rfc))
1964 memcpy(&rfc, (void *)val, olen);
1965 goto done;
1966 }
1967 }
1968
1969done:
1970 switch (rfc.mode) {
1971 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001972 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1973 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001974 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1975 break;
1976 case L2CAP_MODE_STREAMING:
1977 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1978 }
1979}
1980
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001981static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1982{
1983 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
1984
1985 if (rej->reason != 0x0000)
1986 return 0;
1987
1988 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
1989 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001990 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01001991
1992 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01001993 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01001994
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001995 l2cap_conn_start(conn);
1996 }
1997
1998 return 0;
1999}
2000
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2002{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2004 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002005 struct l2cap_chan *chan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002006 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002007 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008
2009 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002010 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011
2012 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2013
2014 /* Check if we have socket listening on psm */
2015 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2016 if (!parent) {
2017 result = L2CAP_CR_BAD_PSM;
2018 goto sendresp;
2019 }
2020
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002021 bh_lock_sock(parent);
2022
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002023 /* Check if the ACL is secure enough (if not SDP) */
2024 if (psm != cpu_to_le16(0x0001) &&
2025 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002026 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002027 result = L2CAP_CR_SEC_BLOCK;
2028 goto response;
2029 }
2030
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 result = L2CAP_CR_NO_MEM;
2032
2033 /* Check for backlog size */
2034 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002035 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 goto response;
2037 }
2038
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002039 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 if (!sk)
2041 goto response;
2042
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002043 chan = l2cap_chan_alloc(sk);
2044 if (!chan) {
2045 l2cap_sock_kill(sk);
2046 goto response;
2047 }
2048
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002049 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050
2051 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002052 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2053 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054 sock_set_flag(sk, SOCK_ZAPPED);
2055 l2cap_sock_kill(sk);
2056 goto response;
2057 }
2058
2059 hci_conn_hold(conn->hcon);
2060
2061 l2cap_sock_init(sk, parent);
2062 bacpy(&bt_sk(sk)->src, conn->src);
2063 bacpy(&bt_sk(sk)->dst, conn->dst);
2064 l2cap_pi(sk)->psm = psm;
2065 l2cap_pi(sk)->dcid = scid;
2066
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002067 bt_accept_enqueue(parent, sk);
2068
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002069 __l2cap_chan_add(conn, chan);
2070
2071 l2cap_pi(sk)->chan = chan;
2072
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073 dcid = l2cap_pi(sk)->scid;
2074
2075 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2076
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 l2cap_pi(sk)->ident = cmd->ident;
2078
Marcel Holtmann984947d2009-02-06 23:35:19 +01002079 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002080 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002081 if (bt_sk(sk)->defer_setup) {
2082 sk->sk_state = BT_CONNECT2;
2083 result = L2CAP_CR_PEND;
2084 status = L2CAP_CS_AUTHOR_PEND;
2085 parent->sk_data_ready(parent, 0);
2086 } else {
2087 sk->sk_state = BT_CONFIG;
2088 result = L2CAP_CR_SUCCESS;
2089 status = L2CAP_CS_NO_INFO;
2090 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002091 } else {
2092 sk->sk_state = BT_CONNECT2;
2093 result = L2CAP_CR_PEND;
2094 status = L2CAP_CS_AUTHEN_PEND;
2095 }
2096 } else {
2097 sk->sk_state = BT_CONNECT2;
2098 result = L2CAP_CR_PEND;
2099 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 }
2101
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002102 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103
2104response:
2105 bh_unlock_sock(parent);
2106
2107sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002108 rsp.scid = cpu_to_le16(scid);
2109 rsp.dcid = cpu_to_le16(dcid);
2110 rsp.result = cpu_to_le16(result);
2111 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002113
2114 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2115 struct l2cap_info_req info;
2116 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2117
2118 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2119 conn->info_ident = l2cap_get_ident(conn);
2120
2121 mod_timer(&conn->info_timer, jiffies +
2122 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2123
2124 l2cap_send_cmd(conn, conn->info_ident,
2125 L2CAP_INFO_REQ, sizeof(info), &info);
2126 }
2127
Nathan Holsteind793fe82010-10-15 11:54:02 -04002128 if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002129 result == L2CAP_CR_SUCCESS) {
2130 u8 buf[128];
2131 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2132 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2133 l2cap_build_conf_req(sk, buf), buf);
2134 l2cap_pi(sk)->num_conf_req++;
2135 }
2136
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 return 0;
2138}
2139
2140static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2141{
2142 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2143 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002144 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145 struct sock *sk;
2146 u8 req[128];
2147
2148 scid = __le16_to_cpu(rsp->scid);
2149 dcid = __le16_to_cpu(rsp->dcid);
2150 result = __le16_to_cpu(rsp->result);
2151 status = __le16_to_cpu(rsp->status);
2152
2153 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2154
2155 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002156 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002157 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002158 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002160 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002161 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002162 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 }
2164
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002165 sk = chan->sk;
2166
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 switch (result) {
2168 case L2CAP_CR_SUCCESS:
2169 sk->sk_state = BT_CONFIG;
2170 l2cap_pi(sk)->ident = 0;
2171 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002172 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2173
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002174 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2175 break;
2176
2177 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2178
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2180 l2cap_build_conf_req(sk, req), req);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002181 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182 break;
2183
2184 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002185 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186 break;
2187
2188 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002189 /* don't delete l2cap channel if sk is owned by user */
2190 if (sock_owned_by_user(sk)) {
2191 sk->sk_state = BT_DISCONN;
2192 l2cap_sock_clear_timer(sk);
2193 l2cap_sock_set_timer(sk, HZ / 5);
2194 break;
2195 }
2196
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002197 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 break;
2199 }
2200
2201 bh_unlock_sock(sk);
2202 return 0;
2203}
2204
Mat Martineau8c462b62010-08-24 15:35:42 -07002205static inline void set_default_fcs(struct l2cap_pinfo *pi)
2206{
2207 /* FCS is enabled only in ERTM or streaming mode, if one or both
2208 * sides request it.
2209 */
2210 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2211 pi->fcs = L2CAP_FCS_NONE;
2212 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2213 pi->fcs = L2CAP_FCS_CRC16;
2214}
2215
Al Viro88219a02007-07-29 00:17:25 -07002216static 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 -07002217{
2218 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2219 u16 dcid, flags;
2220 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002221 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002223 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224
2225 dcid = __le16_to_cpu(req->dcid);
2226 flags = __le16_to_cpu(req->flags);
2227
2228 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2229
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002230 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002231 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232 return -ENOENT;
2233
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002234 sk = chan->sk;
2235
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002236 if (sk->sk_state != BT_CONFIG) {
2237 struct l2cap_cmd_rej rej;
2238
2239 rej.reason = cpu_to_le16(0x0002);
2240 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2241 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002242 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002243 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002244
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002245 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002246 len = cmd_len - sizeof(*req);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002247 if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
2248 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2249 l2cap_build_conf_rsp(sk, rsp,
2250 L2CAP_CONF_REJECT, flags), rsp);
2251 goto unlock;
2252 }
2253
2254 /* Store config. */
2255 memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
2256 l2cap_pi(sk)->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257
2258 if (flags & 0x0001) {
2259 /* Incomplete config. Send empty response. */
2260 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002261 l2cap_build_conf_rsp(sk, rsp,
2262 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 goto unlock;
2264 }
2265
2266 /* Complete config. */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002267 len = l2cap_parse_conf_req(sk, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002268 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002269 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002271 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002273 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002274 l2cap_pi(sk)->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002275
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002276 /* Reset config buffer. */
2277 l2cap_pi(sk)->conf_len = 0;
2278
Marcel Holtmann876d9482007-10-20 13:35:42 +02002279 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2280 goto unlock;
2281
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002283 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002284
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002286
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002287 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002288 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002289 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002290 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2291 l2cap_ertm_init(sk);
2292
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002294 goto unlock;
2295 }
2296
2297 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002298 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002299 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002301 l2cap_build_conf_req(sk, buf), buf);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002302 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 }
2304
2305unlock:
2306 bh_unlock_sock(sk);
2307 return 0;
2308}
2309
2310static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2311{
2312 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2313 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002314 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002316 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317
2318 scid = __le16_to_cpu(rsp->scid);
2319 flags = __le16_to_cpu(rsp->flags);
2320 result = __le16_to_cpu(rsp->result);
2321
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002322 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2323 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002325 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002326 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 return 0;
2328
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002329 sk = chan->sk;
2330
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331 switch (result) {
2332 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002333 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 break;
2335
2336 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002337 if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002338 char req[64];
2339
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002340 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002341 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002342 goto done;
2343 }
2344
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002345 /* throw out any old stored conf requests */
2346 result = L2CAP_CONF_SUCCESS;
2347 len = l2cap_parse_conf_rsp(sk, rsp->data,
2348 len, req, &result);
2349 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002350 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002351 goto done;
2352 }
2353
2354 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2355 L2CAP_CONF_REQ, len, req);
2356 l2cap_pi(sk)->num_conf_req++;
2357 if (result != L2CAP_CONF_SUCCESS)
2358 goto done;
2359 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 }
2361
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002362 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002363 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002365 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 goto done;
2367 }
2368
2369 if (flags & 0x01)
2370 goto done;
2371
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2373
2374 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002375 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002376
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002378 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002379 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002380 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002381 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2382 l2cap_ertm_init(sk);
2383
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384 l2cap_chan_ready(sk);
2385 }
2386
2387done:
2388 bh_unlock_sock(sk);
2389 return 0;
2390}
2391
2392static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2393{
2394 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2395 struct l2cap_disconn_rsp rsp;
2396 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002397 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 struct sock *sk;
2399
2400 scid = __le16_to_cpu(req->scid);
2401 dcid = __le16_to_cpu(req->dcid);
2402
2403 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2404
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002405 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002406 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407 return 0;
2408
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002409 sk = chan->sk;
2410
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002411 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2412 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2414
2415 sk->sk_shutdown = SHUTDOWN_MASK;
2416
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002417 /* don't delete l2cap channel if sk is owned by user */
2418 if (sock_owned_by_user(sk)) {
2419 sk->sk_state = BT_DISCONN;
2420 l2cap_sock_clear_timer(sk);
2421 l2cap_sock_set_timer(sk, HZ / 5);
2422 bh_unlock_sock(sk);
2423 return 0;
2424 }
2425
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002426 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427 bh_unlock_sock(sk);
2428
2429 l2cap_sock_kill(sk);
2430 return 0;
2431}
2432
2433static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2434{
2435 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2436 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002437 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438 struct sock *sk;
2439
2440 scid = __le16_to_cpu(rsp->scid);
2441 dcid = __le16_to_cpu(rsp->dcid);
2442
2443 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2444
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002445 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002446 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 return 0;
2448
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002449 sk = chan->sk;
2450
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002451 /* don't delete l2cap channel if sk is owned by user */
2452 if (sock_owned_by_user(sk)) {
2453 sk->sk_state = BT_DISCONN;
2454 l2cap_sock_clear_timer(sk);
2455 l2cap_sock_set_timer(sk, HZ / 5);
2456 bh_unlock_sock(sk);
2457 return 0;
2458 }
2459
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002460 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461 bh_unlock_sock(sk);
2462
2463 l2cap_sock_kill(sk);
2464 return 0;
2465}
2466
2467static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2468{
2469 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 u16 type;
2471
2472 type = __le16_to_cpu(req->type);
2473
2474 BT_DBG("type 0x%4.4x", type);
2475
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002476 if (type == L2CAP_IT_FEAT_MASK) {
2477 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002478 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002479 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2480 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2481 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002482 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002483 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2484 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002485 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002486 l2cap_send_cmd(conn, cmd->ident,
2487 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002488 } else if (type == L2CAP_IT_FIXED_CHAN) {
2489 u8 buf[12];
2490 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2491 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2492 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2493 memcpy(buf + 4, l2cap_fixed_chan, 8);
2494 l2cap_send_cmd(conn, cmd->ident,
2495 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002496 } else {
2497 struct l2cap_info_rsp rsp;
2498 rsp.type = cpu_to_le16(type);
2499 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2500 l2cap_send_cmd(conn, cmd->ident,
2501 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2502 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503
2504 return 0;
2505}
2506
2507static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2508{
2509 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2510 u16 type, result;
2511
2512 type = __le16_to_cpu(rsp->type);
2513 result = __le16_to_cpu(rsp->result);
2514
2515 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2516
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002517 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2518 if (cmd->ident != conn->info_ident ||
2519 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2520 return 0;
2521
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002522 del_timer(&conn->info_timer);
2523
Ville Tervoadb08ed2010-08-04 09:43:33 +03002524 if (result != L2CAP_IR_SUCCESS) {
2525 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2526 conn->info_ident = 0;
2527
2528 l2cap_conn_start(conn);
2529
2530 return 0;
2531 }
2532
Marcel Holtmann984947d2009-02-06 23:35:19 +01002533 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002534 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002535
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002536 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002537 struct l2cap_info_req req;
2538 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2539
2540 conn->info_ident = l2cap_get_ident(conn);
2541
2542 l2cap_send_cmd(conn, conn->info_ident,
2543 L2CAP_INFO_REQ, sizeof(req), &req);
2544 } else {
2545 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2546 conn->info_ident = 0;
2547
2548 l2cap_conn_start(conn);
2549 }
2550 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002551 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002552 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002553
2554 l2cap_conn_start(conn);
2555 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002556
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557 return 0;
2558}
2559
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002560static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002561 u16 to_multiplier)
2562{
2563 u16 max_latency;
2564
2565 if (min > max || min < 6 || max > 3200)
2566 return -EINVAL;
2567
2568 if (to_multiplier < 10 || to_multiplier > 3200)
2569 return -EINVAL;
2570
2571 if (max >= to_multiplier * 8)
2572 return -EINVAL;
2573
2574 max_latency = (to_multiplier * 8 / max) - 1;
2575 if (latency > 499 || latency > max_latency)
2576 return -EINVAL;
2577
2578 return 0;
2579}
2580
2581static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2582 struct l2cap_cmd_hdr *cmd, u8 *data)
2583{
2584 struct hci_conn *hcon = conn->hcon;
2585 struct l2cap_conn_param_update_req *req;
2586 struct l2cap_conn_param_update_rsp rsp;
2587 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002588 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002589
2590 if (!(hcon->link_mode & HCI_LM_MASTER))
2591 return -EINVAL;
2592
2593 cmd_len = __le16_to_cpu(cmd->len);
2594 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2595 return -EPROTO;
2596
2597 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002598 min = __le16_to_cpu(req->min);
2599 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002600 latency = __le16_to_cpu(req->latency);
2601 to_multiplier = __le16_to_cpu(req->to_multiplier);
2602
2603 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2604 min, max, latency, to_multiplier);
2605
2606 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002607
2608 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2609 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002610 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2611 else
2612 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2613
2614 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2615 sizeof(rsp), &rsp);
2616
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002617 if (!err)
2618 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2619
Claudio Takahaside731152011-02-11 19:28:55 -02002620 return 0;
2621}
2622
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002623static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2624 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2625{
2626 int err = 0;
2627
2628 switch (cmd->code) {
2629 case L2CAP_COMMAND_REJ:
2630 l2cap_command_rej(conn, cmd, data);
2631 break;
2632
2633 case L2CAP_CONN_REQ:
2634 err = l2cap_connect_req(conn, cmd, data);
2635 break;
2636
2637 case L2CAP_CONN_RSP:
2638 err = l2cap_connect_rsp(conn, cmd, data);
2639 break;
2640
2641 case L2CAP_CONF_REQ:
2642 err = l2cap_config_req(conn, cmd, cmd_len, data);
2643 break;
2644
2645 case L2CAP_CONF_RSP:
2646 err = l2cap_config_rsp(conn, cmd, data);
2647 break;
2648
2649 case L2CAP_DISCONN_REQ:
2650 err = l2cap_disconnect_req(conn, cmd, data);
2651 break;
2652
2653 case L2CAP_DISCONN_RSP:
2654 err = l2cap_disconnect_rsp(conn, cmd, data);
2655 break;
2656
2657 case L2CAP_ECHO_REQ:
2658 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2659 break;
2660
2661 case L2CAP_ECHO_RSP:
2662 break;
2663
2664 case L2CAP_INFO_REQ:
2665 err = l2cap_information_req(conn, cmd, data);
2666 break;
2667
2668 case L2CAP_INFO_RSP:
2669 err = l2cap_information_rsp(conn, cmd, data);
2670 break;
2671
2672 default:
2673 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2674 err = -EINVAL;
2675 break;
2676 }
2677
2678 return err;
2679}
2680
2681static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2682 struct l2cap_cmd_hdr *cmd, u8 *data)
2683{
2684 switch (cmd->code) {
2685 case L2CAP_COMMAND_REJ:
2686 return 0;
2687
2688 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002689 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002690
2691 case L2CAP_CONN_PARAM_UPDATE_RSP:
2692 return 0;
2693
2694 default:
2695 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2696 return -EINVAL;
2697 }
2698}
2699
2700static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2701 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702{
2703 u8 *data = skb->data;
2704 int len = skb->len;
2705 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002706 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707
2708 l2cap_raw_recv(conn, skb);
2709
2710 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002711 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2713 data += L2CAP_CMD_HDR_SIZE;
2714 len -= L2CAP_CMD_HDR_SIZE;
2715
Al Viro88219a02007-07-29 00:17:25 -07002716 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717
Al Viro88219a02007-07-29 00:17:25 -07002718 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 -07002719
Al Viro88219a02007-07-29 00:17:25 -07002720 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721 BT_DBG("corrupted command");
2722 break;
2723 }
2724
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002725 if (conn->hcon->type == LE_LINK)
2726 err = l2cap_le_sig_cmd(conn, &cmd, data);
2727 else
2728 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729
2730 if (err) {
2731 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002732
2733 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734
2735 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002736 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2738 }
2739
Al Viro88219a02007-07-29 00:17:25 -07002740 data += cmd_len;
2741 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742 }
2743
2744 kfree_skb(skb);
2745}
2746
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002747static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2748{
2749 u16 our_fcs, rcv_fcs;
2750 int hdr_size = L2CAP_HDR_SIZE + 2;
2751
2752 if (pi->fcs == L2CAP_FCS_CRC16) {
2753 skb_trim(skb, skb->len - 2);
2754 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2755 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2756
2757 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002758 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002759 }
2760 return 0;
2761}
2762
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002763static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
2764{
2765 struct l2cap_pinfo *pi = l2cap_pi(sk);
2766 u16 control = 0;
2767
2768 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002769
2770 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2771
2772 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002773 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002774 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002775 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002776 }
2777
Gustavo F. Padovan4ea727e2010-06-03 16:34:20 -03002778 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
2779 l2cap_retransmit_frames(sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002780
2781 l2cap_ertm_send(sk);
2782
2783 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
2784 pi->frames_sent == 0) {
2785 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002786 l2cap_send_sframe(pi, control);
2787 }
2788}
2789
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002790static 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 -03002791{
2792 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002793 struct l2cap_pinfo *pi = l2cap_pi(sk);
2794 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002795
2796 bt_cb(skb)->tx_seq = tx_seq;
2797 bt_cb(skb)->sar = sar;
2798
2799 next_skb = skb_peek(SREJ_QUEUE(sk));
2800 if (!next_skb) {
2801 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002802 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002803 }
2804
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002805 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
2806 if (tx_seq_offset < 0)
2807 tx_seq_offset += 64;
2808
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002809 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002810 if (bt_cb(next_skb)->tx_seq == tx_seq)
2811 return -EINVAL;
2812
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002813 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
2814 pi->buffer_seq) % 64;
2815 if (next_tx_seq_offset < 0)
2816 next_tx_seq_offset += 64;
2817
2818 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002819 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002820 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002821 }
2822
2823 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
2824 break;
2825
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002826 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002827
2828 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002829
2830 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002831}
2832
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002833static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
2834{
2835 struct l2cap_pinfo *pi = l2cap_pi(sk);
2836 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002837 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002838
2839 switch (control & L2CAP_CTRL_SAR) {
2840 case L2CAP_SDU_UNSEGMENTED:
2841 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2842 goto drop;
2843
2844 err = sock_queue_rcv_skb(sk, skb);
2845 if (!err)
2846 return err;
2847
2848 break;
2849
2850 case L2CAP_SDU_START:
2851 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2852 goto drop;
2853
2854 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002855
2856 if (pi->sdu_len > pi->imtu)
2857 goto disconnect;
2858
2859 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002860 if (!pi->sdu)
2861 return -ENOMEM;
2862
2863 /* pull sdu_len bytes only after alloc, because of Local Busy
2864 * condition we have to be sure that this will be executed
2865 * only once, i.e., when alloc does not fail */
2866 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002867
2868 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2869
2870 pi->conn_state |= L2CAP_CONN_SAR_SDU;
2871 pi->partial_sdu_len = skb->len;
2872 break;
2873
2874 case L2CAP_SDU_CONTINUE:
2875 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2876 goto disconnect;
2877
2878 if (!pi->sdu)
2879 goto disconnect;
2880
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002881 pi->partial_sdu_len += skb->len;
2882 if (pi->partial_sdu_len > pi->sdu_len)
2883 goto drop;
2884
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002885 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2886
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002887 break;
2888
2889 case L2CAP_SDU_END:
2890 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2891 goto disconnect;
2892
2893 if (!pi->sdu)
2894 goto disconnect;
2895
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002896 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002897 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002898
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002899 if (pi->partial_sdu_len > pi->imtu)
2900 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002901
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002902 if (pi->partial_sdu_len != pi->sdu_len)
2903 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002904
2905 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002906 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002907
2908 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002909 if (!_skb) {
2910 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2911 return -ENOMEM;
2912 }
2913
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002914 err = sock_queue_rcv_skb(sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002915 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002916 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002917 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2918 return err;
2919 }
2920
2921 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2922 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002923
2924 kfree_skb(pi->sdu);
2925 break;
2926 }
2927
2928 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002929 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002930
2931drop:
2932 kfree_skb(pi->sdu);
2933 pi->sdu = NULL;
2934
2935disconnect:
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002936 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002937 kfree_skb(skb);
2938 return 0;
2939}
2940
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002941static int l2cap_try_push_rx_skb(struct sock *sk)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002942{
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002943 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002944 struct sk_buff *skb;
2945 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002946 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002947
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002948 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
2949 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
2950 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
2951 if (err < 0) {
2952 skb_queue_head(BUSY_QUEUE(sk), skb);
2953 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002954 }
2955
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002956 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002957 }
2958
2959 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
2960 goto done;
2961
2962 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2963 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
2964 l2cap_send_sframe(pi, control);
2965 l2cap_pi(sk)->retry_count = 1;
2966
2967 del_timer(&pi->retrans_timer);
2968 __mod_monitor_timer();
2969
2970 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
2971
2972done:
2973 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2974 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
2975
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002976 BT_DBG("sk %p, Exit local busy", sk);
2977
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002978 return 0;
2979}
2980
2981static void l2cap_busy_work(struct work_struct *work)
2982{
2983 DECLARE_WAITQUEUE(wait, current);
2984 struct l2cap_pinfo *pi =
2985 container_of(work, struct l2cap_pinfo, busy_work);
2986 struct sock *sk = (struct sock *)pi;
2987 int n_tries = 0, timeo = HZ/5, err;
2988 struct sk_buff *skb;
2989
2990 lock_sock(sk);
2991
2992 add_wait_queue(sk_sleep(sk), &wait);
2993 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
2994 set_current_state(TASK_INTERRUPTIBLE);
2995
2996 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
2997 err = -EBUSY;
2998 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
2999 break;
3000 }
3001
3002 if (!timeo)
3003 timeo = HZ/5;
3004
3005 if (signal_pending(current)) {
3006 err = sock_intr_errno(timeo);
3007 break;
3008 }
3009
3010 release_sock(sk);
3011 timeo = schedule_timeout(timeo);
3012 lock_sock(sk);
3013
3014 err = sock_error(sk);
3015 if (err)
3016 break;
3017
3018 if (l2cap_try_push_rx_skb(sk) == 0)
3019 break;
3020 }
3021
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003022 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003023 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003024
3025 release_sock(sk);
3026}
3027
3028static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
3029{
3030 struct l2cap_pinfo *pi = l2cap_pi(sk);
3031 int sctrl, err;
3032
3033 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
3034 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3035 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003036 return l2cap_try_push_rx_skb(sk);
3037
3038
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003039 }
3040
3041 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3042 if (err >= 0) {
3043 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3044 return err;
3045 }
3046
3047 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003048 BT_DBG("sk %p, Enter local busy", sk);
3049
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003050 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
3051 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3052 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3053
3054 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3055 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
3056 l2cap_send_sframe(pi, sctrl);
3057
3058 pi->conn_state |= L2CAP_CONN_RNR_SENT;
3059
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003060 del_timer(&pi->ack_timer);
3061
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003062 queue_work(_busy_wq, &pi->busy_work);
3063
3064 return err;
3065}
3066
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003067static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003068{
3069 struct l2cap_pinfo *pi = l2cap_pi(sk);
3070 struct sk_buff *_skb;
3071 int err = -EINVAL;
3072
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003073 /*
3074 * TODO: We have to notify the userland if some data is lost with the
3075 * Streaming Mode.
3076 */
3077
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003078 switch (control & L2CAP_CTRL_SAR) {
3079 case L2CAP_SDU_UNSEGMENTED:
3080 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3081 kfree_skb(pi->sdu);
3082 break;
3083 }
3084
3085 err = sock_queue_rcv_skb(sk, skb);
3086 if (!err)
3087 return 0;
3088
3089 break;
3090
3091 case L2CAP_SDU_START:
3092 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3093 kfree_skb(pi->sdu);
3094 break;
3095 }
3096
3097 pi->sdu_len = get_unaligned_le16(skb->data);
3098 skb_pull(skb, 2);
3099
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003100 if (pi->sdu_len > pi->imtu) {
3101 err = -EMSGSIZE;
3102 break;
3103 }
3104
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003105 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3106 if (!pi->sdu) {
3107 err = -ENOMEM;
3108 break;
3109 }
3110
3111 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3112
3113 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3114 pi->partial_sdu_len = skb->len;
3115 err = 0;
3116 break;
3117
3118 case L2CAP_SDU_CONTINUE:
3119 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3120 break;
3121
3122 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3123
3124 pi->partial_sdu_len += skb->len;
3125 if (pi->partial_sdu_len > pi->sdu_len)
3126 kfree_skb(pi->sdu);
3127 else
3128 err = 0;
3129
3130 break;
3131
3132 case L2CAP_SDU_END:
3133 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3134 break;
3135
3136 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3137
3138 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
3139 pi->partial_sdu_len += skb->len;
3140
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003141 if (pi->partial_sdu_len > pi->imtu)
3142 goto drop;
3143
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003144 if (pi->partial_sdu_len == pi->sdu_len) {
3145 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
3146 err = sock_queue_rcv_skb(sk, _skb);
3147 if (err < 0)
3148 kfree_skb(_skb);
3149 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003150 err = 0;
3151
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003152drop:
3153 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003154 break;
3155 }
3156
3157 kfree_skb(skb);
3158 return err;
3159}
3160
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003161static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
3162{
3163 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003164 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003165
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003166 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003167 if (bt_cb(skb)->tx_seq != tx_seq)
3168 break;
3169
3170 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003171 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003172 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003173 l2cap_pi(sk)->buffer_seq_srej =
3174 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003175 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003176 }
3177}
3178
3179static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
3180{
3181 struct l2cap_pinfo *pi = l2cap_pi(sk);
3182 struct srej_list *l, *tmp;
3183 u16 control;
3184
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003185 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003186 if (l->tx_seq == tx_seq) {
3187 list_del(&l->list);
3188 kfree(l);
3189 return;
3190 }
3191 control = L2CAP_SUPER_SELECT_REJECT;
3192 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3193 l2cap_send_sframe(pi, control);
3194 list_del(&l->list);
3195 list_add_tail(&l->list, SREJ_LIST(sk));
3196 }
3197}
3198
3199static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3200{
3201 struct l2cap_pinfo *pi = l2cap_pi(sk);
3202 struct srej_list *new;
3203 u16 control;
3204
3205 while (tx_seq != pi->expected_tx_seq) {
3206 control = L2CAP_SUPER_SELECT_REJECT;
3207 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3208 l2cap_send_sframe(pi, control);
3209
3210 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003211 new->tx_seq = pi->expected_tx_seq;
3212 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003213 list_add_tail(&new->list, SREJ_LIST(sk));
3214 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003215 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003216}
3217
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003218static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3219{
3220 struct l2cap_pinfo *pi = l2cap_pi(sk);
3221 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003222 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003223 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003224 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003225 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003226 int err = 0;
3227
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003228 BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
3229 rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003230
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003231 if (L2CAP_CTRL_FINAL & rx_control &&
3232 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003233 del_timer(&pi->monitor_timer);
3234 if (pi->unacked_frames > 0)
3235 __mod_retrans_timer();
3236 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
3237 }
3238
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003239 pi->expected_ack_seq = req_seq;
3240 l2cap_drop_acked_frames(sk);
3241
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003242 if (tx_seq == pi->expected_tx_seq)
3243 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003244
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003245 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3246 if (tx_seq_offset < 0)
3247 tx_seq_offset += 64;
3248
3249 /* invalid tx_seq */
3250 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003251 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003252 goto drop;
3253 }
3254
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003255 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
3256 goto drop;
3257
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003258 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3259 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003260
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003261 first = list_first_entry(SREJ_LIST(sk),
3262 struct srej_list, list);
3263 if (tx_seq == first->tx_seq) {
3264 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3265 l2cap_check_srej_gap(sk, tx_seq);
3266
3267 list_del(&first->list);
3268 kfree(first);
3269
3270 if (list_empty(SREJ_LIST(sk))) {
3271 pi->buffer_seq = pi->buffer_seq_srej;
3272 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666cc2010-05-01 16:15:40 -03003273 l2cap_send_ack(pi);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003274 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003275 }
3276 } else {
3277 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003278
3279 /* duplicated tx_seq */
3280 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
3281 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003282
3283 list_for_each_entry(l, SREJ_LIST(sk), list) {
3284 if (l->tx_seq == tx_seq) {
3285 l2cap_resend_srejframe(sk, tx_seq);
3286 return 0;
3287 }
3288 }
3289 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003290 }
3291 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003292 expected_tx_seq_offset =
3293 (pi->expected_tx_seq - pi->buffer_seq) % 64;
3294 if (expected_tx_seq_offset < 0)
3295 expected_tx_seq_offset += 64;
3296
3297 /* duplicated tx_seq */
3298 if (tx_seq_offset < expected_tx_seq_offset)
3299 goto drop;
3300
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003301 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003302
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003303 BT_DBG("sk %p, Enter SREJ", sk);
3304
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003305 INIT_LIST_HEAD(SREJ_LIST(sk));
3306 pi->buffer_seq_srej = pi->buffer_seq;
3307
3308 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003309 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003310 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3311
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003312 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
3313
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003314 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003315
3316 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003317 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003318 return 0;
3319
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003320expected:
3321 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3322
3323 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003324 bt_cb(skb)->tx_seq = tx_seq;
3325 bt_cb(skb)->sar = sar;
3326 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003327 return 0;
3328 }
3329
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003330 err = l2cap_push_rx_skb(sk, skb, rx_control);
3331 if (err < 0)
3332 return 0;
3333
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003334 if (rx_control & L2CAP_CTRL_FINAL) {
3335 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3336 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003337 else
3338 l2cap_retransmit_frames(sk);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003339 }
3340
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003341 __mod_ack_timer();
3342
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003343 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
3344 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003345 l2cap_send_ack(pi);
3346
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003347 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003348
3349drop:
3350 kfree_skb(skb);
3351 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003352}
3353
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003354static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003355{
3356 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003357
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003358 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3359 rx_control);
3360
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003361 pi->expected_ack_seq = __get_reqseq(rx_control);
3362 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003363
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003364 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003365 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003366 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3367 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3368 (pi->unacked_frames > 0))
3369 __mod_retrans_timer();
3370
3371 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3372 l2cap_send_srejtail(sk);
3373 } else {
3374 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003375 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003376
3377 } else if (rx_control & L2CAP_CTRL_FINAL) {
3378 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003379
3380 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3381 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003382 else
3383 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003384
3385 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003386 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3387 (pi->unacked_frames > 0))
3388 __mod_retrans_timer();
3389
3390 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003391 if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003392 l2cap_send_ack(pi);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003393 else
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003394 l2cap_ertm_send(sk);
3395 }
3396}
3397
3398static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
3399{
3400 struct l2cap_pinfo *pi = l2cap_pi(sk);
3401 u8 tx_seq = __get_reqseq(rx_control);
3402
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003403 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3404
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003405 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3406
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03003407 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003408 l2cap_drop_acked_frames(sk);
3409
3410 if (rx_control & L2CAP_CTRL_FINAL) {
3411 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3412 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003413 else
3414 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003415 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003416 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003417
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03003418 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003419 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003420 }
3421}
3422static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
3423{
3424 struct l2cap_pinfo *pi = l2cap_pi(sk);
3425 u8 tx_seq = __get_reqseq(rx_control);
3426
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003427 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3428
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003429 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3430
3431 if (rx_control & L2CAP_CTRL_POLL) {
3432 pi->expected_ack_seq = tx_seq;
3433 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003434
3435 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003436 l2cap_retransmit_one_frame(sk, tx_seq);
3437
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003438 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003439
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003440 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3441 pi->srej_save_reqseq = tx_seq;
3442 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3443 }
3444 } else if (rx_control & L2CAP_CTRL_FINAL) {
3445 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
3446 pi->srej_save_reqseq == tx_seq)
3447 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
3448 else
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003449 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003450 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003451 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003452 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3453 pi->srej_save_reqseq = tx_seq;
3454 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3455 }
3456 }
3457}
3458
3459static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
3460{
3461 struct l2cap_pinfo *pi = l2cap_pi(sk);
3462 u8 tx_seq = __get_reqseq(rx_control);
3463
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003464 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3465
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003466 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
3467 pi->expected_ack_seq = tx_seq;
3468 l2cap_drop_acked_frames(sk);
3469
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003470 if (rx_control & L2CAP_CTRL_POLL)
3471 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
3472
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003473 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
3474 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003475 if (rx_control & L2CAP_CTRL_POLL)
3476 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003477 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003478 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003479
3480 if (rx_control & L2CAP_CTRL_POLL)
3481 l2cap_send_srejtail(sk);
3482 else
3483 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003484}
3485
3486static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3487{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003488 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3489
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003490 if (L2CAP_CTRL_FINAL & rx_control &&
3491 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003492 del_timer(&l2cap_pi(sk)->monitor_timer);
3493 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003494 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003495 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003496 }
3497
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003498 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3499 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003500 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003501 break;
3502
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003503 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003504 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003505 break;
3506
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003507 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003508 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003509 break;
3510
3511 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003512 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003513 break;
3514 }
3515
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003516 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003517 return 0;
3518}
3519
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003520static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3521{
3522 struct l2cap_pinfo *pi = l2cap_pi(sk);
3523 u16 control;
3524 u8 req_seq;
3525 int len, next_tx_seq_offset, req_seq_offset;
3526
3527 control = get_unaligned_le16(skb->data);
3528 skb_pull(skb, 2);
3529 len = skb->len;
3530
3531 /*
3532 * We can just drop the corrupted I-frame here.
3533 * Receiver will miss it and start proper recovery
3534 * procedures and ask retransmission.
3535 */
3536 if (l2cap_check_fcs(pi, skb))
3537 goto drop;
3538
3539 if (__is_sar_start(control) && __is_iframe(control))
3540 len -= 2;
3541
3542 if (pi->fcs == L2CAP_FCS_CRC16)
3543 len -= 2;
3544
3545 if (len > pi->mps) {
3546 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3547 goto drop;
3548 }
3549
3550 req_seq = __get_reqseq(control);
3551 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
3552 if (req_seq_offset < 0)
3553 req_seq_offset += 64;
3554
3555 next_tx_seq_offset =
3556 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
3557 if (next_tx_seq_offset < 0)
3558 next_tx_seq_offset += 64;
3559
3560 /* check for invalid req-seq */
3561 if (req_seq_offset > next_tx_seq_offset) {
3562 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3563 goto drop;
3564 }
3565
3566 if (__is_iframe(control)) {
3567 if (len < 0) {
3568 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3569 goto drop;
3570 }
3571
3572 l2cap_data_channel_iframe(sk, control, skb);
3573 } else {
3574 if (len != 0) {
3575 BT_ERR("%d", len);
3576 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3577 goto drop;
3578 }
3579
3580 l2cap_data_channel_sframe(sk, control, skb);
3581 }
3582
3583 return 0;
3584
3585drop:
3586 kfree_skb(skb);
3587 return 0;
3588}
3589
Linus Torvalds1da177e2005-04-16 15:20:36 -07003590static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3591{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003592 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003593 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003594 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003595 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003596 u8 tx_seq;
3597 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003598
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003599 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003600 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601 BT_DBG("unknown cid 0x%4.4x", cid);
3602 goto drop;
3603 }
3604
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003605 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003606 pi = l2cap_pi(sk);
3607
Linus Torvalds1da177e2005-04-16 15:20:36 -07003608 BT_DBG("sk %p, len %d", sk, skb->len);
3609
3610 if (sk->sk_state != BT_CONNECTED)
3611 goto drop;
3612
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003613 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003614 case L2CAP_MODE_BASIC:
3615 /* If socket recv buffers overflows we drop data here
3616 * which is *bad* because L2CAP has to be reliable.
3617 * But we don't have any other choice. L2CAP doesn't
3618 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003620 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003621 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003623 if (!sock_queue_rcv_skb(sk, skb))
3624 goto done;
3625 break;
3626
3627 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003628 if (!sock_owned_by_user(sk)) {
3629 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003630 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003631 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003632 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003633 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003634
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003635 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003636
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003637 case L2CAP_MODE_STREAMING:
3638 control = get_unaligned_le16(skb->data);
3639 skb_pull(skb, 2);
3640 len = skb->len;
3641
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003642 if (l2cap_check_fcs(pi, skb))
3643 goto drop;
3644
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003645 if (__is_sar_start(control))
3646 len -= 2;
3647
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003648 if (pi->fcs == L2CAP_FCS_CRC16)
3649 len -= 2;
3650
Nathan Holstein51893f82010-06-09 15:46:25 -04003651 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003652 goto drop;
3653
3654 tx_seq = __get_txseq(control);
3655
3656 if (pi->expected_tx_seq == tx_seq)
3657 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3658 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03003659 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003660
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003661 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003662
3663 goto done;
3664
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003665 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003666 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003667 break;
3668 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669
3670drop:
3671 kfree_skb(skb);
3672
3673done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003674 if (sk)
3675 bh_unlock_sock(sk);
3676
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677 return 0;
3678}
3679
Al Viro8e036fc2007-07-29 00:16:36 -07003680static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681{
3682 struct sock *sk;
3683
3684 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3685 if (!sk)
3686 goto drop;
3687
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003688 bh_lock_sock(sk);
3689
Linus Torvalds1da177e2005-04-16 15:20:36 -07003690 BT_DBG("sk %p, len %d", sk, skb->len);
3691
3692 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3693 goto drop;
3694
3695 if (l2cap_pi(sk)->imtu < skb->len)
3696 goto drop;
3697
3698 if (!sock_queue_rcv_skb(sk, skb))
3699 goto done;
3700
3701drop:
3702 kfree_skb(skb);
3703
3704done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003705 if (sk)
3706 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707 return 0;
3708}
3709
3710static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3711{
3712 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003713 u16 cid, len;
3714 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715
3716 skb_pull(skb, L2CAP_HDR_SIZE);
3717 cid = __le16_to_cpu(lh->cid);
3718 len = __le16_to_cpu(lh->len);
3719
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003720 if (len != skb->len) {
3721 kfree_skb(skb);
3722 return;
3723 }
3724
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3726
3727 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003728 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003729 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730 l2cap_sig_channel(conn, skb);
3731 break;
3732
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003733 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003734 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735 skb_pull(skb, 2);
3736 l2cap_conless_channel(conn, psm, skb);
3737 break;
3738
3739 default:
3740 l2cap_data_channel(conn, cid, skb);
3741 break;
3742 }
3743}
3744
3745/* ---- L2CAP interface with lower layer (HCI) ---- */
3746
3747static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3748{
3749 int exact = 0, lm1 = 0, lm2 = 0;
3750 register struct sock *sk;
3751 struct hlist_node *node;
3752
3753 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003754 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755
3756 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3757
3758 /* Find listening sockets and check their link_mode */
3759 read_lock(&l2cap_sk_list.lock);
3760 sk_for_each(sk, node, &l2cap_sk_list.head) {
3761 if (sk->sk_state != BT_LISTEN)
3762 continue;
3763
3764 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003765 lm1 |= HCI_LM_ACCEPT;
3766 if (l2cap_pi(sk)->role_switch)
3767 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003769 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3770 lm2 |= HCI_LM_ACCEPT;
3771 if (l2cap_pi(sk)->role_switch)
3772 lm2 |= HCI_LM_MASTER;
3773 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003774 }
3775 read_unlock(&l2cap_sk_list.lock);
3776
3777 return exact ? lm1 : lm2;
3778}
3779
3780static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3781{
Marcel Holtmann01394182006-07-03 10:02:46 +02003782 struct l2cap_conn *conn;
3783
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3785
Ville Tervoacd7d372011-02-10 22:38:49 -03003786 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003787 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003788
3789 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790 conn = l2cap_conn_add(hcon, status);
3791 if (conn)
3792 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003793 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794 l2cap_conn_del(hcon, bt_err(status));
3795
3796 return 0;
3797}
3798
Marcel Holtmann2950f212009-02-12 14:02:50 +01003799static int l2cap_disconn_ind(struct hci_conn *hcon)
3800{
3801 struct l2cap_conn *conn = hcon->l2cap_data;
3802
3803 BT_DBG("hcon %p", hcon);
3804
3805 if (hcon->type != ACL_LINK || !conn)
3806 return 0x13;
3807
3808 return conn->disc_reason;
3809}
3810
3811static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812{
3813 BT_DBG("hcon %p reason %d", hcon, reason);
3814
Ville Tervoacd7d372011-02-10 22:38:49 -03003815 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003816 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817
3818 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003819
Linus Torvalds1da177e2005-04-16 15:20:36 -07003820 return 0;
3821}
3822
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003823static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3824{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003825 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003826 return;
3827
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003828 if (encrypt == 0x00) {
3829 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3830 l2cap_sock_clear_timer(sk);
3831 l2cap_sock_set_timer(sk, HZ * 5);
3832 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3833 __l2cap_sock_close(sk, ECONNREFUSED);
3834 } else {
3835 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3836 l2cap_sock_clear_timer(sk);
3837 }
3838}
3839
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003840static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003842 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003843 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844
Marcel Holtmann01394182006-07-03 10:02:46 +02003845 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003847
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848 BT_DBG("conn %p", conn);
3849
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003850 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003852 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003853 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003854
Linus Torvalds1da177e2005-04-16 15:20:36 -07003855 bh_lock_sock(sk);
3856
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003857 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3858 bh_unlock_sock(sk);
3859 continue;
3860 }
3861
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003862 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003863 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003864 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003865 bh_unlock_sock(sk);
3866 continue;
3867 }
3868
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003869 if (sk->sk_state == BT_CONNECT) {
3870 if (!status) {
3871 struct l2cap_conn_req req;
3872 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3873 req.psm = l2cap_pi(sk)->psm;
3874
3875 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003876 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003877
3878 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3879 L2CAP_CONN_REQ, sizeof(req), &req);
3880 } else {
3881 l2cap_sock_clear_timer(sk);
3882 l2cap_sock_set_timer(sk, HZ / 10);
3883 }
3884 } else if (sk->sk_state == BT_CONNECT2) {
3885 struct l2cap_conn_rsp rsp;
3886 __u16 result;
3887
3888 if (!status) {
3889 sk->sk_state = BT_CONFIG;
3890 result = L2CAP_CR_SUCCESS;
3891 } else {
3892 sk->sk_state = BT_DISCONN;
3893 l2cap_sock_set_timer(sk, HZ / 10);
3894 result = L2CAP_CR_SEC_BLOCK;
3895 }
3896
3897 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3898 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3899 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003900 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003901 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3902 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903 }
3904
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905 bh_unlock_sock(sk);
3906 }
3907
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003908 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003909
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910 return 0;
3911}
3912
3913static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3914{
3915 struct l2cap_conn *conn = hcon->l2cap_data;
3916
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003917 if (!conn)
3918 conn = l2cap_conn_add(hcon, 0);
3919
3920 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921 goto drop;
3922
3923 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3924
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003925 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003927 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003928 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929 int len;
3930
3931 if (conn->rx_len) {
3932 BT_ERR("Unexpected start frame (len %d)", skb->len);
3933 kfree_skb(conn->rx_skb);
3934 conn->rx_skb = NULL;
3935 conn->rx_len = 0;
3936 l2cap_conn_unreliable(conn, ECOMM);
3937 }
3938
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003939 /* Start fragment always begin with Basic L2CAP header */
3940 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941 BT_ERR("Frame is too short (len %d)", skb->len);
3942 l2cap_conn_unreliable(conn, ECOMM);
3943 goto drop;
3944 }
3945
3946 hdr = (struct l2cap_hdr *) skb->data;
3947 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003948 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949
3950 if (len == skb->len) {
3951 /* Complete frame received */
3952 l2cap_recv_frame(conn, skb);
3953 return 0;
3954 }
3955
3956 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3957
3958 if (skb->len > len) {
3959 BT_ERR("Frame is too long (len %d, expected len %d)",
3960 skb->len, len);
3961 l2cap_conn_unreliable(conn, ECOMM);
3962 goto drop;
3963 }
3964
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003965 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003966
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003967 if (chan && chan->sk) {
3968 struct sock *sk = chan->sk;
3969
3970 if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
3971 BT_ERR("Frame exceeding recv MTU (len %d, "
3972 "MTU %d)", len,
3973 l2cap_pi(sk)->imtu);
3974 bh_unlock_sock(sk);
3975 l2cap_conn_unreliable(conn, ECOMM);
3976 goto drop;
3977 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003978 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003979 }
3980
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003982 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
3983 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984 goto drop;
3985
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003986 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003987 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988 conn->rx_len = len - skb->len;
3989 } else {
3990 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
3991
3992 if (!conn->rx_len) {
3993 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
3994 l2cap_conn_unreliable(conn, ECOMM);
3995 goto drop;
3996 }
3997
3998 if (skb->len > conn->rx_len) {
3999 BT_ERR("Fragment is too long (len %d, expected %d)",
4000 skb->len, conn->rx_len);
4001 kfree_skb(conn->rx_skb);
4002 conn->rx_skb = NULL;
4003 conn->rx_len = 0;
4004 l2cap_conn_unreliable(conn, ECOMM);
4005 goto drop;
4006 }
4007
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004008 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004009 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010 conn->rx_len -= skb->len;
4011
4012 if (!conn->rx_len) {
4013 /* Complete frame received */
4014 l2cap_recv_frame(conn, conn->rx_skb);
4015 conn->rx_skb = NULL;
4016 }
4017 }
4018
4019drop:
4020 kfree_skb(skb);
4021 return 0;
4022}
4023
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004024static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025{
4026 struct sock *sk;
4027 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028
4029 read_lock_bh(&l2cap_sk_list.lock);
4030
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004031 sk_for_each(sk, node, &l2cap_sk_list.head) {
4032 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004034 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 +01004035 batostr(&bt_sk(sk)->src),
4036 batostr(&bt_sk(sk)->dst),
4037 sk->sk_state, __le16_to_cpu(pi->psm),
4038 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004039 pi->imtu, pi->omtu, pi->sec_level,
4040 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004041 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004044
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004045 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046}
4047
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004048static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4049{
4050 return single_open(file, l2cap_debugfs_show, inode->i_private);
4051}
4052
4053static const struct file_operations l2cap_debugfs_fops = {
4054 .open = l2cap_debugfs_open,
4055 .read = seq_read,
4056 .llseek = seq_lseek,
4057 .release = single_release,
4058};
4059
4060static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061
Linus Torvalds1da177e2005-04-16 15:20:36 -07004062static struct hci_proto l2cap_hci_proto = {
4063 .name = "L2CAP",
4064 .id = HCI_PROTO_L2CAP,
4065 .connect_ind = l2cap_connect_ind,
4066 .connect_cfm = l2cap_connect_cfm,
4067 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004068 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004069 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070 .recv_acldata = l2cap_recv_acldata
4071};
4072
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004073int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074{
4075 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004076
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004077 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078 if (err < 0)
4079 return err;
4080
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004081 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004082 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004083 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084 goto error;
4085 }
4086
4087 err = hci_register_proto(&l2cap_hci_proto);
4088 if (err < 0) {
4089 BT_ERR("L2CAP protocol registration failed");
4090 bt_sock_unregister(BTPROTO_L2CAP);
4091 goto error;
4092 }
4093
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004094 if (bt_debugfs) {
4095 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4096 bt_debugfs, NULL, &l2cap_debugfs_fops);
4097 if (!l2cap_debugfs)
4098 BT_ERR("Failed to create L2CAP debug file");
4099 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101 return 0;
4102
4103error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004104 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004105 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106 return err;
4107}
4108
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004109void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004111 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004113 flush_workqueue(_busy_wq);
4114 destroy_workqueue(_busy_wq);
4115
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4117 BT_ERR("L2CAP protocol unregistration failed");
4118
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004119 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120}
4121
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004122module_param(disable_ertm, bool, 0644);
4123MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");