blob: cb849b51632fd7ca43c292d4134c9f605b7932a6 [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) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300121 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300122 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200123 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300124 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200125}
126
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300127static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200128{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300129 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300130
131 read_lock(&conn->chan_lock);
132 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300133 if (c)
134 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300135 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300136 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200137}
138
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300139static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200140{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300141 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200142
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300143 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300144 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200145 return cid;
146 }
147
148 return 0;
149}
150
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300151static struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200152{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300153 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200154
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300155 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
156 if (!chan)
157 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200158
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300159 chan->sk = sk;
160
161 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200162}
163
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300164static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200165{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300166 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200167
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300168 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
169 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200170
Marcel Holtmann2950f212009-02-12 14:02:50 +0100171 conn->disc_reason = 0x13;
172
Marcel Holtmann01394182006-07-03 10:02:46 +0200173 l2cap_pi(sk)->conn = conn;
174
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300175 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Ville Tervob62f3282011-02-10 22:38:50 -0300176 if (conn->hcon->type == LE_LINK) {
177 /* LE connection */
178 l2cap_pi(sk)->omtu = L2CAP_LE_DEFAULT_MTU;
179 l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA;
180 l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA;
181 } else {
182 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300183 l2cap_pi(sk)->scid = l2cap_alloc_cid(conn);
Ville Tervob62f3282011-02-10 22:38:50 -0300184 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
185 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200186 } else if (sk->sk_type == SOCK_DGRAM) {
187 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300188 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
189 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200190 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
191 } else {
192 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300193 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
194 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200195 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
196 }
197
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300198 sock_hold(sk);
199
200 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200201}
202
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900203/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200204 * Must be called on the locked socket. */
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300205void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200206{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300207 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200208 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
209 struct sock *parent = bt_sk(sk)->parent;
210
211 l2cap_sock_clear_timer(sk);
212
213 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
214
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900215 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300216 /* Delete from channel list */
217 write_lock_bh(&conn->chan_lock);
218 list_del(&chan->list);
219 write_unlock_bh(&conn->chan_lock);
220 __sock_put(sk);
221
Marcel Holtmann01394182006-07-03 10:02:46 +0200222 l2cap_pi(sk)->conn = NULL;
223 hci_conn_put(conn->hcon);
224 }
225
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200226 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200227 sock_set_flag(sk, SOCK_ZAPPED);
228
229 if (err)
230 sk->sk_err = err;
231
232 if (parent) {
233 bt_accept_unlink(sk);
234 parent->sk_data_ready(parent, 0);
235 } else
236 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300237
238 skb_queue_purge(TX_QUEUE(sk));
239
240 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
241 struct srej_list *l, *tmp;
242
243 del_timer(&l2cap_pi(sk)->retrans_timer);
244 del_timer(&l2cap_pi(sk)->monitor_timer);
245 del_timer(&l2cap_pi(sk)->ack_timer);
246
247 skb_queue_purge(SREJ_QUEUE(sk));
248 skb_queue_purge(BUSY_QUEUE(sk));
249
250 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
251 list_del(&l->list);
252 kfree(l);
253 }
254 }
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300255
256 kfree(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200257}
258
Johan Hedberg8556edd32011-01-19 12:06:50 +0530259static inline u8 l2cap_get_auth_type(struct sock *sk)
260{
261 if (sk->sk_type == SOCK_RAW) {
262 switch (l2cap_pi(sk)->sec_level) {
263 case BT_SECURITY_HIGH:
264 return HCI_AT_DEDICATED_BONDING_MITM;
265 case BT_SECURITY_MEDIUM:
266 return HCI_AT_DEDICATED_BONDING;
267 default:
268 return HCI_AT_NO_BONDING;
269 }
270 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
271 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
272 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
273
274 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
275 return HCI_AT_NO_BONDING_MITM;
276 else
277 return HCI_AT_NO_BONDING;
278 } else {
279 switch (l2cap_pi(sk)->sec_level) {
280 case BT_SECURITY_HIGH:
281 return HCI_AT_GENERAL_BONDING_MITM;
282 case BT_SECURITY_MEDIUM:
283 return HCI_AT_GENERAL_BONDING;
284 default:
285 return HCI_AT_NO_BONDING;
286 }
287 }
288}
289
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200290/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100291static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200292{
293 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100294 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200295
Johan Hedberg8556edd32011-01-19 12:06:50 +0530296 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100297
298 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
299 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200300}
301
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200302u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200303{
304 u8 id;
305
306 /* Get next available identificator.
307 * 1 - 128 are used by kernel.
308 * 129 - 199 are reserved.
309 * 200 - 254 are used by utilities like l2ping, etc.
310 */
311
312 spin_lock_bh(&conn->lock);
313
314 if (++conn->tx_ident > 128)
315 conn->tx_ident = 1;
316
317 id = conn->tx_ident;
318
319 spin_unlock_bh(&conn->lock);
320
321 return id;
322}
323
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200324void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200325{
326 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200327 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200328
329 BT_DBG("code 0x%2.2x", code);
330
331 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300332 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200333
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200334 if (lmp_no_flush_capable(conn->hcon->hdev))
335 flags = ACL_START_NO_FLUSH;
336 else
337 flags = ACL_START;
338
339 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200340}
341
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300342static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300343{
344 struct sk_buff *skb;
345 struct l2cap_hdr *lh;
346 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300347 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300348 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200349 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300350
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300351 if (sk->sk_state != BT_CONNECTED)
352 return;
353
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300354 if (pi->fcs == L2CAP_FCS_CRC16)
355 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300356
357 BT_DBG("pi %p, control 0x%2.2x", pi, control);
358
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300359 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300360 control |= L2CAP_CTRL_FRAME_TYPE;
361
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300362 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
363 control |= L2CAP_CTRL_FINAL;
364 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
365 }
366
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300367 if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
368 control |= L2CAP_CTRL_POLL;
369 pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
370 }
371
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300372 skb = bt_skb_alloc(count, GFP_ATOMIC);
373 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300374 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300375
376 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300377 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300378 lh->cid = cpu_to_le16(pi->dcid);
379 put_unaligned_le16(control, skb_put(skb, 2));
380
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300381 if (pi->fcs == L2CAP_FCS_CRC16) {
382 u16 fcs = crc16(0, (u8 *)lh, count - 2);
383 put_unaligned_le16(fcs, skb_put(skb, 2));
384 }
385
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200386 if (lmp_no_flush_capable(conn->hcon->hdev))
387 flags = ACL_START_NO_FLUSH;
388 else
389 flags = ACL_START;
390
391 hci_send_acl(pi->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300392}
393
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300394static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300395{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300396 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300397 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300398 pi->conn_state |= L2CAP_CONN_RNR_SENT;
399 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300400 control |= L2CAP_SUPER_RCV_READY;
401
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300402 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
403
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300404 l2cap_send_sframe(pi, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300405}
406
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300407static inline int __l2cap_no_conn_pending(struct sock *sk)
408{
409 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
410}
411
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300412static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200413{
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300414 struct sock *sk = chan->sk;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200415 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
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300426 chan->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
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300429 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
430 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200431 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200432 } else {
433 struct l2cap_info_req req;
434 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
435
436 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
437 conn->info_ident = l2cap_get_ident(conn);
438
439 mod_timer(&conn->info_timer, jiffies +
440 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
441
442 l2cap_send_cmd(conn, conn->info_ident,
443 L2CAP_INFO_REQ, sizeof(req), &req);
444 }
445}
446
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300447static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
448{
449 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300450 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300451 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
452
453 switch (mode) {
454 case L2CAP_MODE_ERTM:
455 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
456 case L2CAP_MODE_STREAMING:
457 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
458 default:
459 return 0x00;
460 }
461}
462
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200463void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300464{
465 struct l2cap_disconn_req req;
466
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300467 if (!conn)
468 return;
469
470 skb_queue_purge(TX_QUEUE(sk));
471
472 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
473 del_timer(&l2cap_pi(sk)->retrans_timer);
474 del_timer(&l2cap_pi(sk)->monitor_timer);
475 del_timer(&l2cap_pi(sk)->ack_timer);
476 }
477
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300478 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
479 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
480 l2cap_send_cmd(conn, l2cap_get_ident(conn),
481 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300482
483 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300484 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300485}
486
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200488static void l2cap_conn_start(struct l2cap_conn *conn)
489{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300490 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200491
492 BT_DBG("conn %p", conn);
493
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300494 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200495
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300496 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300497 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300498
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200499 bh_lock_sock(sk);
500
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300501 if (sk->sk_type != SOCK_SEQPACKET &&
502 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200503 bh_unlock_sock(sk);
504 continue;
505 }
506
507 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300508 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300509
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300510 if (!l2cap_check_security(sk) ||
511 !__l2cap_no_conn_pending(sk)) {
512 bh_unlock_sock(sk);
513 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200514 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300515
516 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
517 conn->feat_mask)
518 && l2cap_pi(sk)->conf_state &
519 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300520 /* __l2cap_sock_close() calls list_del(chan)
521 * so release the lock */
522 read_unlock_bh(&conn->chan_lock);
523 __l2cap_sock_close(sk, ECONNRESET);
524 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300525 bh_unlock_sock(sk);
526 continue;
527 }
528
529 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
530 req.psm = l2cap_pi(sk)->psm;
531
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300532 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300533 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
534
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300535 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
536 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300537
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200538 } else if (sk->sk_state == BT_CONNECT2) {
539 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300540 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200541 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
542 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
543
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100544 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100545 if (bt_sk(sk)->defer_setup) {
546 struct sock *parent = bt_sk(sk)->parent;
547 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
548 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
549 parent->sk_data_ready(parent, 0);
550
551 } else {
552 sk->sk_state = BT_CONFIG;
553 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
554 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
555 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200556 } else {
557 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
558 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
559 }
560
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300561 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
562 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300563
564 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
565 rsp.result != L2CAP_CR_SUCCESS) {
566 bh_unlock_sock(sk);
567 continue;
568 }
569
570 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
571 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300572 l2cap_build_conf_req(chan, buf), buf);
573 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200574 }
575
576 bh_unlock_sock(sk);
577 }
578
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300579 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200580}
581
Ville Tervob62f3282011-02-10 22:38:50 -0300582/* Find socket with cid and source bdaddr.
583 * Returns closest match, locked.
584 */
585static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
586{
587 struct sock *s, *sk = NULL, *sk1 = NULL;
588 struct hlist_node *node;
589
590 read_lock(&l2cap_sk_list.lock);
591
592 sk_for_each(sk, node, &l2cap_sk_list.head) {
593 if (state && sk->sk_state != state)
594 continue;
595
596 if (l2cap_pi(sk)->scid == cid) {
597 /* Exact match. */
598 if (!bacmp(&bt_sk(sk)->src, src))
599 break;
600
601 /* Closest match */
602 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
603 sk1 = sk;
604 }
605 }
606 s = node ? sk : sk1;
607 if (s)
608 bh_lock_sock(s);
609 read_unlock(&l2cap_sk_list.lock);
610
611 return s;
612}
613
614static void l2cap_le_conn_ready(struct l2cap_conn *conn)
615{
Ville Tervob62f3282011-02-10 22:38:50 -0300616 struct sock *parent, *uninitialized_var(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300617 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300618
619 BT_DBG("");
620
621 /* Check if we have socket listening on cid */
622 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
623 conn->src);
624 if (!parent)
625 return;
626
627 /* Check for backlog size */
628 if (sk_acceptq_is_full(parent)) {
629 BT_DBG("backlog full %d", parent->sk_ack_backlog);
630 goto clean;
631 }
632
633 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
634 if (!sk)
635 goto clean;
636
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300637 chan = l2cap_chan_alloc(sk);
638 if (!chan) {
639 l2cap_sock_kill(sk);
640 goto clean;
641 }
642
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300643 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300644
645 hci_conn_hold(conn->hcon);
646
647 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300648
Ville Tervob62f3282011-02-10 22:38:50 -0300649 bacpy(&bt_sk(sk)->src, conn->src);
650 bacpy(&bt_sk(sk)->dst, conn->dst);
651
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300652 bt_accept_enqueue(parent, sk);
653
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300654 __l2cap_chan_add(conn, chan);
655
656 l2cap_pi(sk)->chan = chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300657
658 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
659
660 sk->sk_state = BT_CONNECTED;
661 parent->sk_data_ready(parent, 0);
662
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300663 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300664
665clean:
666 bh_unlock_sock(parent);
667}
668
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200669static void l2cap_conn_ready(struct l2cap_conn *conn)
670{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300671 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200672
673 BT_DBG("conn %p", conn);
674
Ville Tervob62f3282011-02-10 22:38:50 -0300675 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
676 l2cap_le_conn_ready(conn);
677
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300678 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200679
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300680 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300681 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300682
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200683 bh_lock_sock(sk);
684
Ville Tervoacd7d372011-02-10 22:38:49 -0300685 if (conn->hcon->type == LE_LINK) {
686 l2cap_sock_clear_timer(sk);
687 sk->sk_state = BT_CONNECTED;
688 sk->sk_state_change(sk);
689 }
690
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300691 if (sk->sk_type != SOCK_SEQPACKET &&
692 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200693 l2cap_sock_clear_timer(sk);
694 sk->sk_state = BT_CONNECTED;
695 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200696 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300697 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200698
699 bh_unlock_sock(sk);
700 }
701
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300702 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200703}
704
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200705/* Notify sockets that we cannot guaranty reliability anymore */
706static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
707{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300708 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200709
710 BT_DBG("conn %p", conn);
711
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300712 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200713
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300714 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300715 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300716
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100717 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200718 sk->sk_err = err;
719 }
720
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300721 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200722}
723
724static void l2cap_info_timeout(unsigned long arg)
725{
726 struct l2cap_conn *conn = (void *) arg;
727
Marcel Holtmann984947d2009-02-06 23:35:19 +0100728 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100729 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100730
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200731 l2cap_conn_start(conn);
732}
733
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
735{
Marcel Holtmann01394182006-07-03 10:02:46 +0200736 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
Marcel Holtmann01394182006-07-03 10:02:46 +0200738 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 return conn;
740
Marcel Holtmann01394182006-07-03 10:02:46 +0200741 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
742 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744
745 hcon->l2cap_data = conn;
746 conn->hcon = hcon;
747
Marcel Holtmann01394182006-07-03 10:02:46 +0200748 BT_DBG("hcon %p conn %p", hcon, conn);
749
Ville Tervoacd7d372011-02-10 22:38:49 -0300750 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
751 conn->mtu = hcon->hdev->le_mtu;
752 else
753 conn->mtu = hcon->hdev->acl_mtu;
754
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 conn->src = &hcon->hdev->bdaddr;
756 conn->dst = &hcon->dst;
757
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200758 conn->feat_mask = 0;
759
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300761 rwlock_init(&conn->chan_lock);
762
763 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764
Ville Tervob62f3282011-02-10 22:38:50 -0300765 if (hcon->type != LE_LINK)
766 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000767 (unsigned long) conn);
768
Marcel Holtmann2950f212009-02-12 14:02:50 +0100769 conn->disc_reason = 0x13;
770
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 return conn;
772}
773
Marcel Holtmann01394182006-07-03 10:02:46 +0200774static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775{
Marcel Holtmann01394182006-07-03 10:02:46 +0200776 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300777 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 struct sock *sk;
779
Marcel Holtmann01394182006-07-03 10:02:46 +0200780 if (!conn)
781 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782
783 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
784
Wei Yongjun7585b972009-02-25 18:29:52 +0800785 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786
787 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300788 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300789 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300791 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 bh_unlock_sock(sk);
793 l2cap_sock_kill(sk);
794 }
795
Dave Young8e8440f2008-03-03 12:18:55 -0800796 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
797 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800798
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 hcon->l2cap_data = NULL;
800 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801}
802
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300803static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300805 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300806 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300807 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808}
809
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811
812/* Find socket with psm and source bdaddr.
813 * Returns closest match.
814 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000815static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816{
817 struct sock *sk = NULL, *sk1 = NULL;
818 struct hlist_node *node;
819
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000820 read_lock(&l2cap_sk_list.lock);
821
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 sk_for_each(sk, node, &l2cap_sk_list.head) {
823 if (state && sk->sk_state != state)
824 continue;
825
826 if (l2cap_pi(sk)->psm == psm) {
827 /* Exact match. */
828 if (!bacmp(&bt_sk(sk)->src, src))
829 break;
830
831 /* Closest match */
832 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
833 sk1 = sk;
834 }
835 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000838
839 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840}
841
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200842int l2cap_do_connect(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843{
844 bdaddr_t *src = &bt_sk(sk)->src;
845 bdaddr_t *dst = &bt_sk(sk)->dst;
846 struct l2cap_conn *conn;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300847 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 struct hci_conn *hcon;
849 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200850 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200851 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100853 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
854 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300856 hdev = hci_get_route(dst, src);
857 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 return -EHOSTUNREACH;
859
860 hci_dev_lock_bh(hdev);
861
Johan Hedberg8556edd32011-01-19 12:06:50 +0530862 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200863
Ville Tervoacd7d372011-02-10 22:38:49 -0300864 if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
865 hcon = hci_connect(hdev, LE_LINK, dst,
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100866 l2cap_pi(sk)->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300867 else
868 hcon = hci_connect(hdev, ACL_LINK, dst,
869 l2cap_pi(sk)->sec_level, auth_type);
870
Ville Tervo30e76272011-02-22 16:10:53 -0300871 if (IS_ERR(hcon)) {
872 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300874 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875
876 conn = l2cap_conn_add(hcon, 0);
877 if (!conn) {
878 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300879 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 goto done;
881 }
882
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300883 chan = l2cap_chan_alloc(sk);
884 if (!chan) {
885 hci_conn_put(hcon);
886 err = -ENOMEM;
887 goto done;
888 }
889
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 /* Update source addr of the socket */
891 bacpy(src, conn->src);
892
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300893 l2cap_chan_add(conn, chan);
894
895 l2cap_pi(sk)->chan = chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896
897 sk->sk_state = BT_CONNECT;
898 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
899
900 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300901 if (sk->sk_type != SOCK_SEQPACKET &&
902 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530904 if (l2cap_check_security(sk))
905 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200906 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300907 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 }
909
Ville Tervo30e76272011-02-22 16:10:53 -0300910 err = 0;
911
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912done:
913 hci_dev_unlock_bh(hdev);
914 hci_dev_put(hdev);
915 return err;
916}
917
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200918int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300919{
920 DECLARE_WAITQUEUE(wait, current);
921 int err = 0;
922 int timeo = HZ/5;
923
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200924 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300925 while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
926 set_current_state(TASK_INTERRUPTIBLE);
927
928 if (!timeo)
929 timeo = HZ/5;
930
931 if (signal_pending(current)) {
932 err = sock_intr_errno(timeo);
933 break;
934 }
935
936 release_sock(sk);
937 timeo = schedule_timeout(timeo);
938 lock_sock(sk);
939
940 err = sock_error(sk);
941 if (err)
942 break;
943 }
944 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200945 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300946 return err;
947}
948
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300949static void l2cap_monitor_timeout(unsigned long arg)
950{
951 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300952
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300953 BT_DBG("sk %p", sk);
954
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300955 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300956 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300957 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200958 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300959 return;
960 }
961
962 l2cap_pi(sk)->retry_count++;
963 __mod_monitor_timer();
964
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -0300965 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300966 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300967}
968
969static void l2cap_retrans_timeout(unsigned long arg)
970{
971 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300972
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300973 BT_DBG("sk %p", sk);
974
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300975 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300976 l2cap_pi(sk)->retry_count = 1;
977 __mod_monitor_timer();
978
979 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
980
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -0300981 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300982 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300983}
984
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300985static void l2cap_drop_acked_frames(struct sock *sk)
986{
987 struct sk_buff *skb;
988
Gustavo F. Padovan812e7372010-05-01 16:15:42 -0300989 while ((skb = skb_peek(TX_QUEUE(sk))) &&
990 l2cap_pi(sk)->unacked_frames) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300991 if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
992 break;
993
994 skb = skb_dequeue(TX_QUEUE(sk));
995 kfree_skb(skb);
996
997 l2cap_pi(sk)->unacked_frames--;
998 }
999
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001000 if (!l2cap_pi(sk)->unacked_frames)
1001 del_timer(&l2cap_pi(sk)->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001002}
1003
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001004void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001005{
1006 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001007 struct hci_conn *hcon = pi->conn->hcon;
1008 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001009
1010 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1011
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001012 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
1013 flags = ACL_START_NO_FLUSH;
1014 else
1015 flags = ACL_START;
1016
1017 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001018}
1019
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001020void l2cap_streaming_send(struct sock *sk)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001021{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001022 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001023 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001024 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001025
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001026 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
1027 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001028 control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001029 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001030
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001031 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001032 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1033 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001034 }
1035
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001036 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001037
1038 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001039 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001040}
1041
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001042static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001043{
1044 struct l2cap_pinfo *pi = l2cap_pi(sk);
1045 struct sk_buff *skb, *tx_skb;
1046 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001047
1048 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001049 if (!skb)
1050 return;
1051
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001052 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001053 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001054 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001055
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001056 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1057 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001058
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001059 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001060
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001061 if (pi->remote_max_tx &&
1062 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001063 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001064 return;
1065 }
1066
1067 tx_skb = skb_clone(skb, GFP_ATOMIC);
1068 bt_cb(skb)->retries++;
1069 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001070
1071 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1072 control |= L2CAP_CTRL_FINAL;
1073 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1074 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001075
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001076 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1077 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001078
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001079 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1080
1081 if (pi->fcs == L2CAP_FCS_CRC16) {
1082 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1083 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1084 }
1085
1086 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001087}
1088
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001089int l2cap_ertm_send(struct sock *sk)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001090{
1091 struct sk_buff *skb, *tx_skb;
1092 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001093 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001094 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001095
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001096 if (sk->sk_state != BT_CONNECTED)
1097 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001098
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001099 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001100
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001101 if (pi->remote_max_tx &&
1102 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001103 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001104 break;
1105 }
1106
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001107 tx_skb = skb_clone(skb, GFP_ATOMIC);
1108
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001109 bt_cb(skb)->retries++;
1110
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001111 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001112 control &= L2CAP_CTRL_SAR;
1113
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001114 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1115 control |= L2CAP_CTRL_FINAL;
1116 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1117 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001118 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001119 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1120 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1121
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001122
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001123 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001124 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1125 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1126 }
1127
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001128 l2cap_do_send(sk, tx_skb);
1129
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001130 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001131
1132 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1133 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1134
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301135 if (bt_cb(skb)->retries == 1)
1136 pi->unacked_frames++;
1137
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001138 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001139
1140 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1141 sk->sk_send_head = NULL;
1142 else
1143 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001144
1145 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001146 }
1147
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001148 return nsent;
1149}
1150
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001151static int l2cap_retransmit_frames(struct sock *sk)
1152{
1153 struct l2cap_pinfo *pi = l2cap_pi(sk);
1154 int ret;
1155
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001156 if (!skb_queue_empty(TX_QUEUE(sk)))
1157 sk->sk_send_head = TX_QUEUE(sk)->next;
1158
1159 pi->next_tx_seq = pi->expected_ack_seq;
1160 ret = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001161 return ret;
1162}
1163
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001164static void l2cap_send_ack(struct l2cap_pinfo *pi)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001165{
1166 struct sock *sk = (struct sock *)pi;
1167 u16 control = 0;
1168
1169 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1170
1171 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1172 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001173 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001174 l2cap_send_sframe(pi, control);
1175 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001176 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001177
Gustavo F. Padovane0f66212010-06-21 18:50:49 -03001178 if (l2cap_ertm_send(sk) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001179 return;
1180
1181 control |= L2CAP_SUPER_RCV_READY;
1182 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001183}
1184
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001185static void l2cap_send_srejtail(struct sock *sk)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001186{
1187 struct srej_list *tail;
1188 u16 control;
1189
1190 control = L2CAP_SUPER_SELECT_REJECT;
1191 control |= L2CAP_CTRL_FINAL;
1192
1193 tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
1194 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1195
1196 l2cap_send_sframe(l2cap_pi(sk), control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001197}
1198
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001199static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200{
1201 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001202 struct sk_buff **frag;
1203 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001205 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001206 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207
1208 sent += count;
1209 len -= count;
1210
1211 /* Continuation fragments (no L2CAP header) */
1212 frag = &skb_shinfo(skb)->frag_list;
1213 while (len) {
1214 count = min_t(unsigned int, conn->mtu, len);
1215
1216 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1217 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001218 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001219 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1220 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221
1222 sent += count;
1223 len -= count;
1224
1225 frag = &(*frag)->next;
1226 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227
1228 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001229}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001231struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001232{
1233 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1234 struct sk_buff *skb;
1235 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1236 struct l2cap_hdr *lh;
1237
1238 BT_DBG("sk %p len %d", sk, (int)len);
1239
1240 count = min_t(unsigned int, (conn->mtu - hlen), len);
1241 skb = bt_skb_send_alloc(sk, count + hlen,
1242 msg->msg_flags & MSG_DONTWAIT, &err);
1243 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001244 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001245
1246 /* Create L2CAP header */
1247 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1248 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1249 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1250 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1251
1252 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1253 if (unlikely(err < 0)) {
1254 kfree_skb(skb);
1255 return ERR_PTR(err);
1256 }
1257 return skb;
1258}
1259
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001260struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001261{
1262 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1263 struct sk_buff *skb;
1264 int err, count, hlen = L2CAP_HDR_SIZE;
1265 struct l2cap_hdr *lh;
1266
1267 BT_DBG("sk %p len %d", sk, (int)len);
1268
1269 count = min_t(unsigned int, (conn->mtu - hlen), len);
1270 skb = bt_skb_send_alloc(sk, count + hlen,
1271 msg->msg_flags & MSG_DONTWAIT, &err);
1272 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001273 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001274
1275 /* Create L2CAP header */
1276 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1277 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1278 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1279
1280 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1281 if (unlikely(err < 0)) {
1282 kfree_skb(skb);
1283 return ERR_PTR(err);
1284 }
1285 return skb;
1286}
1287
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001288struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001289{
1290 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1291 struct sk_buff *skb;
1292 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1293 struct l2cap_hdr *lh;
1294
1295 BT_DBG("sk %p len %d", sk, (int)len);
1296
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001297 if (!conn)
1298 return ERR_PTR(-ENOTCONN);
1299
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001300 if (sdulen)
1301 hlen += 2;
1302
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001303 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1304 hlen += 2;
1305
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001306 count = min_t(unsigned int, (conn->mtu - hlen), len);
1307 skb = bt_skb_send_alloc(sk, count + hlen,
1308 msg->msg_flags & MSG_DONTWAIT, &err);
1309 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001310 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001311
1312 /* Create L2CAP header */
1313 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1314 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1315 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1316 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001317 if (sdulen)
1318 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001319
1320 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1321 if (unlikely(err < 0)) {
1322 kfree_skb(skb);
1323 return ERR_PTR(err);
1324 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001325
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001326 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1327 put_unaligned_le16(0, skb_put(skb, 2));
1328
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001329 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001330 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331}
1332
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001333int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001334{
1335 struct l2cap_pinfo *pi = l2cap_pi(sk);
1336 struct sk_buff *skb;
1337 struct sk_buff_head sar_queue;
1338 u16 control;
1339 size_t size = 0;
1340
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001341 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001342 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001343 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001344 if (IS_ERR(skb))
1345 return PTR_ERR(skb);
1346
1347 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001348 len -= pi->remote_mps;
1349 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001350
1351 while (len > 0) {
1352 size_t buflen;
1353
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001354 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001355 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001356 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001357 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001358 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001359 buflen = len;
1360 }
1361
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001362 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001363 if (IS_ERR(skb)) {
1364 skb_queue_purge(&sar_queue);
1365 return PTR_ERR(skb);
1366 }
1367
1368 __skb_queue_tail(&sar_queue, skb);
1369 len -= buflen;
1370 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001371 }
1372 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1373 if (sk->sk_send_head == NULL)
1374 sk->sk_send_head = sar_queue.next;
1375
1376 return size;
1377}
1378
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379static void l2cap_chan_ready(struct sock *sk)
1380{
1381 struct sock *parent = bt_sk(sk)->parent;
1382
1383 BT_DBG("sk %p, parent %p", sk, parent);
1384
1385 l2cap_pi(sk)->conf_state = 0;
1386 l2cap_sock_clear_timer(sk);
1387
1388 if (!parent) {
1389 /* Outgoing channel.
1390 * Wake up socket sleeping on connect.
1391 */
1392 sk->sk_state = BT_CONNECTED;
1393 sk->sk_state_change(sk);
1394 } else {
1395 /* Incoming channel.
1396 * Wake up socket sleeping on accept.
1397 */
1398 parent->sk_data_ready(parent, 0);
1399 }
1400}
1401
1402/* Copy frame to all raw sockets on that connection */
1403static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1404{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001406 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407
1408 BT_DBG("conn %p", conn);
1409
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001410 read_lock(&conn->chan_lock);
1411 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001412 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 if (sk->sk_type != SOCK_RAW)
1414 continue;
1415
1416 /* Don't send frame to the socket it came from */
1417 if (skb->sk == sk)
1418 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001419 nskb = skb_clone(skb, GFP_ATOMIC);
1420 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 continue;
1422
1423 if (sock_queue_rcv_skb(sk, nskb))
1424 kfree_skb(nskb);
1425 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001426 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427}
1428
1429/* ---- L2CAP signalling commands ---- */
1430static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1431 u8 code, u8 ident, u16 dlen, void *data)
1432{
1433 struct sk_buff *skb, **frag;
1434 struct l2cap_cmd_hdr *cmd;
1435 struct l2cap_hdr *lh;
1436 int len, count;
1437
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001438 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1439 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440
1441 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1442 count = min_t(unsigned int, conn->mtu, len);
1443
1444 skb = bt_skb_alloc(count, GFP_ATOMIC);
1445 if (!skb)
1446 return NULL;
1447
1448 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001449 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001450
1451 if (conn->hcon->type == LE_LINK)
1452 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1453 else
1454 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455
1456 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1457 cmd->code = code;
1458 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001459 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460
1461 if (dlen) {
1462 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1463 memcpy(skb_put(skb, count), data, count);
1464 data += count;
1465 }
1466
1467 len -= skb->len;
1468
1469 /* Continuation fragments (no L2CAP header) */
1470 frag = &skb_shinfo(skb)->frag_list;
1471 while (len) {
1472 count = min_t(unsigned int, conn->mtu, len);
1473
1474 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1475 if (!*frag)
1476 goto fail;
1477
1478 memcpy(skb_put(*frag, count), data, count);
1479
1480 len -= count;
1481 data += count;
1482
1483 frag = &(*frag)->next;
1484 }
1485
1486 return skb;
1487
1488fail:
1489 kfree_skb(skb);
1490 return NULL;
1491}
1492
1493static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1494{
1495 struct l2cap_conf_opt *opt = *ptr;
1496 int len;
1497
1498 len = L2CAP_CONF_OPT_SIZE + opt->len;
1499 *ptr += len;
1500
1501 *type = opt->type;
1502 *olen = opt->len;
1503
1504 switch (opt->len) {
1505 case 1:
1506 *val = *((u8 *) opt->val);
1507 break;
1508
1509 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001510 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 break;
1512
1513 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001514 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 break;
1516
1517 default:
1518 *val = (unsigned long) opt->val;
1519 break;
1520 }
1521
1522 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1523 return len;
1524}
1525
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1527{
1528 struct l2cap_conf_opt *opt = *ptr;
1529
1530 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1531
1532 opt->type = type;
1533 opt->len = len;
1534
1535 switch (len) {
1536 case 1:
1537 *((u8 *) opt->val) = val;
1538 break;
1539
1540 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001541 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 break;
1543
1544 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001545 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 break;
1547
1548 default:
1549 memcpy(opt->val, (void *) val, len);
1550 break;
1551 }
1552
1553 *ptr += L2CAP_CONF_OPT_SIZE + len;
1554}
1555
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001556static void l2cap_ack_timeout(unsigned long arg)
1557{
1558 struct sock *sk = (void *) arg;
1559
1560 bh_lock_sock(sk);
1561 l2cap_send_ack(l2cap_pi(sk));
1562 bh_unlock_sock(sk);
1563}
1564
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001565static inline void l2cap_ertm_init(struct sock *sk)
1566{
1567 l2cap_pi(sk)->expected_ack_seq = 0;
1568 l2cap_pi(sk)->unacked_frames = 0;
1569 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03001570 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001571 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001572
1573 setup_timer(&l2cap_pi(sk)->retrans_timer,
1574 l2cap_retrans_timeout, (unsigned long) sk);
1575 setup_timer(&l2cap_pi(sk)->monitor_timer,
1576 l2cap_monitor_timeout, (unsigned long) sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001577 setup_timer(&l2cap_pi(sk)->ack_timer,
1578 l2cap_ack_timeout, (unsigned long) sk);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001579
1580 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001581 __skb_queue_head_init(BUSY_QUEUE(sk));
1582
1583 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001584
1585 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001586}
1587
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001588static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1589{
1590 switch (mode) {
1591 case L2CAP_MODE_STREAMING:
1592 case L2CAP_MODE_ERTM:
1593 if (l2cap_mode_supported(mode, remote_feat_mask))
1594 return mode;
1595 /* fall through */
1596 default:
1597 return L2CAP_MODE_BASIC;
1598 }
1599}
1600
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001601int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001603 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 struct l2cap_pinfo *pi = l2cap_pi(sk);
1605 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001606 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607 void *ptr = req->data;
1608
1609 BT_DBG("sk %p", sk);
1610
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001611 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001612 goto done;
1613
1614 switch (pi->mode) {
1615 case L2CAP_MODE_STREAMING:
1616 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001617 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001618 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001619
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001620 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001621 default:
1622 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1623 break;
1624 }
1625
1626done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001627 if (pi->imtu != L2CAP_DEFAULT_MTU)
1628 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1629
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001630 switch (pi->mode) {
1631 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001632 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1633 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1634 break;
1635
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001636 rfc.mode = L2CAP_MODE_BASIC;
1637 rfc.txwin_size = 0;
1638 rfc.max_transmit = 0;
1639 rfc.retrans_timeout = 0;
1640 rfc.monitor_timeout = 0;
1641 rfc.max_pdu_size = 0;
1642
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001643 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1644 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001645 break;
1646
1647 case L2CAP_MODE_ERTM:
1648 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001649 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001650 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001651 rfc.retrans_timeout = 0;
1652 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001653 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001654 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001655 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001656
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001657 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1658 (unsigned long) &rfc);
1659
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001660 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1661 break;
1662
1663 if (pi->fcs == L2CAP_FCS_NONE ||
1664 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1665 pi->fcs = L2CAP_FCS_NONE;
1666 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1667 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001668 break;
1669
1670 case L2CAP_MODE_STREAMING:
1671 rfc.mode = L2CAP_MODE_STREAMING;
1672 rfc.txwin_size = 0;
1673 rfc.max_transmit = 0;
1674 rfc.retrans_timeout = 0;
1675 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001676 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001677 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001678 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001679
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001680 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1681 (unsigned long) &rfc);
1682
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001683 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1684 break;
1685
1686 if (pi->fcs == L2CAP_FCS_NONE ||
1687 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1688 pi->fcs = L2CAP_FCS_NONE;
1689 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1690 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001691 break;
1692 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001694 req->dcid = cpu_to_le16(pi->dcid);
1695 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696
1697 return ptr - data;
1698}
1699
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001700static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001702 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001703 struct l2cap_conf_rsp *rsp = data;
1704 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001705 void *req = chan->conf_req;
1706 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001707 int type, hint, olen;
1708 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001709 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001710 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001711 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001713 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001714
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001715 while (len >= L2CAP_CONF_OPT_SIZE) {
1716 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001718 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001719 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001720
1721 switch (type) {
1722 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001723 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001724 break;
1725
1726 case L2CAP_CONF_FLUSH_TO:
1727 pi->flush_to = val;
1728 break;
1729
1730 case L2CAP_CONF_QOS:
1731 break;
1732
Marcel Holtmann6464f352007-10-20 13:39:51 +02001733 case L2CAP_CONF_RFC:
1734 if (olen == sizeof(rfc))
1735 memcpy(&rfc, (void *) val, olen);
1736 break;
1737
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001738 case L2CAP_CONF_FCS:
1739 if (val == L2CAP_FCS_NONE)
1740 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1741
1742 break;
1743
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001744 default:
1745 if (hint)
1746 break;
1747
1748 result = L2CAP_CONF_UNKNOWN;
1749 *((u8 *) ptr++) = type;
1750 break;
1751 }
1752 }
1753
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001754 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001755 goto done;
1756
1757 switch (pi->mode) {
1758 case L2CAP_MODE_STREAMING:
1759 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001760 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1761 pi->mode = l2cap_select_mode(rfc.mode,
1762 pi->conn->feat_mask);
1763 break;
1764 }
1765
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001766 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001767 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001768
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001769 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001770 }
1771
1772done:
1773 if (pi->mode != rfc.mode) {
1774 result = L2CAP_CONF_UNACCEPT;
1775 rfc.mode = pi->mode;
1776
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001777 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001778 return -ECONNREFUSED;
1779
1780 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1781 sizeof(rfc), (unsigned long) &rfc);
1782 }
1783
1784
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001785 if (result == L2CAP_CONF_SUCCESS) {
1786 /* Configure output options and let the other side know
1787 * which ones we don't like. */
1788
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001789 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1790 result = L2CAP_CONF_UNACCEPT;
1791 else {
1792 pi->omtu = mtu;
1793 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1794 }
1795 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001796
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001797 switch (rfc.mode) {
1798 case L2CAP_MODE_BASIC:
1799 pi->fcs = L2CAP_FCS_NONE;
1800 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1801 break;
1802
1803 case L2CAP_MODE_ERTM:
1804 pi->remote_tx_win = rfc.txwin_size;
1805 pi->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001806
1807 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1808 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001809
1810 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001811
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001812 rfc.retrans_timeout =
1813 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1814 rfc.monitor_timeout =
1815 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001816
1817 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001818
1819 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1820 sizeof(rfc), (unsigned long) &rfc);
1821
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001822 break;
1823
1824 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001825 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1826 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001827
1828 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001829
1830 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001831
1832 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1833 sizeof(rfc), (unsigned long) &rfc);
1834
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001835 break;
1836
1837 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001838 result = L2CAP_CONF_UNACCEPT;
1839
1840 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001841 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001842 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001843
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001844 if (result == L2CAP_CONF_SUCCESS)
1845 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1846 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001847 rsp->scid = cpu_to_le16(pi->dcid);
1848 rsp->result = cpu_to_le16(result);
1849 rsp->flags = cpu_to_le16(0x0000);
1850
1851 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852}
1853
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001854static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1855{
1856 struct l2cap_pinfo *pi = l2cap_pi(sk);
1857 struct l2cap_conf_req *req = data;
1858 void *ptr = req->data;
1859 int type, olen;
1860 unsigned long val;
1861 struct l2cap_conf_rfc rfc;
1862
1863 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1864
1865 while (len >= L2CAP_CONF_OPT_SIZE) {
1866 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1867
1868 switch (type) {
1869 case L2CAP_CONF_MTU:
1870 if (val < L2CAP_DEFAULT_MIN_MTU) {
1871 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001872 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001873 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001874 pi->imtu = val;
1875 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001876 break;
1877
1878 case L2CAP_CONF_FLUSH_TO:
1879 pi->flush_to = val;
1880 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1881 2, pi->flush_to);
1882 break;
1883
1884 case L2CAP_CONF_RFC:
1885 if (olen == sizeof(rfc))
1886 memcpy(&rfc, (void *)val, olen);
1887
1888 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1889 rfc.mode != pi->mode)
1890 return -ECONNREFUSED;
1891
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001892 pi->fcs = 0;
1893
1894 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1895 sizeof(rfc), (unsigned long) &rfc);
1896 break;
1897 }
1898 }
1899
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001900 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1901 return -ECONNREFUSED;
1902
1903 pi->mode = rfc.mode;
1904
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001905 if (*result == L2CAP_CONF_SUCCESS) {
1906 switch (rfc.mode) {
1907 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001908 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1909 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001910 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001911 break;
1912 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001913 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001914 }
1915 }
1916
1917 req->dcid = cpu_to_le16(pi->dcid);
1918 req->flags = cpu_to_le16(0x0000);
1919
1920 return ptr - data;
1921}
1922
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001923static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924{
1925 struct l2cap_conf_rsp *rsp = data;
1926 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001928 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001930 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001931 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001932 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933
1934 return ptr - data;
1935}
1936
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001937static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1938{
1939 struct l2cap_pinfo *pi = l2cap_pi(sk);
1940 int type, olen;
1941 unsigned long val;
1942 struct l2cap_conf_rfc rfc;
1943
1944 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1945
1946 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1947 return;
1948
1949 while (len >= L2CAP_CONF_OPT_SIZE) {
1950 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1951
1952 switch (type) {
1953 case L2CAP_CONF_RFC:
1954 if (olen == sizeof(rfc))
1955 memcpy(&rfc, (void *)val, olen);
1956 goto done;
1957 }
1958 }
1959
1960done:
1961 switch (rfc.mode) {
1962 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001963 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1964 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001965 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1966 break;
1967 case L2CAP_MODE_STREAMING:
1968 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1969 }
1970}
1971
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001972static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1973{
1974 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
1975
1976 if (rej->reason != 0x0000)
1977 return 0;
1978
1979 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
1980 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001981 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01001982
1983 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01001984 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01001985
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001986 l2cap_conn_start(conn);
1987 }
1988
1989 return 0;
1990}
1991
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1993{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
1995 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001996 struct l2cap_chan *chan = NULL;
Nathan Holsteind793fe82010-10-15 11:54:02 -04001997 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001998 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999
2000 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002001 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002
2003 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2004
2005 /* Check if we have socket listening on psm */
2006 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2007 if (!parent) {
2008 result = L2CAP_CR_BAD_PSM;
2009 goto sendresp;
2010 }
2011
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002012 bh_lock_sock(parent);
2013
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002014 /* Check if the ACL is secure enough (if not SDP) */
2015 if (psm != cpu_to_le16(0x0001) &&
2016 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002017 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002018 result = L2CAP_CR_SEC_BLOCK;
2019 goto response;
2020 }
2021
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 result = L2CAP_CR_NO_MEM;
2023
2024 /* Check for backlog size */
2025 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002026 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 goto response;
2028 }
2029
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002030 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 if (!sk)
2032 goto response;
2033
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002034 chan = l2cap_chan_alloc(sk);
2035 if (!chan) {
2036 l2cap_sock_kill(sk);
2037 goto response;
2038 }
2039
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002040 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041
2042 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002043 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2044 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 sock_set_flag(sk, SOCK_ZAPPED);
2046 l2cap_sock_kill(sk);
2047 goto response;
2048 }
2049
2050 hci_conn_hold(conn->hcon);
2051
2052 l2cap_sock_init(sk, parent);
2053 bacpy(&bt_sk(sk)->src, conn->src);
2054 bacpy(&bt_sk(sk)->dst, conn->dst);
2055 l2cap_pi(sk)->psm = psm;
2056 l2cap_pi(sk)->dcid = scid;
2057
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002058 bt_accept_enqueue(parent, sk);
2059
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002060 __l2cap_chan_add(conn, chan);
2061
2062 l2cap_pi(sk)->chan = chan;
2063
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 dcid = l2cap_pi(sk)->scid;
2065
2066 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2067
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002068 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069
Marcel Holtmann984947d2009-02-06 23:35:19 +01002070 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002071 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002072 if (bt_sk(sk)->defer_setup) {
2073 sk->sk_state = BT_CONNECT2;
2074 result = L2CAP_CR_PEND;
2075 status = L2CAP_CS_AUTHOR_PEND;
2076 parent->sk_data_ready(parent, 0);
2077 } else {
2078 sk->sk_state = BT_CONFIG;
2079 result = L2CAP_CR_SUCCESS;
2080 status = L2CAP_CS_NO_INFO;
2081 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002082 } else {
2083 sk->sk_state = BT_CONNECT2;
2084 result = L2CAP_CR_PEND;
2085 status = L2CAP_CS_AUTHEN_PEND;
2086 }
2087 } else {
2088 sk->sk_state = BT_CONNECT2;
2089 result = L2CAP_CR_PEND;
2090 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 }
2092
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002093 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094
2095response:
2096 bh_unlock_sock(parent);
2097
2098sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002099 rsp.scid = cpu_to_le16(scid);
2100 rsp.dcid = cpu_to_le16(dcid);
2101 rsp.result = cpu_to_le16(result);
2102 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002104
2105 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2106 struct l2cap_info_req info;
2107 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2108
2109 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2110 conn->info_ident = l2cap_get_ident(conn);
2111
2112 mod_timer(&conn->info_timer, jiffies +
2113 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2114
2115 l2cap_send_cmd(conn, conn->info_ident,
2116 L2CAP_INFO_REQ, sizeof(info), &info);
2117 }
2118
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002119 if (chan && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002120 result == L2CAP_CR_SUCCESS) {
2121 u8 buf[128];
2122 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2123 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002124 l2cap_build_conf_req(chan, buf), buf);
2125 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002126 }
2127
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 return 0;
2129}
2130
2131static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2132{
2133 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2134 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002135 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 struct sock *sk;
2137 u8 req[128];
2138
2139 scid = __le16_to_cpu(rsp->scid);
2140 dcid = __le16_to_cpu(rsp->dcid);
2141 result = __le16_to_cpu(rsp->result);
2142 status = __le16_to_cpu(rsp->status);
2143
2144 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2145
2146 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002147 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002148 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002149 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002151 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002152 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002153 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 }
2155
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002156 sk = chan->sk;
2157
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 switch (result) {
2159 case L2CAP_CR_SUCCESS:
2160 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002161 chan->ident = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002163 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2164
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002165 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2166 break;
2167
2168 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2169
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002171 l2cap_build_conf_req(chan, req), req);
2172 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173 break;
2174
2175 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002176 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 break;
2178
2179 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002180 /* don't delete l2cap channel if sk is owned by user */
2181 if (sock_owned_by_user(sk)) {
2182 sk->sk_state = BT_DISCONN;
2183 l2cap_sock_clear_timer(sk);
2184 l2cap_sock_set_timer(sk, HZ / 5);
2185 break;
2186 }
2187
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002188 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 break;
2190 }
2191
2192 bh_unlock_sock(sk);
2193 return 0;
2194}
2195
Mat Martineau8c462b62010-08-24 15:35:42 -07002196static inline void set_default_fcs(struct l2cap_pinfo *pi)
2197{
2198 /* FCS is enabled only in ERTM or streaming mode, if one or both
2199 * sides request it.
2200 */
2201 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2202 pi->fcs = L2CAP_FCS_NONE;
2203 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2204 pi->fcs = L2CAP_FCS_CRC16;
2205}
2206
Al Viro88219a02007-07-29 00:17:25 -07002207static 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 -07002208{
2209 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2210 u16 dcid, flags;
2211 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002212 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002214 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215
2216 dcid = __le16_to_cpu(req->dcid);
2217 flags = __le16_to_cpu(req->flags);
2218
2219 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2220
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002221 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002222 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 return -ENOENT;
2224
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002225 sk = chan->sk;
2226
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002227 if (sk->sk_state != BT_CONFIG) {
2228 struct l2cap_cmd_rej rej;
2229
2230 rej.reason = cpu_to_le16(0x0002);
2231 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2232 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002233 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002234 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002235
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002236 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002237 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002238 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002239 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2240 l2cap_build_conf_rsp(sk, rsp,
2241 L2CAP_CONF_REJECT, flags), rsp);
2242 goto unlock;
2243 }
2244
2245 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002246 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2247 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248
2249 if (flags & 0x0001) {
2250 /* Incomplete config. Send empty response. */
2251 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002252 l2cap_build_conf_rsp(sk, rsp,
2253 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 goto unlock;
2255 }
2256
2257 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002258 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002259 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002260 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002262 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002264 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002265 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002266
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002267 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002268 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002269
Marcel Holtmann876d9482007-10-20 13:35:42 +02002270 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2271 goto unlock;
2272
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002274 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002275
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002277
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002278 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002279 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002280 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002281 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2282 l2cap_ertm_init(sk);
2283
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002285 goto unlock;
2286 }
2287
2288 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002289 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002290 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002292 l2cap_build_conf_req(chan, buf), buf);
2293 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 }
2295
2296unlock:
2297 bh_unlock_sock(sk);
2298 return 0;
2299}
2300
2301static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2302{
2303 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2304 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002305 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002307 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308
2309 scid = __le16_to_cpu(rsp->scid);
2310 flags = __le16_to_cpu(rsp->flags);
2311 result = __le16_to_cpu(rsp->result);
2312
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002313 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2314 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002316 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002317 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 return 0;
2319
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002320 sk = chan->sk;
2321
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 switch (result) {
2323 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002324 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325 break;
2326
2327 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002328 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002329 char req[64];
2330
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002331 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002332 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002333 goto done;
2334 }
2335
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002336 /* throw out any old stored conf requests */
2337 result = L2CAP_CONF_SUCCESS;
2338 len = l2cap_parse_conf_rsp(sk, rsp->data,
2339 len, req, &result);
2340 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002341 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002342 goto done;
2343 }
2344
2345 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2346 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002347 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002348 if (result != L2CAP_CONF_SUCCESS)
2349 goto done;
2350 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 }
2352
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002353 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002354 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002356 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 goto done;
2358 }
2359
2360 if (flags & 0x01)
2361 goto done;
2362
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2364
2365 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002366 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002367
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002369 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002370 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002371 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002372 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2373 l2cap_ertm_init(sk);
2374
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 l2cap_chan_ready(sk);
2376 }
2377
2378done:
2379 bh_unlock_sock(sk);
2380 return 0;
2381}
2382
2383static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2384{
2385 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2386 struct l2cap_disconn_rsp rsp;
2387 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002388 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389 struct sock *sk;
2390
2391 scid = __le16_to_cpu(req->scid);
2392 dcid = __le16_to_cpu(req->dcid);
2393
2394 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2395
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002396 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002397 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 return 0;
2399
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002400 sk = chan->sk;
2401
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002402 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2403 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2405
2406 sk->sk_shutdown = SHUTDOWN_MASK;
2407
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002408 /* don't delete l2cap channel if sk is owned by user */
2409 if (sock_owned_by_user(sk)) {
2410 sk->sk_state = BT_DISCONN;
2411 l2cap_sock_clear_timer(sk);
2412 l2cap_sock_set_timer(sk, HZ / 5);
2413 bh_unlock_sock(sk);
2414 return 0;
2415 }
2416
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002417 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418 bh_unlock_sock(sk);
2419
2420 l2cap_sock_kill(sk);
2421 return 0;
2422}
2423
2424static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2425{
2426 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2427 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002428 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 struct sock *sk;
2430
2431 scid = __le16_to_cpu(rsp->scid);
2432 dcid = __le16_to_cpu(rsp->dcid);
2433
2434 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2435
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002436 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002437 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438 return 0;
2439
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002440 sk = chan->sk;
2441
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002442 /* don't delete l2cap channel if sk is owned by user */
2443 if (sock_owned_by_user(sk)) {
2444 sk->sk_state = BT_DISCONN;
2445 l2cap_sock_clear_timer(sk);
2446 l2cap_sock_set_timer(sk, HZ / 5);
2447 bh_unlock_sock(sk);
2448 return 0;
2449 }
2450
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002451 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 bh_unlock_sock(sk);
2453
2454 l2cap_sock_kill(sk);
2455 return 0;
2456}
2457
2458static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2459{
2460 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461 u16 type;
2462
2463 type = __le16_to_cpu(req->type);
2464
2465 BT_DBG("type 0x%4.4x", type);
2466
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002467 if (type == L2CAP_IT_FEAT_MASK) {
2468 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002469 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002470 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2471 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2472 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002473 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002474 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2475 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002476 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002477 l2cap_send_cmd(conn, cmd->ident,
2478 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002479 } else if (type == L2CAP_IT_FIXED_CHAN) {
2480 u8 buf[12];
2481 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2482 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2483 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2484 memcpy(buf + 4, l2cap_fixed_chan, 8);
2485 l2cap_send_cmd(conn, cmd->ident,
2486 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002487 } else {
2488 struct l2cap_info_rsp rsp;
2489 rsp.type = cpu_to_le16(type);
2490 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2491 l2cap_send_cmd(conn, cmd->ident,
2492 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2493 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494
2495 return 0;
2496}
2497
2498static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2499{
2500 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2501 u16 type, result;
2502
2503 type = __le16_to_cpu(rsp->type);
2504 result = __le16_to_cpu(rsp->result);
2505
2506 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2507
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002508 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2509 if (cmd->ident != conn->info_ident ||
2510 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2511 return 0;
2512
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002513 del_timer(&conn->info_timer);
2514
Ville Tervoadb08ed2010-08-04 09:43:33 +03002515 if (result != L2CAP_IR_SUCCESS) {
2516 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2517 conn->info_ident = 0;
2518
2519 l2cap_conn_start(conn);
2520
2521 return 0;
2522 }
2523
Marcel Holtmann984947d2009-02-06 23:35:19 +01002524 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002525 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002526
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002527 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002528 struct l2cap_info_req req;
2529 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2530
2531 conn->info_ident = l2cap_get_ident(conn);
2532
2533 l2cap_send_cmd(conn, conn->info_ident,
2534 L2CAP_INFO_REQ, sizeof(req), &req);
2535 } else {
2536 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2537 conn->info_ident = 0;
2538
2539 l2cap_conn_start(conn);
2540 }
2541 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002542 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002543 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002544
2545 l2cap_conn_start(conn);
2546 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002547
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548 return 0;
2549}
2550
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002551static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002552 u16 to_multiplier)
2553{
2554 u16 max_latency;
2555
2556 if (min > max || min < 6 || max > 3200)
2557 return -EINVAL;
2558
2559 if (to_multiplier < 10 || to_multiplier > 3200)
2560 return -EINVAL;
2561
2562 if (max >= to_multiplier * 8)
2563 return -EINVAL;
2564
2565 max_latency = (to_multiplier * 8 / max) - 1;
2566 if (latency > 499 || latency > max_latency)
2567 return -EINVAL;
2568
2569 return 0;
2570}
2571
2572static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2573 struct l2cap_cmd_hdr *cmd, u8 *data)
2574{
2575 struct hci_conn *hcon = conn->hcon;
2576 struct l2cap_conn_param_update_req *req;
2577 struct l2cap_conn_param_update_rsp rsp;
2578 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002579 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002580
2581 if (!(hcon->link_mode & HCI_LM_MASTER))
2582 return -EINVAL;
2583
2584 cmd_len = __le16_to_cpu(cmd->len);
2585 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2586 return -EPROTO;
2587
2588 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002589 min = __le16_to_cpu(req->min);
2590 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002591 latency = __le16_to_cpu(req->latency);
2592 to_multiplier = __le16_to_cpu(req->to_multiplier);
2593
2594 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2595 min, max, latency, to_multiplier);
2596
2597 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002598
2599 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2600 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002601 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2602 else
2603 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2604
2605 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2606 sizeof(rsp), &rsp);
2607
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002608 if (!err)
2609 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2610
Claudio Takahaside731152011-02-11 19:28:55 -02002611 return 0;
2612}
2613
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002614static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2615 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2616{
2617 int err = 0;
2618
2619 switch (cmd->code) {
2620 case L2CAP_COMMAND_REJ:
2621 l2cap_command_rej(conn, cmd, data);
2622 break;
2623
2624 case L2CAP_CONN_REQ:
2625 err = l2cap_connect_req(conn, cmd, data);
2626 break;
2627
2628 case L2CAP_CONN_RSP:
2629 err = l2cap_connect_rsp(conn, cmd, data);
2630 break;
2631
2632 case L2CAP_CONF_REQ:
2633 err = l2cap_config_req(conn, cmd, cmd_len, data);
2634 break;
2635
2636 case L2CAP_CONF_RSP:
2637 err = l2cap_config_rsp(conn, cmd, data);
2638 break;
2639
2640 case L2CAP_DISCONN_REQ:
2641 err = l2cap_disconnect_req(conn, cmd, data);
2642 break;
2643
2644 case L2CAP_DISCONN_RSP:
2645 err = l2cap_disconnect_rsp(conn, cmd, data);
2646 break;
2647
2648 case L2CAP_ECHO_REQ:
2649 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2650 break;
2651
2652 case L2CAP_ECHO_RSP:
2653 break;
2654
2655 case L2CAP_INFO_REQ:
2656 err = l2cap_information_req(conn, cmd, data);
2657 break;
2658
2659 case L2CAP_INFO_RSP:
2660 err = l2cap_information_rsp(conn, cmd, data);
2661 break;
2662
2663 default:
2664 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2665 err = -EINVAL;
2666 break;
2667 }
2668
2669 return err;
2670}
2671
2672static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2673 struct l2cap_cmd_hdr *cmd, u8 *data)
2674{
2675 switch (cmd->code) {
2676 case L2CAP_COMMAND_REJ:
2677 return 0;
2678
2679 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002680 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002681
2682 case L2CAP_CONN_PARAM_UPDATE_RSP:
2683 return 0;
2684
2685 default:
2686 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2687 return -EINVAL;
2688 }
2689}
2690
2691static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2692 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693{
2694 u8 *data = skb->data;
2695 int len = skb->len;
2696 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002697 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698
2699 l2cap_raw_recv(conn, skb);
2700
2701 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002702 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2704 data += L2CAP_CMD_HDR_SIZE;
2705 len -= L2CAP_CMD_HDR_SIZE;
2706
Al Viro88219a02007-07-29 00:17:25 -07002707 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708
Al Viro88219a02007-07-29 00:17:25 -07002709 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 -07002710
Al Viro88219a02007-07-29 00:17:25 -07002711 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712 BT_DBG("corrupted command");
2713 break;
2714 }
2715
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002716 if (conn->hcon->type == LE_LINK)
2717 err = l2cap_le_sig_cmd(conn, &cmd, data);
2718 else
2719 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720
2721 if (err) {
2722 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002723
2724 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725
2726 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002727 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2729 }
2730
Al Viro88219a02007-07-29 00:17:25 -07002731 data += cmd_len;
2732 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 }
2734
2735 kfree_skb(skb);
2736}
2737
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002738static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2739{
2740 u16 our_fcs, rcv_fcs;
2741 int hdr_size = L2CAP_HDR_SIZE + 2;
2742
2743 if (pi->fcs == L2CAP_FCS_CRC16) {
2744 skb_trim(skb, skb->len - 2);
2745 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2746 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2747
2748 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002749 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002750 }
2751 return 0;
2752}
2753
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002754static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
2755{
2756 struct l2cap_pinfo *pi = l2cap_pi(sk);
2757 u16 control = 0;
2758
2759 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002760
2761 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2762
2763 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002764 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002765 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002766 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002767 }
2768
Gustavo F. Padovan4ea727e2010-06-03 16:34:20 -03002769 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
2770 l2cap_retransmit_frames(sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002771
2772 l2cap_ertm_send(sk);
2773
2774 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
2775 pi->frames_sent == 0) {
2776 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002777 l2cap_send_sframe(pi, control);
2778 }
2779}
2780
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002781static 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 -03002782{
2783 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002784 struct l2cap_pinfo *pi = l2cap_pi(sk);
2785 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002786
2787 bt_cb(skb)->tx_seq = tx_seq;
2788 bt_cb(skb)->sar = sar;
2789
2790 next_skb = skb_peek(SREJ_QUEUE(sk));
2791 if (!next_skb) {
2792 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002793 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002794 }
2795
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002796 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
2797 if (tx_seq_offset < 0)
2798 tx_seq_offset += 64;
2799
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002800 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002801 if (bt_cb(next_skb)->tx_seq == tx_seq)
2802 return -EINVAL;
2803
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002804 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
2805 pi->buffer_seq) % 64;
2806 if (next_tx_seq_offset < 0)
2807 next_tx_seq_offset += 64;
2808
2809 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002810 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002811 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002812 }
2813
2814 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
2815 break;
2816
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002817 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002818
2819 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002820
2821 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002822}
2823
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002824static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
2825{
2826 struct l2cap_pinfo *pi = l2cap_pi(sk);
2827 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002828 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002829
2830 switch (control & L2CAP_CTRL_SAR) {
2831 case L2CAP_SDU_UNSEGMENTED:
2832 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2833 goto drop;
2834
2835 err = sock_queue_rcv_skb(sk, skb);
2836 if (!err)
2837 return err;
2838
2839 break;
2840
2841 case L2CAP_SDU_START:
2842 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2843 goto drop;
2844
2845 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002846
2847 if (pi->sdu_len > pi->imtu)
2848 goto disconnect;
2849
2850 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002851 if (!pi->sdu)
2852 return -ENOMEM;
2853
2854 /* pull sdu_len bytes only after alloc, because of Local Busy
2855 * condition we have to be sure that this will be executed
2856 * only once, i.e., when alloc does not fail */
2857 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002858
2859 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2860
2861 pi->conn_state |= L2CAP_CONN_SAR_SDU;
2862 pi->partial_sdu_len = skb->len;
2863 break;
2864
2865 case L2CAP_SDU_CONTINUE:
2866 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2867 goto disconnect;
2868
2869 if (!pi->sdu)
2870 goto disconnect;
2871
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002872 pi->partial_sdu_len += skb->len;
2873 if (pi->partial_sdu_len > pi->sdu_len)
2874 goto drop;
2875
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002876 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2877
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002878 break;
2879
2880 case L2CAP_SDU_END:
2881 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2882 goto disconnect;
2883
2884 if (!pi->sdu)
2885 goto disconnect;
2886
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002887 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002888 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002889
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002890 if (pi->partial_sdu_len > pi->imtu)
2891 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002892
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002893 if (pi->partial_sdu_len != pi->sdu_len)
2894 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002895
2896 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002897 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002898
2899 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002900 if (!_skb) {
2901 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2902 return -ENOMEM;
2903 }
2904
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002905 err = sock_queue_rcv_skb(sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002906 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002907 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002908 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2909 return err;
2910 }
2911
2912 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2913 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002914
2915 kfree_skb(pi->sdu);
2916 break;
2917 }
2918
2919 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002920 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002921
2922drop:
2923 kfree_skb(pi->sdu);
2924 pi->sdu = NULL;
2925
2926disconnect:
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002927 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002928 kfree_skb(skb);
2929 return 0;
2930}
2931
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002932static int l2cap_try_push_rx_skb(struct sock *sk)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002933{
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002934 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002935 struct sk_buff *skb;
2936 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002937 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002938
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002939 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
2940 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
2941 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
2942 if (err < 0) {
2943 skb_queue_head(BUSY_QUEUE(sk), skb);
2944 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002945 }
2946
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002947 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002948 }
2949
2950 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
2951 goto done;
2952
2953 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2954 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
2955 l2cap_send_sframe(pi, control);
2956 l2cap_pi(sk)->retry_count = 1;
2957
2958 del_timer(&pi->retrans_timer);
2959 __mod_monitor_timer();
2960
2961 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
2962
2963done:
2964 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2965 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
2966
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002967 BT_DBG("sk %p, Exit local busy", sk);
2968
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002969 return 0;
2970}
2971
2972static void l2cap_busy_work(struct work_struct *work)
2973{
2974 DECLARE_WAITQUEUE(wait, current);
2975 struct l2cap_pinfo *pi =
2976 container_of(work, struct l2cap_pinfo, busy_work);
2977 struct sock *sk = (struct sock *)pi;
2978 int n_tries = 0, timeo = HZ/5, err;
2979 struct sk_buff *skb;
2980
2981 lock_sock(sk);
2982
2983 add_wait_queue(sk_sleep(sk), &wait);
2984 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
2985 set_current_state(TASK_INTERRUPTIBLE);
2986
2987 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
2988 err = -EBUSY;
2989 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
2990 break;
2991 }
2992
2993 if (!timeo)
2994 timeo = HZ/5;
2995
2996 if (signal_pending(current)) {
2997 err = sock_intr_errno(timeo);
2998 break;
2999 }
3000
3001 release_sock(sk);
3002 timeo = schedule_timeout(timeo);
3003 lock_sock(sk);
3004
3005 err = sock_error(sk);
3006 if (err)
3007 break;
3008
3009 if (l2cap_try_push_rx_skb(sk) == 0)
3010 break;
3011 }
3012
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003013 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003014 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003015
3016 release_sock(sk);
3017}
3018
3019static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
3020{
3021 struct l2cap_pinfo *pi = l2cap_pi(sk);
3022 int sctrl, err;
3023
3024 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
3025 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3026 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003027 return l2cap_try_push_rx_skb(sk);
3028
3029
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003030 }
3031
3032 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3033 if (err >= 0) {
3034 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3035 return err;
3036 }
3037
3038 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003039 BT_DBG("sk %p, Enter local busy", sk);
3040
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003041 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
3042 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3043 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3044
3045 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3046 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
3047 l2cap_send_sframe(pi, sctrl);
3048
3049 pi->conn_state |= L2CAP_CONN_RNR_SENT;
3050
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003051 del_timer(&pi->ack_timer);
3052
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003053 queue_work(_busy_wq, &pi->busy_work);
3054
3055 return err;
3056}
3057
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003058static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003059{
3060 struct l2cap_pinfo *pi = l2cap_pi(sk);
3061 struct sk_buff *_skb;
3062 int err = -EINVAL;
3063
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003064 /*
3065 * TODO: We have to notify the userland if some data is lost with the
3066 * Streaming Mode.
3067 */
3068
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003069 switch (control & L2CAP_CTRL_SAR) {
3070 case L2CAP_SDU_UNSEGMENTED:
3071 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3072 kfree_skb(pi->sdu);
3073 break;
3074 }
3075
3076 err = sock_queue_rcv_skb(sk, skb);
3077 if (!err)
3078 return 0;
3079
3080 break;
3081
3082 case L2CAP_SDU_START:
3083 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3084 kfree_skb(pi->sdu);
3085 break;
3086 }
3087
3088 pi->sdu_len = get_unaligned_le16(skb->data);
3089 skb_pull(skb, 2);
3090
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003091 if (pi->sdu_len > pi->imtu) {
3092 err = -EMSGSIZE;
3093 break;
3094 }
3095
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003096 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3097 if (!pi->sdu) {
3098 err = -ENOMEM;
3099 break;
3100 }
3101
3102 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3103
3104 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3105 pi->partial_sdu_len = skb->len;
3106 err = 0;
3107 break;
3108
3109 case L2CAP_SDU_CONTINUE:
3110 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3111 break;
3112
3113 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3114
3115 pi->partial_sdu_len += skb->len;
3116 if (pi->partial_sdu_len > pi->sdu_len)
3117 kfree_skb(pi->sdu);
3118 else
3119 err = 0;
3120
3121 break;
3122
3123 case L2CAP_SDU_END:
3124 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3125 break;
3126
3127 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3128
3129 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
3130 pi->partial_sdu_len += skb->len;
3131
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003132 if (pi->partial_sdu_len > pi->imtu)
3133 goto drop;
3134
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003135 if (pi->partial_sdu_len == pi->sdu_len) {
3136 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
3137 err = sock_queue_rcv_skb(sk, _skb);
3138 if (err < 0)
3139 kfree_skb(_skb);
3140 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003141 err = 0;
3142
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003143drop:
3144 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003145 break;
3146 }
3147
3148 kfree_skb(skb);
3149 return err;
3150}
3151
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003152static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
3153{
3154 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003155 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003156
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003157 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003158 if (bt_cb(skb)->tx_seq != tx_seq)
3159 break;
3160
3161 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003162 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003163 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003164 l2cap_pi(sk)->buffer_seq_srej =
3165 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003166 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003167 }
3168}
3169
3170static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
3171{
3172 struct l2cap_pinfo *pi = l2cap_pi(sk);
3173 struct srej_list *l, *tmp;
3174 u16 control;
3175
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003176 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003177 if (l->tx_seq == tx_seq) {
3178 list_del(&l->list);
3179 kfree(l);
3180 return;
3181 }
3182 control = L2CAP_SUPER_SELECT_REJECT;
3183 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3184 l2cap_send_sframe(pi, control);
3185 list_del(&l->list);
3186 list_add_tail(&l->list, SREJ_LIST(sk));
3187 }
3188}
3189
3190static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3191{
3192 struct l2cap_pinfo *pi = l2cap_pi(sk);
3193 struct srej_list *new;
3194 u16 control;
3195
3196 while (tx_seq != pi->expected_tx_seq) {
3197 control = L2CAP_SUPER_SELECT_REJECT;
3198 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3199 l2cap_send_sframe(pi, control);
3200
3201 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003202 new->tx_seq = pi->expected_tx_seq;
3203 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003204 list_add_tail(&new->list, SREJ_LIST(sk));
3205 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003206 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003207}
3208
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003209static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3210{
3211 struct l2cap_pinfo *pi = l2cap_pi(sk);
3212 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003213 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003214 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003215 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003216 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003217 int err = 0;
3218
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003219 BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
3220 rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003221
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003222 if (L2CAP_CTRL_FINAL & rx_control &&
3223 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003224 del_timer(&pi->monitor_timer);
3225 if (pi->unacked_frames > 0)
3226 __mod_retrans_timer();
3227 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
3228 }
3229
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003230 pi->expected_ack_seq = req_seq;
3231 l2cap_drop_acked_frames(sk);
3232
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003233 if (tx_seq == pi->expected_tx_seq)
3234 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003235
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003236 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3237 if (tx_seq_offset < 0)
3238 tx_seq_offset += 64;
3239
3240 /* invalid tx_seq */
3241 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003242 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003243 goto drop;
3244 }
3245
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003246 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
3247 goto drop;
3248
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003249 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3250 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003251
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003252 first = list_first_entry(SREJ_LIST(sk),
3253 struct srej_list, list);
3254 if (tx_seq == first->tx_seq) {
3255 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3256 l2cap_check_srej_gap(sk, tx_seq);
3257
3258 list_del(&first->list);
3259 kfree(first);
3260
3261 if (list_empty(SREJ_LIST(sk))) {
3262 pi->buffer_seq = pi->buffer_seq_srej;
3263 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666cc2010-05-01 16:15:40 -03003264 l2cap_send_ack(pi);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003265 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003266 }
3267 } else {
3268 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003269
3270 /* duplicated tx_seq */
3271 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
3272 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003273
3274 list_for_each_entry(l, SREJ_LIST(sk), list) {
3275 if (l->tx_seq == tx_seq) {
3276 l2cap_resend_srejframe(sk, tx_seq);
3277 return 0;
3278 }
3279 }
3280 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003281 }
3282 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003283 expected_tx_seq_offset =
3284 (pi->expected_tx_seq - pi->buffer_seq) % 64;
3285 if (expected_tx_seq_offset < 0)
3286 expected_tx_seq_offset += 64;
3287
3288 /* duplicated tx_seq */
3289 if (tx_seq_offset < expected_tx_seq_offset)
3290 goto drop;
3291
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003292 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003293
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003294 BT_DBG("sk %p, Enter SREJ", sk);
3295
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003296 INIT_LIST_HEAD(SREJ_LIST(sk));
3297 pi->buffer_seq_srej = pi->buffer_seq;
3298
3299 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003300 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003301 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3302
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003303 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
3304
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003305 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003306
3307 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003308 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003309 return 0;
3310
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003311expected:
3312 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3313
3314 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003315 bt_cb(skb)->tx_seq = tx_seq;
3316 bt_cb(skb)->sar = sar;
3317 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003318 return 0;
3319 }
3320
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003321 err = l2cap_push_rx_skb(sk, skb, rx_control);
3322 if (err < 0)
3323 return 0;
3324
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003325 if (rx_control & L2CAP_CTRL_FINAL) {
3326 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3327 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003328 else
3329 l2cap_retransmit_frames(sk);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003330 }
3331
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003332 __mod_ack_timer();
3333
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003334 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
3335 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003336 l2cap_send_ack(pi);
3337
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003338 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003339
3340drop:
3341 kfree_skb(skb);
3342 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003343}
3344
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003345static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003346{
3347 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003348
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003349 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3350 rx_control);
3351
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003352 pi->expected_ack_seq = __get_reqseq(rx_control);
3353 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003354
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003355 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003356 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003357 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3358 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3359 (pi->unacked_frames > 0))
3360 __mod_retrans_timer();
3361
3362 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3363 l2cap_send_srejtail(sk);
3364 } else {
3365 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003366 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003367
3368 } else if (rx_control & L2CAP_CTRL_FINAL) {
3369 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003370
3371 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3372 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003373 else
3374 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003375
3376 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003377 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3378 (pi->unacked_frames > 0))
3379 __mod_retrans_timer();
3380
3381 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003382 if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003383 l2cap_send_ack(pi);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003384 else
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003385 l2cap_ertm_send(sk);
3386 }
3387}
3388
3389static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
3390{
3391 struct l2cap_pinfo *pi = l2cap_pi(sk);
3392 u8 tx_seq = __get_reqseq(rx_control);
3393
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003394 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3395
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003396 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3397
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03003398 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003399 l2cap_drop_acked_frames(sk);
3400
3401 if (rx_control & L2CAP_CTRL_FINAL) {
3402 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3403 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003404 else
3405 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003406 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003407 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003408
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03003409 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003410 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003411 }
3412}
3413static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
3414{
3415 struct l2cap_pinfo *pi = l2cap_pi(sk);
3416 u8 tx_seq = __get_reqseq(rx_control);
3417
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003418 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3419
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003420 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3421
3422 if (rx_control & L2CAP_CTRL_POLL) {
3423 pi->expected_ack_seq = tx_seq;
3424 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003425
3426 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003427 l2cap_retransmit_one_frame(sk, tx_seq);
3428
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003429 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003430
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003431 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3432 pi->srej_save_reqseq = tx_seq;
3433 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3434 }
3435 } else if (rx_control & L2CAP_CTRL_FINAL) {
3436 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
3437 pi->srej_save_reqseq == tx_seq)
3438 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
3439 else
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003440 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003441 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003442 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003443 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3444 pi->srej_save_reqseq = tx_seq;
3445 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3446 }
3447 }
3448}
3449
3450static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
3451{
3452 struct l2cap_pinfo *pi = l2cap_pi(sk);
3453 u8 tx_seq = __get_reqseq(rx_control);
3454
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003455 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3456
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003457 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
3458 pi->expected_ack_seq = tx_seq;
3459 l2cap_drop_acked_frames(sk);
3460
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003461 if (rx_control & L2CAP_CTRL_POLL)
3462 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
3463
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003464 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
3465 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003466 if (rx_control & L2CAP_CTRL_POLL)
3467 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003468 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003469 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003470
3471 if (rx_control & L2CAP_CTRL_POLL)
3472 l2cap_send_srejtail(sk);
3473 else
3474 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003475}
3476
3477static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3478{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003479 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3480
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003481 if (L2CAP_CTRL_FINAL & rx_control &&
3482 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003483 del_timer(&l2cap_pi(sk)->monitor_timer);
3484 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003485 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003486 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003487 }
3488
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003489 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3490 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003491 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003492 break;
3493
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003494 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003495 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003496 break;
3497
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003498 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003499 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003500 break;
3501
3502 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003503 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003504 break;
3505 }
3506
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003507 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003508 return 0;
3509}
3510
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003511static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3512{
3513 struct l2cap_pinfo *pi = l2cap_pi(sk);
3514 u16 control;
3515 u8 req_seq;
3516 int len, next_tx_seq_offset, req_seq_offset;
3517
3518 control = get_unaligned_le16(skb->data);
3519 skb_pull(skb, 2);
3520 len = skb->len;
3521
3522 /*
3523 * We can just drop the corrupted I-frame here.
3524 * Receiver will miss it and start proper recovery
3525 * procedures and ask retransmission.
3526 */
3527 if (l2cap_check_fcs(pi, skb))
3528 goto drop;
3529
3530 if (__is_sar_start(control) && __is_iframe(control))
3531 len -= 2;
3532
3533 if (pi->fcs == L2CAP_FCS_CRC16)
3534 len -= 2;
3535
3536 if (len > pi->mps) {
3537 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3538 goto drop;
3539 }
3540
3541 req_seq = __get_reqseq(control);
3542 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
3543 if (req_seq_offset < 0)
3544 req_seq_offset += 64;
3545
3546 next_tx_seq_offset =
3547 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
3548 if (next_tx_seq_offset < 0)
3549 next_tx_seq_offset += 64;
3550
3551 /* check for invalid req-seq */
3552 if (req_seq_offset > next_tx_seq_offset) {
3553 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3554 goto drop;
3555 }
3556
3557 if (__is_iframe(control)) {
3558 if (len < 0) {
3559 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3560 goto drop;
3561 }
3562
3563 l2cap_data_channel_iframe(sk, control, skb);
3564 } else {
3565 if (len != 0) {
3566 BT_ERR("%d", len);
3567 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3568 goto drop;
3569 }
3570
3571 l2cap_data_channel_sframe(sk, control, skb);
3572 }
3573
3574 return 0;
3575
3576drop:
3577 kfree_skb(skb);
3578 return 0;
3579}
3580
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3582{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003583 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003585 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003586 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003587 u8 tx_seq;
3588 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003589
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003590 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003591 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003592 BT_DBG("unknown cid 0x%4.4x", cid);
3593 goto drop;
3594 }
3595
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003596 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003597 pi = l2cap_pi(sk);
3598
Linus Torvalds1da177e2005-04-16 15:20:36 -07003599 BT_DBG("sk %p, len %d", sk, skb->len);
3600
3601 if (sk->sk_state != BT_CONNECTED)
3602 goto drop;
3603
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003604 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003605 case L2CAP_MODE_BASIC:
3606 /* If socket recv buffers overflows we drop data here
3607 * which is *bad* because L2CAP has to be reliable.
3608 * But we don't have any other choice. L2CAP doesn't
3609 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003610
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003611 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003612 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003614 if (!sock_queue_rcv_skb(sk, skb))
3615 goto done;
3616 break;
3617
3618 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003619 if (!sock_owned_by_user(sk)) {
3620 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003621 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003622 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003623 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003624 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003625
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003626 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003627
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003628 case L2CAP_MODE_STREAMING:
3629 control = get_unaligned_le16(skb->data);
3630 skb_pull(skb, 2);
3631 len = skb->len;
3632
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003633 if (l2cap_check_fcs(pi, skb))
3634 goto drop;
3635
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003636 if (__is_sar_start(control))
3637 len -= 2;
3638
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003639 if (pi->fcs == L2CAP_FCS_CRC16)
3640 len -= 2;
3641
Nathan Holstein51893f82010-06-09 15:46:25 -04003642 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003643 goto drop;
3644
3645 tx_seq = __get_txseq(control);
3646
3647 if (pi->expected_tx_seq == tx_seq)
3648 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3649 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03003650 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003651
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003652 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003653
3654 goto done;
3655
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003656 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003657 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003658 break;
3659 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660
3661drop:
3662 kfree_skb(skb);
3663
3664done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003665 if (sk)
3666 bh_unlock_sock(sk);
3667
Linus Torvalds1da177e2005-04-16 15:20:36 -07003668 return 0;
3669}
3670
Al Viro8e036fc2007-07-29 00:16:36 -07003671static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672{
3673 struct sock *sk;
3674
3675 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3676 if (!sk)
3677 goto drop;
3678
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003679 bh_lock_sock(sk);
3680
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681 BT_DBG("sk %p, len %d", sk, skb->len);
3682
3683 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3684 goto drop;
3685
3686 if (l2cap_pi(sk)->imtu < skb->len)
3687 goto drop;
3688
3689 if (!sock_queue_rcv_skb(sk, skb))
3690 goto done;
3691
3692drop:
3693 kfree_skb(skb);
3694
3695done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003696 if (sk)
3697 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698 return 0;
3699}
3700
3701static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3702{
3703 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003704 u16 cid, len;
3705 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706
3707 skb_pull(skb, L2CAP_HDR_SIZE);
3708 cid = __le16_to_cpu(lh->cid);
3709 len = __le16_to_cpu(lh->len);
3710
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003711 if (len != skb->len) {
3712 kfree_skb(skb);
3713 return;
3714 }
3715
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3717
3718 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003719 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003720 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721 l2cap_sig_channel(conn, skb);
3722 break;
3723
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003724 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003725 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726 skb_pull(skb, 2);
3727 l2cap_conless_channel(conn, psm, skb);
3728 break;
3729
3730 default:
3731 l2cap_data_channel(conn, cid, skb);
3732 break;
3733 }
3734}
3735
3736/* ---- L2CAP interface with lower layer (HCI) ---- */
3737
3738static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3739{
3740 int exact = 0, lm1 = 0, lm2 = 0;
3741 register struct sock *sk;
3742 struct hlist_node *node;
3743
3744 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003745 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003746
3747 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3748
3749 /* Find listening sockets and check their link_mode */
3750 read_lock(&l2cap_sk_list.lock);
3751 sk_for_each(sk, node, &l2cap_sk_list.head) {
3752 if (sk->sk_state != BT_LISTEN)
3753 continue;
3754
3755 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003756 lm1 |= HCI_LM_ACCEPT;
3757 if (l2cap_pi(sk)->role_switch)
3758 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003759 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003760 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3761 lm2 |= HCI_LM_ACCEPT;
3762 if (l2cap_pi(sk)->role_switch)
3763 lm2 |= HCI_LM_MASTER;
3764 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765 }
3766 read_unlock(&l2cap_sk_list.lock);
3767
3768 return exact ? lm1 : lm2;
3769}
3770
3771static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3772{
Marcel Holtmann01394182006-07-03 10:02:46 +02003773 struct l2cap_conn *conn;
3774
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3776
Ville Tervoacd7d372011-02-10 22:38:49 -03003777 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003778 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779
3780 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781 conn = l2cap_conn_add(hcon, status);
3782 if (conn)
3783 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003784 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785 l2cap_conn_del(hcon, bt_err(status));
3786
3787 return 0;
3788}
3789
Marcel Holtmann2950f212009-02-12 14:02:50 +01003790static int l2cap_disconn_ind(struct hci_conn *hcon)
3791{
3792 struct l2cap_conn *conn = hcon->l2cap_data;
3793
3794 BT_DBG("hcon %p", hcon);
3795
3796 if (hcon->type != ACL_LINK || !conn)
3797 return 0x13;
3798
3799 return conn->disc_reason;
3800}
3801
3802static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003803{
3804 BT_DBG("hcon %p reason %d", hcon, reason);
3805
Ville Tervoacd7d372011-02-10 22:38:49 -03003806 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003807 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808
3809 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003810
Linus Torvalds1da177e2005-04-16 15:20:36 -07003811 return 0;
3812}
3813
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003814static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3815{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003816 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003817 return;
3818
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003819 if (encrypt == 0x00) {
3820 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3821 l2cap_sock_clear_timer(sk);
3822 l2cap_sock_set_timer(sk, HZ * 5);
3823 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3824 __l2cap_sock_close(sk, ECONNREFUSED);
3825 } else {
3826 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3827 l2cap_sock_clear_timer(sk);
3828 }
3829}
3830
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003831static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003832{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003833 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003834 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835
Marcel Holtmann01394182006-07-03 10:02:46 +02003836 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003838
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839 BT_DBG("conn %p", conn);
3840
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003841 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003843 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003844 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003845
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846 bh_lock_sock(sk);
3847
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003848 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3849 bh_unlock_sock(sk);
3850 continue;
3851 }
3852
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003853 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003854 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003855 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003856 bh_unlock_sock(sk);
3857 continue;
3858 }
3859
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003860 if (sk->sk_state == BT_CONNECT) {
3861 if (!status) {
3862 struct l2cap_conn_req req;
3863 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3864 req.psm = l2cap_pi(sk)->psm;
3865
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003866 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003867 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003868
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003869 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003870 L2CAP_CONN_REQ, sizeof(req), &req);
3871 } else {
3872 l2cap_sock_clear_timer(sk);
3873 l2cap_sock_set_timer(sk, HZ / 10);
3874 }
3875 } else if (sk->sk_state == BT_CONNECT2) {
3876 struct l2cap_conn_rsp rsp;
3877 __u16 result;
3878
3879 if (!status) {
3880 sk->sk_state = BT_CONFIG;
3881 result = L2CAP_CR_SUCCESS;
3882 } else {
3883 sk->sk_state = BT_DISCONN;
3884 l2cap_sock_set_timer(sk, HZ / 10);
3885 result = L2CAP_CR_SEC_BLOCK;
3886 }
3887
3888 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3889 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3890 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003891 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003892 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
3893 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894 }
3895
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896 bh_unlock_sock(sk);
3897 }
3898
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003899 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003900
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901 return 0;
3902}
3903
3904static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3905{
3906 struct l2cap_conn *conn = hcon->l2cap_data;
3907
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003908 if (!conn)
3909 conn = l2cap_conn_add(hcon, 0);
3910
3911 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912 goto drop;
3913
3914 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3915
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003916 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003918 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003919 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920 int len;
3921
3922 if (conn->rx_len) {
3923 BT_ERR("Unexpected start frame (len %d)", skb->len);
3924 kfree_skb(conn->rx_skb);
3925 conn->rx_skb = NULL;
3926 conn->rx_len = 0;
3927 l2cap_conn_unreliable(conn, ECOMM);
3928 }
3929
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003930 /* Start fragment always begin with Basic L2CAP header */
3931 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932 BT_ERR("Frame is too short (len %d)", skb->len);
3933 l2cap_conn_unreliable(conn, ECOMM);
3934 goto drop;
3935 }
3936
3937 hdr = (struct l2cap_hdr *) skb->data;
3938 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003939 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940
3941 if (len == skb->len) {
3942 /* Complete frame received */
3943 l2cap_recv_frame(conn, skb);
3944 return 0;
3945 }
3946
3947 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3948
3949 if (skb->len > len) {
3950 BT_ERR("Frame is too long (len %d, expected len %d)",
3951 skb->len, len);
3952 l2cap_conn_unreliable(conn, ECOMM);
3953 goto drop;
3954 }
3955
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003956 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003957
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003958 if (chan && chan->sk) {
3959 struct sock *sk = chan->sk;
3960
3961 if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
3962 BT_ERR("Frame exceeding recv MTU (len %d, "
3963 "MTU %d)", len,
3964 l2cap_pi(sk)->imtu);
3965 bh_unlock_sock(sk);
3966 l2cap_conn_unreliable(conn, ECOMM);
3967 goto drop;
3968 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003969 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003970 }
3971
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003973 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
3974 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003975 goto drop;
3976
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003977 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003978 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003979 conn->rx_len = len - skb->len;
3980 } else {
3981 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
3982
3983 if (!conn->rx_len) {
3984 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
3985 l2cap_conn_unreliable(conn, ECOMM);
3986 goto drop;
3987 }
3988
3989 if (skb->len > conn->rx_len) {
3990 BT_ERR("Fragment is too long (len %d, expected %d)",
3991 skb->len, conn->rx_len);
3992 kfree_skb(conn->rx_skb);
3993 conn->rx_skb = NULL;
3994 conn->rx_len = 0;
3995 l2cap_conn_unreliable(conn, ECOMM);
3996 goto drop;
3997 }
3998
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003999 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004000 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004001 conn->rx_len -= skb->len;
4002
4003 if (!conn->rx_len) {
4004 /* Complete frame received */
4005 l2cap_recv_frame(conn, conn->rx_skb);
4006 conn->rx_skb = NULL;
4007 }
4008 }
4009
4010drop:
4011 kfree_skb(skb);
4012 return 0;
4013}
4014
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004015static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016{
4017 struct sock *sk;
4018 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019
4020 read_lock_bh(&l2cap_sk_list.lock);
4021
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004022 sk_for_each(sk, node, &l2cap_sk_list.head) {
4023 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004025 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 +01004026 batostr(&bt_sk(sk)->src),
4027 batostr(&bt_sk(sk)->dst),
4028 sk->sk_state, __le16_to_cpu(pi->psm),
4029 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004030 pi->imtu, pi->omtu, pi->sec_level,
4031 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004032 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004035
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004036 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037}
4038
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004039static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4040{
4041 return single_open(file, l2cap_debugfs_show, inode->i_private);
4042}
4043
4044static const struct file_operations l2cap_debugfs_fops = {
4045 .open = l2cap_debugfs_open,
4046 .read = seq_read,
4047 .llseek = seq_lseek,
4048 .release = single_release,
4049};
4050
4051static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053static struct hci_proto l2cap_hci_proto = {
4054 .name = "L2CAP",
4055 .id = HCI_PROTO_L2CAP,
4056 .connect_ind = l2cap_connect_ind,
4057 .connect_cfm = l2cap_connect_cfm,
4058 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004059 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004060 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061 .recv_acldata = l2cap_recv_acldata
4062};
4063
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004064int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065{
4066 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004067
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004068 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069 if (err < 0)
4070 return err;
4071
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004072 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004073 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004074 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075 goto error;
4076 }
4077
4078 err = hci_register_proto(&l2cap_hci_proto);
4079 if (err < 0) {
4080 BT_ERR("L2CAP protocol registration failed");
4081 bt_sock_unregister(BTPROTO_L2CAP);
4082 goto error;
4083 }
4084
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004085 if (bt_debugfs) {
4086 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4087 bt_debugfs, NULL, &l2cap_debugfs_fops);
4088 if (!l2cap_debugfs)
4089 BT_ERR("Failed to create L2CAP debug file");
4090 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092 return 0;
4093
4094error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004095 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004096 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097 return err;
4098}
4099
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004100void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004102 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004104 flush_workqueue(_busy_wq);
4105 destroy_workqueue(_busy_wq);
4106
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4108 BT_ERR("L2CAP protocol unregistration failed");
4109
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004110 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111}
4112
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004113module_param(disable_ertm, bool, 0644);
4114MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");