blob: 0edfa658090a6b8730862f324a4e3c83062d998e [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
7 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation;
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
16 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090017 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090022 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
23 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 SOFTWARE IS DISCLAIMED.
25*/
26
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020027/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30
31#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080032#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
34#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/poll.h>
38#include <linux/fcntl.h>
39#include <linux/init.h>
40#include <linux/interrupt.h>
41#include <linux/socket.h>
42#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080044#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010045#include <linux/debugfs.h>
46#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030047#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030048#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/sock.h>
50
51#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
57
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020058int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020059
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070060static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010061static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030063static struct workqueue_struct *_busy_wq;
64
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020065struct bt_sock_list l2cap_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070066 .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070067};
68
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030069static void l2cap_busy_work(struct work_struct *work);
70
Linus Torvalds1da177e2005-04-16 15:20:36 -070071static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
72 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030073static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030075static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
76
Marcel Holtmann01394182006-07-03 10:02:46 +020077/* ---- L2CAP channels ---- */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030078static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020079{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030080 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030081
82 list_for_each_entry(c, &conn->chan_l, list) {
83 struct sock *s = c->sk;
84 if (l2cap_pi(s)->dcid == cid)
85 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020086 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030087 return NULL;
88
Marcel Holtmann01394182006-07-03 10:02:46 +020089}
90
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030091static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020092{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030093 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030094
95 list_for_each_entry(c, &conn->chan_l, list) {
96 struct sock *s = c->sk;
97 if (l2cap_pi(s)->scid == cid)
98 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020099 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300100 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200101}
102
103/* Find channel with given SCID.
104 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300105static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200106{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300107 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300108
109 read_lock(&conn->chan_lock);
110 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300111 if (c)
112 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300113 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300114 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200115}
116
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300117static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200118{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300119 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300120
121 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300122 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300123 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200124 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300125 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200126}
127
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300128static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200129{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300130 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300131
132 read_lock(&conn->chan_lock);
133 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300134 if (c)
135 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300136 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300137 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200138}
139
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300140static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200141{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300142 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200143
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300144 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300145 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200146 return cid;
147 }
148
149 return 0;
150}
151
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300152static struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200153{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300154 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200155
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300156 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
157 if (!chan)
158 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200159
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300160 chan->sk = sk;
161
162 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200163}
164
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300165static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200166{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300167 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200168
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300169 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
170 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200171
Marcel Holtmann2950f212009-02-12 14:02:50 +0100172 conn->disc_reason = 0x13;
173
Marcel Holtmann01394182006-07-03 10:02:46 +0200174 l2cap_pi(sk)->conn = conn;
175
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300176 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Ville Tervob62f3282011-02-10 22:38:50 -0300177 if (conn->hcon->type == LE_LINK) {
178 /* LE connection */
179 l2cap_pi(sk)->omtu = L2CAP_LE_DEFAULT_MTU;
180 l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA;
181 l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA;
182 } else {
183 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300184 l2cap_pi(sk)->scid = l2cap_alloc_cid(conn);
Ville Tervob62f3282011-02-10 22:38:50 -0300185 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
186 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200187 } else if (sk->sk_type == SOCK_DGRAM) {
188 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300189 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
190 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200191 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
192 } else {
193 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300194 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
195 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200196 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
197 }
198
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300199 sock_hold(sk);
200
201 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200202}
203
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900204/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200205 * Must be called on the locked socket. */
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300206void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200207{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300208 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200209 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
210 struct sock *parent = bt_sk(sk)->parent;
211
212 l2cap_sock_clear_timer(sk);
213
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300214 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200215
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900216 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300217 /* Delete from channel list */
218 write_lock_bh(&conn->chan_lock);
219 list_del(&chan->list);
220 write_unlock_bh(&conn->chan_lock);
221 __sock_put(sk);
222
Marcel Holtmann01394182006-07-03 10:02:46 +0200223 l2cap_pi(sk)->conn = NULL;
224 hci_conn_put(conn->hcon);
225 }
226
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200227 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200228 sock_set_flag(sk, SOCK_ZAPPED);
229
230 if (err)
231 sk->sk_err = err;
232
233 if (parent) {
234 bt_accept_unlink(sk);
235 parent->sk_data_ready(parent, 0);
236 } else
237 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300238
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300239 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE &&
240 l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE))
241 goto free;
242
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300243 skb_queue_purge(TX_QUEUE(sk));
244
245 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
246 struct srej_list *l, *tmp;
247
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300248 del_timer(&chan->retrans_timer);
249 del_timer(&chan->monitor_timer);
250 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300251
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300252 skb_queue_purge(&chan->srej_q);
253 skb_queue_purge(&chan->busy_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300254
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300255 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300256 list_del(&l->list);
257 kfree(l);
258 }
259 }
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300260
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300261free:
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300262 kfree(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200263}
264
Johan Hedberg8556edd32011-01-19 12:06:50 +0530265static inline u8 l2cap_get_auth_type(struct sock *sk)
266{
267 if (sk->sk_type == SOCK_RAW) {
268 switch (l2cap_pi(sk)->sec_level) {
269 case BT_SECURITY_HIGH:
270 return HCI_AT_DEDICATED_BONDING_MITM;
271 case BT_SECURITY_MEDIUM:
272 return HCI_AT_DEDICATED_BONDING;
273 default:
274 return HCI_AT_NO_BONDING;
275 }
276 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
277 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
278 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
279
280 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
281 return HCI_AT_NO_BONDING_MITM;
282 else
283 return HCI_AT_NO_BONDING;
284 } else {
285 switch (l2cap_pi(sk)->sec_level) {
286 case BT_SECURITY_HIGH:
287 return HCI_AT_GENERAL_BONDING_MITM;
288 case BT_SECURITY_MEDIUM:
289 return HCI_AT_GENERAL_BONDING;
290 default:
291 return HCI_AT_NO_BONDING;
292 }
293 }
294}
295
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200296/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100297static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200298{
299 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100300 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200301
Johan Hedberg8556edd32011-01-19 12:06:50 +0530302 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100303
304 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
305 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200306}
307
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200308u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200309{
310 u8 id;
311
312 /* Get next available identificator.
313 * 1 - 128 are used by kernel.
314 * 129 - 199 are reserved.
315 * 200 - 254 are used by utilities like l2ping, etc.
316 */
317
318 spin_lock_bh(&conn->lock);
319
320 if (++conn->tx_ident > 128)
321 conn->tx_ident = 1;
322
323 id = conn->tx_ident;
324
325 spin_unlock_bh(&conn->lock);
326
327 return id;
328}
329
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200330void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200331{
332 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200333 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200334
335 BT_DBG("code 0x%2.2x", code);
336
337 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300338 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200339
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200340 if (lmp_no_flush_capable(conn->hcon->hdev))
341 flags = ACL_START_NO_FLUSH;
342 else
343 flags = ACL_START;
344
345 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200346}
347
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300348static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300349{
350 struct sk_buff *skb;
351 struct l2cap_hdr *lh;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300352 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300353 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300354 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300355 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200356 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300357
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300358 if (sk->sk_state != BT_CONNECTED)
359 return;
360
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300361 if (pi->fcs == L2CAP_FCS_CRC16)
362 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300363
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300364 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300365
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300366 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300367 control |= L2CAP_CTRL_FRAME_TYPE;
368
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300369 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300370 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300371 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300372 }
373
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300374 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300375 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300376 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300377 }
378
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300379 skb = bt_skb_alloc(count, GFP_ATOMIC);
380 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300381 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300382
383 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300384 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300385 lh->cid = cpu_to_le16(pi->dcid);
386 put_unaligned_le16(control, skb_put(skb, 2));
387
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300388 if (pi->fcs == L2CAP_FCS_CRC16) {
389 u16 fcs = crc16(0, (u8 *)lh, count - 2);
390 put_unaligned_le16(fcs, skb_put(skb, 2));
391 }
392
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200393 if (lmp_no_flush_capable(conn->hcon->hdev))
394 flags = ACL_START_NO_FLUSH;
395 else
396 flags = ACL_START;
397
398 hci_send_acl(pi->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300399}
400
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300401static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300402{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300403 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300404 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300405 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300406 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300407 control |= L2CAP_SUPER_RCV_READY;
408
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300409 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300410
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300411 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300412}
413
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300414static inline int __l2cap_no_conn_pending(struct sock *sk)
415{
416 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
417}
418
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300419static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200420{
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300421 struct sock *sk = chan->sk;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200422 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
423
424 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100425 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
426 return;
427
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300428 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200429 struct l2cap_conn_req req;
430 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
431 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200432
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300433 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300434 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200435
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300436 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
437 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200438 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200439 } else {
440 struct l2cap_info_req req;
441 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
442
443 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
444 conn->info_ident = l2cap_get_ident(conn);
445
446 mod_timer(&conn->info_timer, jiffies +
447 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
448
449 l2cap_send_cmd(conn, conn->info_ident,
450 L2CAP_INFO_REQ, sizeof(req), &req);
451 }
452}
453
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300454static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
455{
456 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300457 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300458 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
459
460 switch (mode) {
461 case L2CAP_MODE_ERTM:
462 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
463 case L2CAP_MODE_STREAMING:
464 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
465 default:
466 return 0x00;
467 }
468}
469
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300470void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300471{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300472 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300473 struct l2cap_disconn_req req;
474
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300475 if (!conn)
476 return;
477
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300478 sk = chan->sk;
479
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300480 skb_queue_purge(TX_QUEUE(sk));
481
482 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300483 del_timer(&chan->retrans_timer);
484 del_timer(&chan->monitor_timer);
485 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300486 }
487
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300488 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
489 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
490 l2cap_send_cmd(conn, l2cap_get_ident(conn),
491 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300492
493 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300494 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300495}
496
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200498static void l2cap_conn_start(struct l2cap_conn *conn)
499{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300500 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200501
502 BT_DBG("conn %p", conn);
503
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300504 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200505
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300506 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300507 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300508
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200509 bh_lock_sock(sk);
510
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300511 if (sk->sk_type != SOCK_SEQPACKET &&
512 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200513 bh_unlock_sock(sk);
514 continue;
515 }
516
517 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300518 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300519
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300520 if (!l2cap_check_security(sk) ||
521 !__l2cap_no_conn_pending(sk)) {
522 bh_unlock_sock(sk);
523 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200524 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300525
526 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
527 conn->feat_mask)
528 && l2cap_pi(sk)->conf_state &
529 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300530 /* __l2cap_sock_close() calls list_del(chan)
531 * so release the lock */
532 read_unlock_bh(&conn->chan_lock);
533 __l2cap_sock_close(sk, ECONNRESET);
534 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300535 bh_unlock_sock(sk);
536 continue;
537 }
538
539 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
540 req.psm = l2cap_pi(sk)->psm;
541
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300542 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300543 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
544
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300545 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
546 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300547
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200548 } else if (sk->sk_state == BT_CONNECT2) {
549 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300550 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200551 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
552 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
553
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100554 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100555 if (bt_sk(sk)->defer_setup) {
556 struct sock *parent = bt_sk(sk)->parent;
557 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
558 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
559 parent->sk_data_ready(parent, 0);
560
561 } else {
562 sk->sk_state = BT_CONFIG;
563 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
564 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
565 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200566 } else {
567 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
568 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
569 }
570
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300571 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
572 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300573
574 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
575 rsp.result != L2CAP_CR_SUCCESS) {
576 bh_unlock_sock(sk);
577 continue;
578 }
579
580 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
581 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300582 l2cap_build_conf_req(chan, buf), buf);
583 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200584 }
585
586 bh_unlock_sock(sk);
587 }
588
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300589 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200590}
591
Ville Tervob62f3282011-02-10 22:38:50 -0300592/* Find socket with cid and source bdaddr.
593 * Returns closest match, locked.
594 */
595static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
596{
597 struct sock *s, *sk = NULL, *sk1 = NULL;
598 struct hlist_node *node;
599
600 read_lock(&l2cap_sk_list.lock);
601
602 sk_for_each(sk, node, &l2cap_sk_list.head) {
603 if (state && sk->sk_state != state)
604 continue;
605
606 if (l2cap_pi(sk)->scid == cid) {
607 /* Exact match. */
608 if (!bacmp(&bt_sk(sk)->src, src))
609 break;
610
611 /* Closest match */
612 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
613 sk1 = sk;
614 }
615 }
616 s = node ? sk : sk1;
617 if (s)
618 bh_lock_sock(s);
619 read_unlock(&l2cap_sk_list.lock);
620
621 return s;
622}
623
624static void l2cap_le_conn_ready(struct l2cap_conn *conn)
625{
Ville Tervob62f3282011-02-10 22:38:50 -0300626 struct sock *parent, *uninitialized_var(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300627 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300628
629 BT_DBG("");
630
631 /* Check if we have socket listening on cid */
632 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
633 conn->src);
634 if (!parent)
635 return;
636
637 /* Check for backlog size */
638 if (sk_acceptq_is_full(parent)) {
639 BT_DBG("backlog full %d", parent->sk_ack_backlog);
640 goto clean;
641 }
642
643 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
644 if (!sk)
645 goto clean;
646
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300647 chan = l2cap_chan_alloc(sk);
648 if (!chan) {
649 l2cap_sock_kill(sk);
650 goto clean;
651 }
652
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300653 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300654
655 hci_conn_hold(conn->hcon);
656
657 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300658
Ville Tervob62f3282011-02-10 22:38:50 -0300659 bacpy(&bt_sk(sk)->src, conn->src);
660 bacpy(&bt_sk(sk)->dst, conn->dst);
661
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300662 bt_accept_enqueue(parent, sk);
663
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300664 __l2cap_chan_add(conn, chan);
665
666 l2cap_pi(sk)->chan = chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300667
668 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
669
670 sk->sk_state = BT_CONNECTED;
671 parent->sk_data_ready(parent, 0);
672
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300673 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300674
675clean:
676 bh_unlock_sock(parent);
677}
678
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200679static void l2cap_conn_ready(struct l2cap_conn *conn)
680{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300681 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200682
683 BT_DBG("conn %p", conn);
684
Ville Tervob62f3282011-02-10 22:38:50 -0300685 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
686 l2cap_le_conn_ready(conn);
687
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300688 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200689
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300690 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300691 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300692
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200693 bh_lock_sock(sk);
694
Ville Tervoacd7d372011-02-10 22:38:49 -0300695 if (conn->hcon->type == LE_LINK) {
696 l2cap_sock_clear_timer(sk);
697 sk->sk_state = BT_CONNECTED;
698 sk->sk_state_change(sk);
699 }
700
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300701 if (sk->sk_type != SOCK_SEQPACKET &&
702 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200703 l2cap_sock_clear_timer(sk);
704 sk->sk_state = BT_CONNECTED;
705 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200706 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300707 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200708
709 bh_unlock_sock(sk);
710 }
711
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300712 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200713}
714
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200715/* Notify sockets that we cannot guaranty reliability anymore */
716static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
717{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300718 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200719
720 BT_DBG("conn %p", conn);
721
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300722 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200723
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300724 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300725 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300726
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100727 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200728 sk->sk_err = err;
729 }
730
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300731 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200732}
733
734static void l2cap_info_timeout(unsigned long arg)
735{
736 struct l2cap_conn *conn = (void *) arg;
737
Marcel Holtmann984947d2009-02-06 23:35:19 +0100738 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100739 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100740
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200741 l2cap_conn_start(conn);
742}
743
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
745{
Marcel Holtmann01394182006-07-03 10:02:46 +0200746 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
Marcel Holtmann01394182006-07-03 10:02:46 +0200748 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 return conn;
750
Marcel Holtmann01394182006-07-03 10:02:46 +0200751 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
752 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
755 hcon->l2cap_data = conn;
756 conn->hcon = hcon;
757
Marcel Holtmann01394182006-07-03 10:02:46 +0200758 BT_DBG("hcon %p conn %p", hcon, conn);
759
Ville Tervoacd7d372011-02-10 22:38:49 -0300760 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
761 conn->mtu = hcon->hdev->le_mtu;
762 else
763 conn->mtu = hcon->hdev->acl_mtu;
764
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 conn->src = &hcon->hdev->bdaddr;
766 conn->dst = &hcon->dst;
767
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200768 conn->feat_mask = 0;
769
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300771 rwlock_init(&conn->chan_lock);
772
773 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774
Ville Tervob62f3282011-02-10 22:38:50 -0300775 if (hcon->type != LE_LINK)
776 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000777 (unsigned long) conn);
778
Marcel Holtmann2950f212009-02-12 14:02:50 +0100779 conn->disc_reason = 0x13;
780
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 return conn;
782}
783
Marcel Holtmann01394182006-07-03 10:02:46 +0200784static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785{
Marcel Holtmann01394182006-07-03 10:02:46 +0200786 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300787 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 struct sock *sk;
789
Marcel Holtmann01394182006-07-03 10:02:46 +0200790 if (!conn)
791 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
793 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
794
Wei Yongjun7585b972009-02-25 18:29:52 +0800795 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796
797 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300798 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300799 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300801 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 bh_unlock_sock(sk);
803 l2cap_sock_kill(sk);
804 }
805
Dave Young8e8440f2008-03-03 12:18:55 -0800806 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
807 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800808
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 hcon->l2cap_data = NULL;
810 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811}
812
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300813static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300815 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300816 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300817 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818}
819
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
822/* Find socket with psm and source bdaddr.
823 * Returns closest match.
824 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000825static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826{
827 struct sock *sk = NULL, *sk1 = NULL;
828 struct hlist_node *node;
829
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000830 read_lock(&l2cap_sk_list.lock);
831
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 sk_for_each(sk, node, &l2cap_sk_list.head) {
833 if (state && sk->sk_state != state)
834 continue;
835
836 if (l2cap_pi(sk)->psm == psm) {
837 /* Exact match. */
838 if (!bacmp(&bt_sk(sk)->src, src))
839 break;
840
841 /* Closest match */
842 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
843 sk1 = sk;
844 }
845 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000848
849 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850}
851
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200852int l2cap_do_connect(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853{
854 bdaddr_t *src = &bt_sk(sk)->src;
855 bdaddr_t *dst = &bt_sk(sk)->dst;
856 struct l2cap_conn *conn;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300857 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 struct hci_conn *hcon;
859 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200860 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200861 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100863 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
864 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300866 hdev = hci_get_route(dst, src);
867 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 return -EHOSTUNREACH;
869
870 hci_dev_lock_bh(hdev);
871
Johan Hedberg8556edd32011-01-19 12:06:50 +0530872 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200873
Ville Tervoacd7d372011-02-10 22:38:49 -0300874 if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
875 hcon = hci_connect(hdev, LE_LINK, dst,
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100876 l2cap_pi(sk)->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300877 else
878 hcon = hci_connect(hdev, ACL_LINK, dst,
879 l2cap_pi(sk)->sec_level, auth_type);
880
Ville Tervo30e76272011-02-22 16:10:53 -0300881 if (IS_ERR(hcon)) {
882 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300884 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885
886 conn = l2cap_conn_add(hcon, 0);
887 if (!conn) {
888 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300889 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 goto done;
891 }
892
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300893 chan = l2cap_chan_alloc(sk);
894 if (!chan) {
895 hci_conn_put(hcon);
896 err = -ENOMEM;
897 goto done;
898 }
899
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 /* Update source addr of the socket */
901 bacpy(src, conn->src);
902
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300903 l2cap_chan_add(conn, chan);
904
905 l2cap_pi(sk)->chan = chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906
907 sk->sk_state = BT_CONNECT;
908 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
909
910 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300911 if (sk->sk_type != SOCK_SEQPACKET &&
912 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530914 if (l2cap_check_security(sk))
915 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200916 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300917 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 }
919
Ville Tervo30e76272011-02-22 16:10:53 -0300920 err = 0;
921
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922done:
923 hci_dev_unlock_bh(hdev);
924 hci_dev_put(hdev);
925 return err;
926}
927
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200928int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300929{
930 DECLARE_WAITQUEUE(wait, current);
931 int err = 0;
932 int timeo = HZ/5;
933
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200934 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300935 while ((l2cap_pi(sk)->chan->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300936 set_current_state(TASK_INTERRUPTIBLE);
937
938 if (!timeo)
939 timeo = HZ/5;
940
941 if (signal_pending(current)) {
942 err = sock_intr_errno(timeo);
943 break;
944 }
945
946 release_sock(sk);
947 timeo = schedule_timeout(timeo);
948 lock_sock(sk);
949
950 err = sock_error(sk);
951 if (err)
952 break;
953 }
954 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200955 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300956 return err;
957}
958
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300959static void l2cap_monitor_timeout(unsigned long arg)
960{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300961 struct l2cap_chan *chan = (void *) arg;
962 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300963
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300964 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300965
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300966 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -0300967 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300968 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200969 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300970 return;
971 }
972
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300973 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300974 __mod_monitor_timer();
975
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300976 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300977 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300978}
979
980static void l2cap_retrans_timeout(unsigned long arg)
981{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300982 struct l2cap_chan *chan = (void *) arg;
983 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300984
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300985 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300986
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300987 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300988 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300989 __mod_monitor_timer();
990
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300991 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300992
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300993 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300994 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300995}
996
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300997static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300998{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300999 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001000 struct sk_buff *skb;
1001
Gustavo F. Padovan812e7372010-05-01 16:15:42 -03001002 while ((skb = skb_peek(TX_QUEUE(sk))) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001003 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001004 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001005 break;
1006
1007 skb = skb_dequeue(TX_QUEUE(sk));
1008 kfree_skb(skb);
1009
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001010 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001011 }
1012
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001013 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001014 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001015}
1016
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001017void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001018{
1019 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001020 struct hci_conn *hcon = pi->conn->hcon;
1021 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001022
1023 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1024
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001025 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
1026 flags = ACL_START_NO_FLUSH;
1027 else
1028 flags = ACL_START;
1029
1030 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001031}
1032
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001033void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001034{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001035 struct sock *sk = chan->sk;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001036 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001037 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001038 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001039
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001040 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
1041 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001042 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001043 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001044
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001045 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001046 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1047 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001048 }
1049
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001050 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001051
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001052 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001053 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001054}
1055
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001056static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001057{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001058 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001059 struct l2cap_pinfo *pi = l2cap_pi(sk);
1060 struct sk_buff *skb, *tx_skb;
1061 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001062
1063 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001064 if (!skb)
1065 return;
1066
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001067 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001068 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001069 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001070
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001071 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1072 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001073
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001074 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001075
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001076 if (chan->remote_max_tx &&
1077 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001078 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001079 return;
1080 }
1081
1082 tx_skb = skb_clone(skb, GFP_ATOMIC);
1083 bt_cb(skb)->retries++;
1084 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001085
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001086 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001087 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001088 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001089 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001090
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001091 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001092 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001093
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001094 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1095
1096 if (pi->fcs == L2CAP_FCS_CRC16) {
1097 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1098 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1099 }
1100
1101 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001102}
1103
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001104int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001105{
1106 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001107 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001108 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001109 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001110 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001111
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001112 if (sk->sk_state != BT_CONNECTED)
1113 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001114
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001115 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001116
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001117 if (chan->remote_max_tx &&
1118 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001119 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001120 break;
1121 }
1122
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001123 tx_skb = skb_clone(skb, GFP_ATOMIC);
1124
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001125 bt_cb(skb)->retries++;
1126
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001127 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001128 control &= L2CAP_CTRL_SAR;
1129
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001130 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001131 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001132 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001133 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001134 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1135 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001136 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1137
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001138
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001139 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001140 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1141 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1142 }
1143
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001144 l2cap_do_send(sk, tx_skb);
1145
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001146 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001147
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001148 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1149 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001150
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301151 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001152 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301153
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001154 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001155
1156 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1157 sk->sk_send_head = NULL;
1158 else
1159 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001160
1161 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001162 }
1163
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001164 return nsent;
1165}
1166
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001167static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001168{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001169 struct sock *sk = chan->sk;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001170 int ret;
1171
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001172 if (!skb_queue_empty(TX_QUEUE(sk)))
1173 sk->sk_send_head = TX_QUEUE(sk)->next;
1174
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001175 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001176 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001177 return ret;
1178}
1179
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001180static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001181{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001182 u16 control = 0;
1183
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001184 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001185
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001186 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001187 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001188 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1189 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001190 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001191 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001192
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001193 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001194 return;
1195
1196 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001197 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001198}
1199
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001200static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001201{
1202 struct srej_list *tail;
1203 u16 control;
1204
1205 control = L2CAP_SUPER_SELECT_REJECT;
1206 control |= L2CAP_CTRL_FINAL;
1207
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001208 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001209 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1210
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001211 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001212}
1213
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001214static 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 -07001215{
1216 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001217 struct sk_buff **frag;
1218 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001220 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001221 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222
1223 sent += count;
1224 len -= count;
1225
1226 /* Continuation fragments (no L2CAP header) */
1227 frag = &skb_shinfo(skb)->frag_list;
1228 while (len) {
1229 count = min_t(unsigned int, conn->mtu, len);
1230
1231 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1232 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001233 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001234 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1235 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236
1237 sent += count;
1238 len -= count;
1239
1240 frag = &(*frag)->next;
1241 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242
1243 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001244}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001246struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001247{
1248 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1249 struct sk_buff *skb;
1250 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1251 struct l2cap_hdr *lh;
1252
1253 BT_DBG("sk %p len %d", sk, (int)len);
1254
1255 count = min_t(unsigned int, (conn->mtu - hlen), len);
1256 skb = bt_skb_send_alloc(sk, count + hlen,
1257 msg->msg_flags & MSG_DONTWAIT, &err);
1258 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001259 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001260
1261 /* Create L2CAP header */
1262 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1263 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1264 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1265 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1266
1267 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1268 if (unlikely(err < 0)) {
1269 kfree_skb(skb);
1270 return ERR_PTR(err);
1271 }
1272 return skb;
1273}
1274
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001275struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001276{
1277 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1278 struct sk_buff *skb;
1279 int err, count, hlen = L2CAP_HDR_SIZE;
1280 struct l2cap_hdr *lh;
1281
1282 BT_DBG("sk %p len %d", sk, (int)len);
1283
1284 count = min_t(unsigned int, (conn->mtu - hlen), len);
1285 skb = bt_skb_send_alloc(sk, count + hlen,
1286 msg->msg_flags & MSG_DONTWAIT, &err);
1287 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001288 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001289
1290 /* Create L2CAP header */
1291 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1292 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1293 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1294
1295 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1296 if (unlikely(err < 0)) {
1297 kfree_skb(skb);
1298 return ERR_PTR(err);
1299 }
1300 return skb;
1301}
1302
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001303struct 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 -03001304{
1305 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1306 struct sk_buff *skb;
1307 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1308 struct l2cap_hdr *lh;
1309
1310 BT_DBG("sk %p len %d", sk, (int)len);
1311
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001312 if (!conn)
1313 return ERR_PTR(-ENOTCONN);
1314
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001315 if (sdulen)
1316 hlen += 2;
1317
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001318 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1319 hlen += 2;
1320
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001321 count = min_t(unsigned int, (conn->mtu - hlen), len);
1322 skb = bt_skb_send_alloc(sk, count + hlen,
1323 msg->msg_flags & MSG_DONTWAIT, &err);
1324 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001325 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001326
1327 /* Create L2CAP header */
1328 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1329 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1330 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1331 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001332 if (sdulen)
1333 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001334
1335 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1336 if (unlikely(err < 0)) {
1337 kfree_skb(skb);
1338 return ERR_PTR(err);
1339 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001340
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001341 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1342 put_unaligned_le16(0, skb_put(skb, 2));
1343
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001344 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001345 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346}
1347
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001348int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001349{
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001350 struct sock *sk = chan->sk;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001351 struct sk_buff *skb;
1352 struct sk_buff_head sar_queue;
1353 u16 control;
1354 size_t size = 0;
1355
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001356 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001357 control = L2CAP_SDU_START;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001358 skb = l2cap_create_iframe_pdu(sk, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001359 if (IS_ERR(skb))
1360 return PTR_ERR(skb);
1361
1362 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001363 len -= chan->remote_mps;
1364 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001365
1366 while (len > 0) {
1367 size_t buflen;
1368
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001369 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001370 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001371 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001372 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001373 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001374 buflen = len;
1375 }
1376
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001377 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001378 if (IS_ERR(skb)) {
1379 skb_queue_purge(&sar_queue);
1380 return PTR_ERR(skb);
1381 }
1382
1383 __skb_queue_tail(&sar_queue, skb);
1384 len -= buflen;
1385 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001386 }
1387 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1388 if (sk->sk_send_head == NULL)
1389 sk->sk_send_head = sar_queue.next;
1390
1391 return size;
1392}
1393
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394static void l2cap_chan_ready(struct sock *sk)
1395{
1396 struct sock *parent = bt_sk(sk)->parent;
1397
1398 BT_DBG("sk %p, parent %p", sk, parent);
1399
1400 l2cap_pi(sk)->conf_state = 0;
1401 l2cap_sock_clear_timer(sk);
1402
1403 if (!parent) {
1404 /* Outgoing channel.
1405 * Wake up socket sleeping on connect.
1406 */
1407 sk->sk_state = BT_CONNECTED;
1408 sk->sk_state_change(sk);
1409 } else {
1410 /* Incoming channel.
1411 * Wake up socket sleeping on accept.
1412 */
1413 parent->sk_data_ready(parent, 0);
1414 }
1415}
1416
1417/* Copy frame to all raw sockets on that connection */
1418static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1419{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001421 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422
1423 BT_DBG("conn %p", conn);
1424
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001425 read_lock(&conn->chan_lock);
1426 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001427 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 if (sk->sk_type != SOCK_RAW)
1429 continue;
1430
1431 /* Don't send frame to the socket it came from */
1432 if (skb->sk == sk)
1433 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001434 nskb = skb_clone(skb, GFP_ATOMIC);
1435 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 continue;
1437
1438 if (sock_queue_rcv_skb(sk, nskb))
1439 kfree_skb(nskb);
1440 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001441 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442}
1443
1444/* ---- L2CAP signalling commands ---- */
1445static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1446 u8 code, u8 ident, u16 dlen, void *data)
1447{
1448 struct sk_buff *skb, **frag;
1449 struct l2cap_cmd_hdr *cmd;
1450 struct l2cap_hdr *lh;
1451 int len, count;
1452
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001453 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1454 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455
1456 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1457 count = min_t(unsigned int, conn->mtu, len);
1458
1459 skb = bt_skb_alloc(count, GFP_ATOMIC);
1460 if (!skb)
1461 return NULL;
1462
1463 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001464 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001465
1466 if (conn->hcon->type == LE_LINK)
1467 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1468 else
1469 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
1471 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1472 cmd->code = code;
1473 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001474 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475
1476 if (dlen) {
1477 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1478 memcpy(skb_put(skb, count), data, count);
1479 data += count;
1480 }
1481
1482 len -= skb->len;
1483
1484 /* Continuation fragments (no L2CAP header) */
1485 frag = &skb_shinfo(skb)->frag_list;
1486 while (len) {
1487 count = min_t(unsigned int, conn->mtu, len);
1488
1489 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1490 if (!*frag)
1491 goto fail;
1492
1493 memcpy(skb_put(*frag, count), data, count);
1494
1495 len -= count;
1496 data += count;
1497
1498 frag = &(*frag)->next;
1499 }
1500
1501 return skb;
1502
1503fail:
1504 kfree_skb(skb);
1505 return NULL;
1506}
1507
1508static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1509{
1510 struct l2cap_conf_opt *opt = *ptr;
1511 int len;
1512
1513 len = L2CAP_CONF_OPT_SIZE + opt->len;
1514 *ptr += len;
1515
1516 *type = opt->type;
1517 *olen = opt->len;
1518
1519 switch (opt->len) {
1520 case 1:
1521 *val = *((u8 *) opt->val);
1522 break;
1523
1524 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001525 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 break;
1527
1528 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001529 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 break;
1531
1532 default:
1533 *val = (unsigned long) opt->val;
1534 break;
1535 }
1536
1537 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1538 return len;
1539}
1540
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1542{
1543 struct l2cap_conf_opt *opt = *ptr;
1544
1545 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1546
1547 opt->type = type;
1548 opt->len = len;
1549
1550 switch (len) {
1551 case 1:
1552 *((u8 *) opt->val) = val;
1553 break;
1554
1555 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001556 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 break;
1558
1559 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001560 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561 break;
1562
1563 default:
1564 memcpy(opt->val, (void *) val, len);
1565 break;
1566 }
1567
1568 *ptr += L2CAP_CONF_OPT_SIZE + len;
1569}
1570
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001571static void l2cap_ack_timeout(unsigned long arg)
1572{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001573 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001574
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001575 bh_lock_sock(chan->sk);
1576 l2cap_send_ack(chan);
1577 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001578}
1579
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001580static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001581{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001582 struct sock *sk = chan->sk;
1583
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001584 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001585 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001586 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001587 chan->num_acked = 0;
1588 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001589
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001590 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1591 (unsigned long) chan);
1592 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1593 (unsigned long) chan);
1594 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001595
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001596 skb_queue_head_init(&chan->srej_q);
1597 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001598
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001599 INIT_LIST_HEAD(&chan->srej_l);
1600
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001601 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001602
1603 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001604}
1605
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001606static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1607{
1608 switch (mode) {
1609 case L2CAP_MODE_STREAMING:
1610 case L2CAP_MODE_ERTM:
1611 if (l2cap_mode_supported(mode, remote_feat_mask))
1612 return mode;
1613 /* fall through */
1614 default:
1615 return L2CAP_MODE_BASIC;
1616 }
1617}
1618
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001619static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001621 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001623 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624 void *ptr = req->data;
1625
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001626 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001628 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001629 goto done;
1630
1631 switch (pi->mode) {
1632 case L2CAP_MODE_STREAMING:
1633 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001634 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001635 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001636
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001637 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001638 default:
1639 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1640 break;
1641 }
1642
1643done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001644 if (pi->imtu != L2CAP_DEFAULT_MTU)
1645 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1646
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001647 switch (pi->mode) {
1648 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001649 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1650 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1651 break;
1652
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001653 rfc.mode = L2CAP_MODE_BASIC;
1654 rfc.txwin_size = 0;
1655 rfc.max_transmit = 0;
1656 rfc.retrans_timeout = 0;
1657 rfc.monitor_timeout = 0;
1658 rfc.max_pdu_size = 0;
1659
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001660 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1661 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001662 break;
1663
1664 case L2CAP_MODE_ERTM:
1665 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001666 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001667 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001668 rfc.retrans_timeout = 0;
1669 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001670 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001671 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001672 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001673
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001674 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1675 (unsigned long) &rfc);
1676
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001677 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1678 break;
1679
1680 if (pi->fcs == L2CAP_FCS_NONE ||
1681 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1682 pi->fcs = L2CAP_FCS_NONE;
1683 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1684 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001685 break;
1686
1687 case L2CAP_MODE_STREAMING:
1688 rfc.mode = L2CAP_MODE_STREAMING;
1689 rfc.txwin_size = 0;
1690 rfc.max_transmit = 0;
1691 rfc.retrans_timeout = 0;
1692 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001693 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001694 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001695 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001696
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001697 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1698 (unsigned long) &rfc);
1699
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001700 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1701 break;
1702
1703 if (pi->fcs == L2CAP_FCS_NONE ||
1704 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1705 pi->fcs = L2CAP_FCS_NONE;
1706 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1707 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001708 break;
1709 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001711 req->dcid = cpu_to_le16(pi->dcid);
1712 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713
1714 return ptr - data;
1715}
1716
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001717static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001719 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001720 struct l2cap_conf_rsp *rsp = data;
1721 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001722 void *req = chan->conf_req;
1723 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001724 int type, hint, olen;
1725 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001726 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001727 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001728 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001730 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001731
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001732 while (len >= L2CAP_CONF_OPT_SIZE) {
1733 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001735 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001736 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001737
1738 switch (type) {
1739 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001740 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001741 break;
1742
1743 case L2CAP_CONF_FLUSH_TO:
1744 pi->flush_to = val;
1745 break;
1746
1747 case L2CAP_CONF_QOS:
1748 break;
1749
Marcel Holtmann6464f352007-10-20 13:39:51 +02001750 case L2CAP_CONF_RFC:
1751 if (olen == sizeof(rfc))
1752 memcpy(&rfc, (void *) val, olen);
1753 break;
1754
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001755 case L2CAP_CONF_FCS:
1756 if (val == L2CAP_FCS_NONE)
1757 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1758
1759 break;
1760
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001761 default:
1762 if (hint)
1763 break;
1764
1765 result = L2CAP_CONF_UNKNOWN;
1766 *((u8 *) ptr++) = type;
1767 break;
1768 }
1769 }
1770
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001771 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001772 goto done;
1773
1774 switch (pi->mode) {
1775 case L2CAP_MODE_STREAMING:
1776 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001777 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1778 pi->mode = l2cap_select_mode(rfc.mode,
1779 pi->conn->feat_mask);
1780 break;
1781 }
1782
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001783 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001784 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001785
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001786 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001787 }
1788
1789done:
1790 if (pi->mode != rfc.mode) {
1791 result = L2CAP_CONF_UNACCEPT;
1792 rfc.mode = pi->mode;
1793
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001794 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001795 return -ECONNREFUSED;
1796
1797 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1798 sizeof(rfc), (unsigned long) &rfc);
1799 }
1800
1801
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001802 if (result == L2CAP_CONF_SUCCESS) {
1803 /* Configure output options and let the other side know
1804 * which ones we don't like. */
1805
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001806 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1807 result = L2CAP_CONF_UNACCEPT;
1808 else {
1809 pi->omtu = mtu;
1810 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1811 }
1812 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001813
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001814 switch (rfc.mode) {
1815 case L2CAP_MODE_BASIC:
1816 pi->fcs = L2CAP_FCS_NONE;
1817 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1818 break;
1819
1820 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001821 chan->remote_tx_win = rfc.txwin_size;
1822 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001823
1824 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1825 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001826
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001827 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001828
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001829 rfc.retrans_timeout =
1830 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1831 rfc.monitor_timeout =
1832 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001833
1834 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001835
1836 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1837 sizeof(rfc), (unsigned long) &rfc);
1838
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001839 break;
1840
1841 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001842 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1843 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001844
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001845 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001846
1847 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001848
1849 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1850 sizeof(rfc), (unsigned long) &rfc);
1851
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001852 break;
1853
1854 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001855 result = L2CAP_CONF_UNACCEPT;
1856
1857 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001858 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001859 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001860
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001861 if (result == L2CAP_CONF_SUCCESS)
1862 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1863 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001864 rsp->scid = cpu_to_le16(pi->dcid);
1865 rsp->result = cpu_to_le16(result);
1866 rsp->flags = cpu_to_le16(0x0000);
1867
1868 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869}
1870
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001871static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1872{
1873 struct l2cap_pinfo *pi = l2cap_pi(sk);
1874 struct l2cap_conf_req *req = data;
1875 void *ptr = req->data;
1876 int type, olen;
1877 unsigned long val;
1878 struct l2cap_conf_rfc rfc;
1879
1880 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1881
1882 while (len >= L2CAP_CONF_OPT_SIZE) {
1883 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1884
1885 switch (type) {
1886 case L2CAP_CONF_MTU:
1887 if (val < L2CAP_DEFAULT_MIN_MTU) {
1888 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001889 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001890 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001891 pi->imtu = val;
1892 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001893 break;
1894
1895 case L2CAP_CONF_FLUSH_TO:
1896 pi->flush_to = val;
1897 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1898 2, pi->flush_to);
1899 break;
1900
1901 case L2CAP_CONF_RFC:
1902 if (olen == sizeof(rfc))
1903 memcpy(&rfc, (void *)val, olen);
1904
1905 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1906 rfc.mode != pi->mode)
1907 return -ECONNREFUSED;
1908
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001909 pi->fcs = 0;
1910
1911 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1912 sizeof(rfc), (unsigned long) &rfc);
1913 break;
1914 }
1915 }
1916
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001917 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1918 return -ECONNREFUSED;
1919
1920 pi->mode = rfc.mode;
1921
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001922 if (*result == L2CAP_CONF_SUCCESS) {
1923 switch (rfc.mode) {
1924 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001925 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1926 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001927 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001928 break;
1929 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001930 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001931 }
1932 }
1933
1934 req->dcid = cpu_to_le16(pi->dcid);
1935 req->flags = cpu_to_le16(0x0000);
1936
1937 return ptr - data;
1938}
1939
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001940static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941{
1942 struct l2cap_conf_rsp *rsp = data;
1943 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001945 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001947 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001948 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001949 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950
1951 return ptr - data;
1952}
1953
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001954void __l2cap_connect_rsp_defer(struct sock *sk)
1955{
1956 struct l2cap_conn_rsp rsp;
1957 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1958 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
1959 u8 buf[128];
1960
1961 sk->sk_state = BT_CONFIG;
1962
1963 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1964 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1965 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1966 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1967 l2cap_send_cmd(conn, chan->ident,
1968 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1969
1970 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
1971 return;
1972
1973 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
1974 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1975 l2cap_build_conf_req(chan, buf), buf);
1976 chan->num_conf_req++;
1977}
1978
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001979static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1980{
1981 struct l2cap_pinfo *pi = l2cap_pi(sk);
1982 int type, olen;
1983 unsigned long val;
1984 struct l2cap_conf_rfc rfc;
1985
1986 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1987
1988 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1989 return;
1990
1991 while (len >= L2CAP_CONF_OPT_SIZE) {
1992 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1993
1994 switch (type) {
1995 case L2CAP_CONF_RFC:
1996 if (olen == sizeof(rfc))
1997 memcpy(&rfc, (void *)val, olen);
1998 goto done;
1999 }
2000 }
2001
2002done:
2003 switch (rfc.mode) {
2004 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002005 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2006 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002007 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2008 break;
2009 case L2CAP_MODE_STREAMING:
2010 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2011 }
2012}
2013
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002014static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2015{
2016 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2017
2018 if (rej->reason != 0x0000)
2019 return 0;
2020
2021 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2022 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002023 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002024
2025 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002026 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002027
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002028 l2cap_conn_start(conn);
2029 }
2030
2031 return 0;
2032}
2033
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2035{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2037 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002038 struct l2cap_chan *chan = NULL;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002039 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002040 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041
2042 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002043 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044
2045 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2046
2047 /* Check if we have socket listening on psm */
2048 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2049 if (!parent) {
2050 result = L2CAP_CR_BAD_PSM;
2051 goto sendresp;
2052 }
2053
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002054 bh_lock_sock(parent);
2055
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002056 /* Check if the ACL is secure enough (if not SDP) */
2057 if (psm != cpu_to_le16(0x0001) &&
2058 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002059 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002060 result = L2CAP_CR_SEC_BLOCK;
2061 goto response;
2062 }
2063
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 result = L2CAP_CR_NO_MEM;
2065
2066 /* Check for backlog size */
2067 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002068 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069 goto response;
2070 }
2071
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002072 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073 if (!sk)
2074 goto response;
2075
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002076 chan = l2cap_chan_alloc(sk);
2077 if (!chan) {
2078 l2cap_sock_kill(sk);
2079 goto response;
2080 }
2081
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002082 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083
2084 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002085 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2086 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 sock_set_flag(sk, SOCK_ZAPPED);
2088 l2cap_sock_kill(sk);
2089 goto response;
2090 }
2091
2092 hci_conn_hold(conn->hcon);
2093
2094 l2cap_sock_init(sk, parent);
2095 bacpy(&bt_sk(sk)->src, conn->src);
2096 bacpy(&bt_sk(sk)->dst, conn->dst);
2097 l2cap_pi(sk)->psm = psm;
2098 l2cap_pi(sk)->dcid = scid;
2099
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002100 bt_accept_enqueue(parent, sk);
2101
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002102 __l2cap_chan_add(conn, chan);
2103
2104 l2cap_pi(sk)->chan = chan;
2105
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 dcid = l2cap_pi(sk)->scid;
2107
2108 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2109
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002110 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111
Marcel Holtmann984947d2009-02-06 23:35:19 +01002112 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002113 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002114 if (bt_sk(sk)->defer_setup) {
2115 sk->sk_state = BT_CONNECT2;
2116 result = L2CAP_CR_PEND;
2117 status = L2CAP_CS_AUTHOR_PEND;
2118 parent->sk_data_ready(parent, 0);
2119 } else {
2120 sk->sk_state = BT_CONFIG;
2121 result = L2CAP_CR_SUCCESS;
2122 status = L2CAP_CS_NO_INFO;
2123 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002124 } else {
2125 sk->sk_state = BT_CONNECT2;
2126 result = L2CAP_CR_PEND;
2127 status = L2CAP_CS_AUTHEN_PEND;
2128 }
2129 } else {
2130 sk->sk_state = BT_CONNECT2;
2131 result = L2CAP_CR_PEND;
2132 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 }
2134
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002135 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136
2137response:
2138 bh_unlock_sock(parent);
2139
2140sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002141 rsp.scid = cpu_to_le16(scid);
2142 rsp.dcid = cpu_to_le16(dcid);
2143 rsp.result = cpu_to_le16(result);
2144 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002146
2147 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2148 struct l2cap_info_req info;
2149 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2150
2151 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2152 conn->info_ident = l2cap_get_ident(conn);
2153
2154 mod_timer(&conn->info_timer, jiffies +
2155 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2156
2157 l2cap_send_cmd(conn, conn->info_ident,
2158 L2CAP_INFO_REQ, sizeof(info), &info);
2159 }
2160
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002161 if (chan && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002162 result == L2CAP_CR_SUCCESS) {
2163 u8 buf[128];
2164 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2165 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002166 l2cap_build_conf_req(chan, buf), buf);
2167 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002168 }
2169
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170 return 0;
2171}
2172
2173static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2174{
2175 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2176 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002177 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 struct sock *sk;
2179 u8 req[128];
2180
2181 scid = __le16_to_cpu(rsp->scid);
2182 dcid = __le16_to_cpu(rsp->dcid);
2183 result = __le16_to_cpu(rsp->result);
2184 status = __le16_to_cpu(rsp->status);
2185
2186 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2187
2188 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002189 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002190 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002191 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002193 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002194 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002195 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 }
2197
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002198 sk = chan->sk;
2199
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 switch (result) {
2201 case L2CAP_CR_SUCCESS:
2202 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002203 chan->ident = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002205 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2206
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002207 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2208 break;
2209
2210 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2211
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002213 l2cap_build_conf_req(chan, req), req);
2214 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 break;
2216
2217 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002218 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219 break;
2220
2221 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002222 /* don't delete l2cap channel if sk is owned by user */
2223 if (sock_owned_by_user(sk)) {
2224 sk->sk_state = BT_DISCONN;
2225 l2cap_sock_clear_timer(sk);
2226 l2cap_sock_set_timer(sk, HZ / 5);
2227 break;
2228 }
2229
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002230 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231 break;
2232 }
2233
2234 bh_unlock_sock(sk);
2235 return 0;
2236}
2237
Mat Martineau8c462b62010-08-24 15:35:42 -07002238static inline void set_default_fcs(struct l2cap_pinfo *pi)
2239{
2240 /* FCS is enabled only in ERTM or streaming mode, if one or both
2241 * sides request it.
2242 */
2243 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2244 pi->fcs = L2CAP_FCS_NONE;
2245 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2246 pi->fcs = L2CAP_FCS_CRC16;
2247}
2248
Al Viro88219a02007-07-29 00:17:25 -07002249static 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 -07002250{
2251 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2252 u16 dcid, flags;
2253 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002254 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002256 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257
2258 dcid = __le16_to_cpu(req->dcid);
2259 flags = __le16_to_cpu(req->flags);
2260
2261 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2262
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002263 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002264 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 return -ENOENT;
2266
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002267 sk = chan->sk;
2268
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002269 if (sk->sk_state != BT_CONFIG) {
2270 struct l2cap_cmd_rej rej;
2271
2272 rej.reason = cpu_to_le16(0x0002);
2273 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2274 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002275 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002276 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002277
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002278 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002279 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002280 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002281 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2282 l2cap_build_conf_rsp(sk, rsp,
2283 L2CAP_CONF_REJECT, flags), rsp);
2284 goto unlock;
2285 }
2286
2287 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002288 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2289 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290
2291 if (flags & 0x0001) {
2292 /* Incomplete config. Send empty response. */
2293 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002294 l2cap_build_conf_rsp(sk, rsp,
2295 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 goto unlock;
2297 }
2298
2299 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002300 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002301 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002302 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002304 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002306 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002307 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002308
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002309 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002310 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002311
Marcel Holtmann876d9482007-10-20 13:35:42 +02002312 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2313 goto unlock;
2314
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002316 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002317
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002319
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002320 chan->next_tx_seq = 0;
2321 chan->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002322 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002323 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002324 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002325
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002327 goto unlock;
2328 }
2329
2330 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002331 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002332 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002334 l2cap_build_conf_req(chan, buf), buf);
2335 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336 }
2337
2338unlock:
2339 bh_unlock_sock(sk);
2340 return 0;
2341}
2342
2343static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2344{
2345 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2346 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002347 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002349 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350
2351 scid = __le16_to_cpu(rsp->scid);
2352 flags = __le16_to_cpu(rsp->flags);
2353 result = __le16_to_cpu(rsp->result);
2354
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002355 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2356 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002358 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002359 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 return 0;
2361
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002362 sk = chan->sk;
2363
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364 switch (result) {
2365 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002366 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367 break;
2368
2369 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002370 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002371 char req[64];
2372
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002373 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002374 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002375 goto done;
2376 }
2377
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002378 /* throw out any old stored conf requests */
2379 result = L2CAP_CONF_SUCCESS;
2380 len = l2cap_parse_conf_rsp(sk, rsp->data,
2381 len, req, &result);
2382 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002383 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002384 goto done;
2385 }
2386
2387 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2388 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002389 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002390 if (result != L2CAP_CONF_SUCCESS)
2391 goto done;
2392 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393 }
2394
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002395 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002396 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002398 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 goto done;
2400 }
2401
2402 if (flags & 0x01)
2403 goto done;
2404
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2406
2407 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002408 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002409
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002411 chan->next_tx_seq = 0;
2412 chan->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002413 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002414 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002415 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002416
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 l2cap_chan_ready(sk);
2418 }
2419
2420done:
2421 bh_unlock_sock(sk);
2422 return 0;
2423}
2424
2425static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2426{
2427 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2428 struct l2cap_disconn_rsp rsp;
2429 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002430 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431 struct sock *sk;
2432
2433 scid = __le16_to_cpu(req->scid);
2434 dcid = __le16_to_cpu(req->dcid);
2435
2436 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2437
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002438 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002439 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440 return 0;
2441
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002442 sk = chan->sk;
2443
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002444 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2445 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2447
2448 sk->sk_shutdown = SHUTDOWN_MASK;
2449
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002450 /* don't delete l2cap channel if sk is owned by user */
2451 if (sock_owned_by_user(sk)) {
2452 sk->sk_state = BT_DISCONN;
2453 l2cap_sock_clear_timer(sk);
2454 l2cap_sock_set_timer(sk, HZ / 5);
2455 bh_unlock_sock(sk);
2456 return 0;
2457 }
2458
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002459 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460 bh_unlock_sock(sk);
2461
2462 l2cap_sock_kill(sk);
2463 return 0;
2464}
2465
2466static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2467{
2468 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2469 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002470 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471 struct sock *sk;
2472
2473 scid = __le16_to_cpu(rsp->scid);
2474 dcid = __le16_to_cpu(rsp->dcid);
2475
2476 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2477
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002478 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002479 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 return 0;
2481
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002482 sk = chan->sk;
2483
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002484 /* don't delete l2cap channel if sk is owned by user */
2485 if (sock_owned_by_user(sk)) {
2486 sk->sk_state = BT_DISCONN;
2487 l2cap_sock_clear_timer(sk);
2488 l2cap_sock_set_timer(sk, HZ / 5);
2489 bh_unlock_sock(sk);
2490 return 0;
2491 }
2492
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002493 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494 bh_unlock_sock(sk);
2495
2496 l2cap_sock_kill(sk);
2497 return 0;
2498}
2499
2500static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2501{
2502 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 u16 type;
2504
2505 type = __le16_to_cpu(req->type);
2506
2507 BT_DBG("type 0x%4.4x", type);
2508
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002509 if (type == L2CAP_IT_FEAT_MASK) {
2510 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002511 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002512 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2513 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2514 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002515 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002516 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2517 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002518 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002519 l2cap_send_cmd(conn, cmd->ident,
2520 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002521 } else if (type == L2CAP_IT_FIXED_CHAN) {
2522 u8 buf[12];
2523 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2524 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2525 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2526 memcpy(buf + 4, l2cap_fixed_chan, 8);
2527 l2cap_send_cmd(conn, cmd->ident,
2528 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002529 } else {
2530 struct l2cap_info_rsp rsp;
2531 rsp.type = cpu_to_le16(type);
2532 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2533 l2cap_send_cmd(conn, cmd->ident,
2534 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2535 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536
2537 return 0;
2538}
2539
2540static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2541{
2542 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2543 u16 type, result;
2544
2545 type = __le16_to_cpu(rsp->type);
2546 result = __le16_to_cpu(rsp->result);
2547
2548 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2549
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002550 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2551 if (cmd->ident != conn->info_ident ||
2552 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2553 return 0;
2554
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002555 del_timer(&conn->info_timer);
2556
Ville Tervoadb08ed2010-08-04 09:43:33 +03002557 if (result != L2CAP_IR_SUCCESS) {
2558 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2559 conn->info_ident = 0;
2560
2561 l2cap_conn_start(conn);
2562
2563 return 0;
2564 }
2565
Marcel Holtmann984947d2009-02-06 23:35:19 +01002566 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002567 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002568
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002569 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002570 struct l2cap_info_req req;
2571 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2572
2573 conn->info_ident = l2cap_get_ident(conn);
2574
2575 l2cap_send_cmd(conn, conn->info_ident,
2576 L2CAP_INFO_REQ, sizeof(req), &req);
2577 } else {
2578 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2579 conn->info_ident = 0;
2580
2581 l2cap_conn_start(conn);
2582 }
2583 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002584 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002585 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002586
2587 l2cap_conn_start(conn);
2588 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002589
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590 return 0;
2591}
2592
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002593static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002594 u16 to_multiplier)
2595{
2596 u16 max_latency;
2597
2598 if (min > max || min < 6 || max > 3200)
2599 return -EINVAL;
2600
2601 if (to_multiplier < 10 || to_multiplier > 3200)
2602 return -EINVAL;
2603
2604 if (max >= to_multiplier * 8)
2605 return -EINVAL;
2606
2607 max_latency = (to_multiplier * 8 / max) - 1;
2608 if (latency > 499 || latency > max_latency)
2609 return -EINVAL;
2610
2611 return 0;
2612}
2613
2614static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2615 struct l2cap_cmd_hdr *cmd, u8 *data)
2616{
2617 struct hci_conn *hcon = conn->hcon;
2618 struct l2cap_conn_param_update_req *req;
2619 struct l2cap_conn_param_update_rsp rsp;
2620 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002621 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002622
2623 if (!(hcon->link_mode & HCI_LM_MASTER))
2624 return -EINVAL;
2625
2626 cmd_len = __le16_to_cpu(cmd->len);
2627 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2628 return -EPROTO;
2629
2630 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002631 min = __le16_to_cpu(req->min);
2632 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002633 latency = __le16_to_cpu(req->latency);
2634 to_multiplier = __le16_to_cpu(req->to_multiplier);
2635
2636 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2637 min, max, latency, to_multiplier);
2638
2639 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002640
2641 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2642 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002643 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2644 else
2645 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2646
2647 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2648 sizeof(rsp), &rsp);
2649
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002650 if (!err)
2651 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2652
Claudio Takahaside731152011-02-11 19:28:55 -02002653 return 0;
2654}
2655
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002656static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2657 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2658{
2659 int err = 0;
2660
2661 switch (cmd->code) {
2662 case L2CAP_COMMAND_REJ:
2663 l2cap_command_rej(conn, cmd, data);
2664 break;
2665
2666 case L2CAP_CONN_REQ:
2667 err = l2cap_connect_req(conn, cmd, data);
2668 break;
2669
2670 case L2CAP_CONN_RSP:
2671 err = l2cap_connect_rsp(conn, cmd, data);
2672 break;
2673
2674 case L2CAP_CONF_REQ:
2675 err = l2cap_config_req(conn, cmd, cmd_len, data);
2676 break;
2677
2678 case L2CAP_CONF_RSP:
2679 err = l2cap_config_rsp(conn, cmd, data);
2680 break;
2681
2682 case L2CAP_DISCONN_REQ:
2683 err = l2cap_disconnect_req(conn, cmd, data);
2684 break;
2685
2686 case L2CAP_DISCONN_RSP:
2687 err = l2cap_disconnect_rsp(conn, cmd, data);
2688 break;
2689
2690 case L2CAP_ECHO_REQ:
2691 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2692 break;
2693
2694 case L2CAP_ECHO_RSP:
2695 break;
2696
2697 case L2CAP_INFO_REQ:
2698 err = l2cap_information_req(conn, cmd, data);
2699 break;
2700
2701 case L2CAP_INFO_RSP:
2702 err = l2cap_information_rsp(conn, cmd, data);
2703 break;
2704
2705 default:
2706 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2707 err = -EINVAL;
2708 break;
2709 }
2710
2711 return err;
2712}
2713
2714static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2715 struct l2cap_cmd_hdr *cmd, u8 *data)
2716{
2717 switch (cmd->code) {
2718 case L2CAP_COMMAND_REJ:
2719 return 0;
2720
2721 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002722 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002723
2724 case L2CAP_CONN_PARAM_UPDATE_RSP:
2725 return 0;
2726
2727 default:
2728 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2729 return -EINVAL;
2730 }
2731}
2732
2733static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2734 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735{
2736 u8 *data = skb->data;
2737 int len = skb->len;
2738 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002739 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740
2741 l2cap_raw_recv(conn, skb);
2742
2743 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002744 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2746 data += L2CAP_CMD_HDR_SIZE;
2747 len -= L2CAP_CMD_HDR_SIZE;
2748
Al Viro88219a02007-07-29 00:17:25 -07002749 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750
Al Viro88219a02007-07-29 00:17:25 -07002751 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 -07002752
Al Viro88219a02007-07-29 00:17:25 -07002753 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754 BT_DBG("corrupted command");
2755 break;
2756 }
2757
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002758 if (conn->hcon->type == LE_LINK)
2759 err = l2cap_le_sig_cmd(conn, &cmd, data);
2760 else
2761 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762
2763 if (err) {
2764 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002765
2766 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767
2768 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002769 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2771 }
2772
Al Viro88219a02007-07-29 00:17:25 -07002773 data += cmd_len;
2774 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 }
2776
2777 kfree_skb(skb);
2778}
2779
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002780static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2781{
2782 u16 our_fcs, rcv_fcs;
2783 int hdr_size = L2CAP_HDR_SIZE + 2;
2784
2785 if (pi->fcs == L2CAP_FCS_CRC16) {
2786 skb_trim(skb, skb->len - 2);
2787 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2788 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2789
2790 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002791 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002792 }
2793 return 0;
2794}
2795
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002796static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002797{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002798 u16 control = 0;
2799
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002800 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002801
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002802 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002803
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002804 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002805 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002806 l2cap_send_sframe(chan, control);
2807 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002808 }
2809
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002810 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2811 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002812
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002813 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002814
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002815 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002816 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002817 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002818 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002819 }
2820}
2821
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002822static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u8 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002823{
2824 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002825 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002826
2827 bt_cb(skb)->tx_seq = tx_seq;
2828 bt_cb(skb)->sar = sar;
2829
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002830 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002831 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002832 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002833 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002834 }
2835
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002836 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002837 if (tx_seq_offset < 0)
2838 tx_seq_offset += 64;
2839
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002840 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002841 if (bt_cb(next_skb)->tx_seq == tx_seq)
2842 return -EINVAL;
2843
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002844 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002845 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002846 if (next_tx_seq_offset < 0)
2847 next_tx_seq_offset += 64;
2848
2849 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002850 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002851 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002852 }
2853
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002854 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002855 break;
2856
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002857 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002858
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002859 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002860
2861 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002862}
2863
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002864static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002865{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002866 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002867 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002868 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002869
2870 switch (control & L2CAP_CTRL_SAR) {
2871 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002872 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002873 goto drop;
2874
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002875 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002876 if (!err)
2877 return err;
2878
2879 break;
2880
2881 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002882 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002883 goto drop;
2884
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002885 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002886
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002887 if (chan->sdu_len > pi->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002888 goto disconnect;
2889
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002890 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
2891 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002892 return -ENOMEM;
2893
2894 /* pull sdu_len bytes only after alloc, because of Local Busy
2895 * condition we have to be sure that this will be executed
2896 * only once, i.e., when alloc does not fail */
2897 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002898
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002899 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002900
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002901 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002902 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002903 break;
2904
2905 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002906 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002907 goto disconnect;
2908
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002909 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002910 goto disconnect;
2911
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002912 chan->partial_sdu_len += skb->len;
2913 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002914 goto drop;
2915
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002916 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002917
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002918 break;
2919
2920 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002921 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002922 goto disconnect;
2923
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002924 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002925 goto disconnect;
2926
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002927 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002928 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002929
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002930 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002931 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002932
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002933 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002934 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002935
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002936 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002937 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002938
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002939 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002940 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002941 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002942 return -ENOMEM;
2943 }
2944
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002945 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002946 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002947 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002948 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002949 return err;
2950 }
2951
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002952 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2953 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002954
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002955 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002956 break;
2957 }
2958
2959 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002960 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002961
2962drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002963 kfree_skb(chan->sdu);
2964 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002965
2966disconnect:
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002967 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002968 kfree_skb(skb);
2969 return 0;
2970}
2971
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002972static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002973{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002974 struct sk_buff *skb;
2975 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002976 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002977
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002978 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002979 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002980 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002981 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002982 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002983 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002984 }
2985
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002986 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002987 }
2988
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002989 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002990 goto done;
2991
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002992 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002993 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002994 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002995 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002996
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002997 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002998 __mod_monitor_timer();
2999
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003000 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003001
3002done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003003 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3004 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003005
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003006 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003007
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003008 return 0;
3009}
3010
3011static void l2cap_busy_work(struct work_struct *work)
3012{
3013 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003014 struct l2cap_chan *chan =
3015 container_of(work, struct l2cap_chan, busy_work);
3016 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003017 int n_tries = 0, timeo = HZ/5, err;
3018 struct sk_buff *skb;
3019
3020 lock_sock(sk);
3021
3022 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003023 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003024 set_current_state(TASK_INTERRUPTIBLE);
3025
3026 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3027 err = -EBUSY;
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003028 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003029 break;
3030 }
3031
3032 if (!timeo)
3033 timeo = HZ/5;
3034
3035 if (signal_pending(current)) {
3036 err = sock_intr_errno(timeo);
3037 break;
3038 }
3039
3040 release_sock(sk);
3041 timeo = schedule_timeout(timeo);
3042 lock_sock(sk);
3043
3044 err = sock_error(sk);
3045 if (err)
3046 break;
3047
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003048 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003049 break;
3050 }
3051
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003052 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003053 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003054
3055 release_sock(sk);
3056}
3057
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003058static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003059{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003060 int sctrl, err;
3061
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003062 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003063 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003064 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003065 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003066
3067
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003068 }
3069
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003070 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003071 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003072 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003073 return err;
3074 }
3075
3076 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003077 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003078
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003079 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003080 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003081 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003082
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003083 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003084 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003085 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003086
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003087 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003088
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003089 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003090
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003091 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003092
3093 return err;
3094}
3095
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003096static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003097{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003098 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003099 struct sk_buff *_skb;
3100 int err = -EINVAL;
3101
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003102 /*
3103 * TODO: We have to notify the userland if some data is lost with the
3104 * Streaming Mode.
3105 */
3106
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003107 switch (control & L2CAP_CTRL_SAR) {
3108 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003109 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003110 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003111 break;
3112 }
3113
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003114 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003115 if (!err)
3116 return 0;
3117
3118 break;
3119
3120 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003121 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003122 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003123 break;
3124 }
3125
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003126 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003127 skb_pull(skb, 2);
3128
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003129 if (chan->sdu_len > pi->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003130 err = -EMSGSIZE;
3131 break;
3132 }
3133
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003134 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3135 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003136 err = -ENOMEM;
3137 break;
3138 }
3139
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003140 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003141
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003142 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003143 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003144 err = 0;
3145 break;
3146
3147 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003148 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003149 break;
3150
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003151 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003152
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003153 chan->partial_sdu_len += skb->len;
3154 if (chan->partial_sdu_len > chan->sdu_len)
3155 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003156 else
3157 err = 0;
3158
3159 break;
3160
3161 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003162 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003163 break;
3164
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003165 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003166
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003167 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003168 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003169
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003170 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003171 goto drop;
3172
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003173 if (chan->partial_sdu_len == chan->sdu_len) {
3174 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003175 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003176 if (err < 0)
3177 kfree_skb(_skb);
3178 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003179 err = 0;
3180
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003181drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003182 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003183 break;
3184 }
3185
3186 kfree_skb(skb);
3187 return err;
3188}
3189
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003190static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003191{
3192 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003193 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003194
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003195 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003196 if (bt_cb(skb)->tx_seq != tx_seq)
3197 break;
3198
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003199 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003200 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003201 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003202 chan->buffer_seq_srej =
3203 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003204 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003205 }
3206}
3207
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003208static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003209{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003210 struct srej_list *l, *tmp;
3211 u16 control;
3212
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003213 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003214 if (l->tx_seq == tx_seq) {
3215 list_del(&l->list);
3216 kfree(l);
3217 return;
3218 }
3219 control = L2CAP_SUPER_SELECT_REJECT;
3220 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003221 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003222 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003223 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003224 }
3225}
3226
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003227static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003228{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003229 struct srej_list *new;
3230 u16 control;
3231
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003232 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003233 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003234 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003235 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003236
3237 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003238 new->tx_seq = chan->expected_tx_seq;
3239 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003240 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003241 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003242 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003243}
3244
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003245static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003246{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003247 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003248 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003249 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003250 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003251 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003252 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003253 int err = 0;
3254
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003255 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3256 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003257
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003258 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003259 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003260 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003261 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003262 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003263 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003264 }
3265
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003266 chan->expected_ack_seq = req_seq;
3267 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003268
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003269 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003270 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003271
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003272 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003273 if (tx_seq_offset < 0)
3274 tx_seq_offset += 64;
3275
3276 /* invalid tx_seq */
3277 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003278 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003279 goto drop;
3280 }
3281
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003282 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003283 goto drop;
3284
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003285 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003286 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003287
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003288 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003289 struct srej_list, list);
3290 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003291 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003292 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003293
3294 list_del(&first->list);
3295 kfree(first);
3296
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003297 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003298 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003299 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3300 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003301 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003302 }
3303 } else {
3304 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003305
3306 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003307 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003308 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003309
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003310 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003311 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003312 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003313 return 0;
3314 }
3315 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003316 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003317 }
3318 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003319 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003320 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003321 if (expected_tx_seq_offset < 0)
3322 expected_tx_seq_offset += 64;
3323
3324 /* duplicated tx_seq */
3325 if (tx_seq_offset < expected_tx_seq_offset)
3326 goto drop;
3327
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003328 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003329
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003330 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003331
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003332 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003333 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003334
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003335 __skb_queue_head_init(&chan->srej_q);
3336 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003337 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003338
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003339 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003340
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003341 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003342
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003343 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003344 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003345 return 0;
3346
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003347expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003348 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003349
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003350 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003351 bt_cb(skb)->tx_seq = tx_seq;
3352 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003353 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003354 return 0;
3355 }
3356
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003357 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003358 if (err < 0)
3359 return 0;
3360
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003361 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003362 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3363 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003364 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003365 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003366 }
3367
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003368 __mod_ack_timer();
3369
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003370 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3371 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003372 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003373
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003374 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003375
3376drop:
3377 kfree_skb(skb);
3378 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003379}
3380
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003381static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003382{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003383 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003384 rx_control);
3385
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003386 chan->expected_ack_seq = __get_reqseq(rx_control);
3387 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003388
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003389 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003390 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3391 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3392 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003393 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003394 __mod_retrans_timer();
3395
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003396 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3397 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003398 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003399 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003400 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003401
3402 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003403 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003404
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003405 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3406 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003407 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003408 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003409
3410 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003411 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003412 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003413 __mod_retrans_timer();
3414
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003415 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3416 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3417 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003418 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003419 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003420 }
3421}
3422
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003423static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003424{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003425 u8 tx_seq = __get_reqseq(rx_control);
3426
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003427 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003428
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003429 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003430
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003431 chan->expected_ack_seq = tx_seq;
3432 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003433
3434 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003435 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3436 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003437 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003438 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003439 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003440 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003441
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003442 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3443 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003444 }
3445}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003446static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003447{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003448 u8 tx_seq = __get_reqseq(rx_control);
3449
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003450 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003451
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003452 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003453
3454 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003455 chan->expected_ack_seq = tx_seq;
3456 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003457
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003458 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3459 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003460
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003461 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003462
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003463 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003464 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003465 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003466 }
3467 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003468 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003469 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003470 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003471 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003472 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003473 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003474 l2cap_retransmit_one_frame(chan, tx_seq);
3475 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003476 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003477 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003478 }
3479 }
3480}
3481
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003482static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003483{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003484 u8 tx_seq = __get_reqseq(rx_control);
3485
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003486 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003487
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003488 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003489 chan->expected_ack_seq = tx_seq;
3490 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003491
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003492 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003493 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003494
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003495 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003496 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003497 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003498 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003499 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003500 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003501
3502 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003503 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003504 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003505 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003506}
3507
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003508static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003509{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003510 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003511
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003512 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003513 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003514 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003515 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003516 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003517 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003518 }
3519
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003520 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3521 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003522 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003523 break;
3524
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003525 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003526 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003527 break;
3528
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003529 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003530 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003531 break;
3532
3533 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003534 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003535 break;
3536 }
3537
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003538 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003539 return 0;
3540}
3541
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003542static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3543{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003544 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003545 struct l2cap_pinfo *pi = l2cap_pi(sk);
3546 u16 control;
3547 u8 req_seq;
3548 int len, next_tx_seq_offset, req_seq_offset;
3549
3550 control = get_unaligned_le16(skb->data);
3551 skb_pull(skb, 2);
3552 len = skb->len;
3553
3554 /*
3555 * We can just drop the corrupted I-frame here.
3556 * Receiver will miss it and start proper recovery
3557 * procedures and ask retransmission.
3558 */
3559 if (l2cap_check_fcs(pi, skb))
3560 goto drop;
3561
3562 if (__is_sar_start(control) && __is_iframe(control))
3563 len -= 2;
3564
3565 if (pi->fcs == L2CAP_FCS_CRC16)
3566 len -= 2;
3567
3568 if (len > pi->mps) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003569 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003570 goto drop;
3571 }
3572
3573 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003574 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003575 if (req_seq_offset < 0)
3576 req_seq_offset += 64;
3577
3578 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003579 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003580 if (next_tx_seq_offset < 0)
3581 next_tx_seq_offset += 64;
3582
3583 /* check for invalid req-seq */
3584 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003585 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003586 goto drop;
3587 }
3588
3589 if (__is_iframe(control)) {
3590 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003591 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003592 goto drop;
3593 }
3594
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003595 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003596 } else {
3597 if (len != 0) {
3598 BT_ERR("%d", len);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003599 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003600 goto drop;
3601 }
3602
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003603 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003604 }
3605
3606 return 0;
3607
3608drop:
3609 kfree_skb(skb);
3610 return 0;
3611}
3612
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3614{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003615 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003617 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003618 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003619 u8 tx_seq;
3620 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003622 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003623 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624 BT_DBG("unknown cid 0x%4.4x", cid);
3625 goto drop;
3626 }
3627
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003628 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003629 pi = l2cap_pi(sk);
3630
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003631 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632
3633 if (sk->sk_state != BT_CONNECTED)
3634 goto drop;
3635
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003636 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003637 case L2CAP_MODE_BASIC:
3638 /* If socket recv buffers overflows we drop data here
3639 * which is *bad* because L2CAP has to be reliable.
3640 * But we don't have any other choice. L2CAP doesn't
3641 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003643 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003644 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003646 if (!sock_queue_rcv_skb(sk, skb))
3647 goto done;
3648 break;
3649
3650 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003651 if (!sock_owned_by_user(sk)) {
3652 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003653 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003654 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003655 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003656 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003657
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003658 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003659
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003660 case L2CAP_MODE_STREAMING:
3661 control = get_unaligned_le16(skb->data);
3662 skb_pull(skb, 2);
3663 len = skb->len;
3664
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003665 if (l2cap_check_fcs(pi, skb))
3666 goto drop;
3667
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003668 if (__is_sar_start(control))
3669 len -= 2;
3670
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003671 if (pi->fcs == L2CAP_FCS_CRC16)
3672 len -= 2;
3673
Nathan Holstein51893f82010-06-09 15:46:25 -04003674 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003675 goto drop;
3676
3677 tx_seq = __get_txseq(control);
3678
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003679 if (chan->expected_tx_seq == tx_seq)
3680 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003681 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003682 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003683
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003684 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003685
3686 goto done;
3687
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003688 default:
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003689 BT_DBG("chan %p: bad mode 0x%2.2x", chan, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003690 break;
3691 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692
3693drop:
3694 kfree_skb(skb);
3695
3696done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003697 if (sk)
3698 bh_unlock_sock(sk);
3699
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700 return 0;
3701}
3702
Al Viro8e036fc2007-07-29 00:16:36 -07003703static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704{
3705 struct sock *sk;
3706
3707 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3708 if (!sk)
3709 goto drop;
3710
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003711 bh_lock_sock(sk);
3712
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713 BT_DBG("sk %p, len %d", sk, skb->len);
3714
3715 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3716 goto drop;
3717
3718 if (l2cap_pi(sk)->imtu < skb->len)
3719 goto drop;
3720
3721 if (!sock_queue_rcv_skb(sk, skb))
3722 goto done;
3723
3724drop:
3725 kfree_skb(skb);
3726
3727done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003728 if (sk)
3729 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730 return 0;
3731}
3732
3733static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3734{
3735 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003736 u16 cid, len;
3737 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003738
3739 skb_pull(skb, L2CAP_HDR_SIZE);
3740 cid = __le16_to_cpu(lh->cid);
3741 len = __le16_to_cpu(lh->len);
3742
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003743 if (len != skb->len) {
3744 kfree_skb(skb);
3745 return;
3746 }
3747
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3749
3750 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003751 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003752 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753 l2cap_sig_channel(conn, skb);
3754 break;
3755
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003756 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003757 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758 skb_pull(skb, 2);
3759 l2cap_conless_channel(conn, psm, skb);
3760 break;
3761
3762 default:
3763 l2cap_data_channel(conn, cid, skb);
3764 break;
3765 }
3766}
3767
3768/* ---- L2CAP interface with lower layer (HCI) ---- */
3769
3770static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3771{
3772 int exact = 0, lm1 = 0, lm2 = 0;
3773 register struct sock *sk;
3774 struct hlist_node *node;
3775
3776 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003777 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778
3779 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3780
3781 /* Find listening sockets and check their link_mode */
3782 read_lock(&l2cap_sk_list.lock);
3783 sk_for_each(sk, node, &l2cap_sk_list.head) {
3784 if (sk->sk_state != BT_LISTEN)
3785 continue;
3786
3787 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003788 lm1 |= HCI_LM_ACCEPT;
3789 if (l2cap_pi(sk)->role_switch)
3790 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003792 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3793 lm2 |= HCI_LM_ACCEPT;
3794 if (l2cap_pi(sk)->role_switch)
3795 lm2 |= HCI_LM_MASTER;
3796 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797 }
3798 read_unlock(&l2cap_sk_list.lock);
3799
3800 return exact ? lm1 : lm2;
3801}
3802
3803static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3804{
Marcel Holtmann01394182006-07-03 10:02:46 +02003805 struct l2cap_conn *conn;
3806
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3808
Ville Tervoacd7d372011-02-10 22:38:49 -03003809 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003810 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003811
3812 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813 conn = l2cap_conn_add(hcon, status);
3814 if (conn)
3815 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003816 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817 l2cap_conn_del(hcon, bt_err(status));
3818
3819 return 0;
3820}
3821
Marcel Holtmann2950f212009-02-12 14:02:50 +01003822static int l2cap_disconn_ind(struct hci_conn *hcon)
3823{
3824 struct l2cap_conn *conn = hcon->l2cap_data;
3825
3826 BT_DBG("hcon %p", hcon);
3827
3828 if (hcon->type != ACL_LINK || !conn)
3829 return 0x13;
3830
3831 return conn->disc_reason;
3832}
3833
3834static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835{
3836 BT_DBG("hcon %p reason %d", hcon, reason);
3837
Ville Tervoacd7d372011-02-10 22:38:49 -03003838 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003839 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840
3841 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003842
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843 return 0;
3844}
3845
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003846static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3847{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003848 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003849 return;
3850
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003851 if (encrypt == 0x00) {
3852 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3853 l2cap_sock_clear_timer(sk);
3854 l2cap_sock_set_timer(sk, HZ * 5);
3855 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3856 __l2cap_sock_close(sk, ECONNREFUSED);
3857 } else {
3858 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3859 l2cap_sock_clear_timer(sk);
3860 }
3861}
3862
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003863static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003865 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003866 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867
Marcel Holtmann01394182006-07-03 10:02:46 +02003868 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003870
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871 BT_DBG("conn %p", conn);
3872
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003873 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003875 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003876 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003877
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878 bh_lock_sock(sk);
3879
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003880 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3881 bh_unlock_sock(sk);
3882 continue;
3883 }
3884
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003885 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003886 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003887 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003888 bh_unlock_sock(sk);
3889 continue;
3890 }
3891
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003892 if (sk->sk_state == BT_CONNECT) {
3893 if (!status) {
3894 struct l2cap_conn_req req;
3895 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3896 req.psm = l2cap_pi(sk)->psm;
3897
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003898 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003899 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003900
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003901 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003902 L2CAP_CONN_REQ, sizeof(req), &req);
3903 } else {
3904 l2cap_sock_clear_timer(sk);
3905 l2cap_sock_set_timer(sk, HZ / 10);
3906 }
3907 } else if (sk->sk_state == BT_CONNECT2) {
3908 struct l2cap_conn_rsp rsp;
3909 __u16 result;
3910
3911 if (!status) {
3912 sk->sk_state = BT_CONFIG;
3913 result = L2CAP_CR_SUCCESS;
3914 } else {
3915 sk->sk_state = BT_DISCONN;
3916 l2cap_sock_set_timer(sk, HZ / 10);
3917 result = L2CAP_CR_SEC_BLOCK;
3918 }
3919
3920 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3921 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3922 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003923 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003924 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
3925 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926 }
3927
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928 bh_unlock_sock(sk);
3929 }
3930
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003931 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003932
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933 return 0;
3934}
3935
3936static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3937{
3938 struct l2cap_conn *conn = hcon->l2cap_data;
3939
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003940 if (!conn)
3941 conn = l2cap_conn_add(hcon, 0);
3942
3943 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944 goto drop;
3945
3946 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3947
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003948 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003950 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003951 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003952 int len;
3953
3954 if (conn->rx_len) {
3955 BT_ERR("Unexpected start frame (len %d)", skb->len);
3956 kfree_skb(conn->rx_skb);
3957 conn->rx_skb = NULL;
3958 conn->rx_len = 0;
3959 l2cap_conn_unreliable(conn, ECOMM);
3960 }
3961
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003962 /* Start fragment always begin with Basic L2CAP header */
3963 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964 BT_ERR("Frame is too short (len %d)", skb->len);
3965 l2cap_conn_unreliable(conn, ECOMM);
3966 goto drop;
3967 }
3968
3969 hdr = (struct l2cap_hdr *) skb->data;
3970 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003971 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972
3973 if (len == skb->len) {
3974 /* Complete frame received */
3975 l2cap_recv_frame(conn, skb);
3976 return 0;
3977 }
3978
3979 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3980
3981 if (skb->len > len) {
3982 BT_ERR("Frame is too long (len %d, expected len %d)",
3983 skb->len, len);
3984 l2cap_conn_unreliable(conn, ECOMM);
3985 goto drop;
3986 }
3987
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003988 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003989
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003990 if (chan && chan->sk) {
3991 struct sock *sk = chan->sk;
3992
3993 if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
3994 BT_ERR("Frame exceeding recv MTU (len %d, "
3995 "MTU %d)", len,
3996 l2cap_pi(sk)->imtu);
3997 bh_unlock_sock(sk);
3998 l2cap_conn_unreliable(conn, ECOMM);
3999 goto drop;
4000 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004001 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004002 }
4003
Linus Torvalds1da177e2005-04-16 15:20:36 -07004004 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004005 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4006 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007 goto drop;
4008
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004009 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004010 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011 conn->rx_len = len - skb->len;
4012 } else {
4013 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4014
4015 if (!conn->rx_len) {
4016 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4017 l2cap_conn_unreliable(conn, ECOMM);
4018 goto drop;
4019 }
4020
4021 if (skb->len > conn->rx_len) {
4022 BT_ERR("Fragment is too long (len %d, expected %d)",
4023 skb->len, conn->rx_len);
4024 kfree_skb(conn->rx_skb);
4025 conn->rx_skb = NULL;
4026 conn->rx_len = 0;
4027 l2cap_conn_unreliable(conn, ECOMM);
4028 goto drop;
4029 }
4030
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004031 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004032 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033 conn->rx_len -= skb->len;
4034
4035 if (!conn->rx_len) {
4036 /* Complete frame received */
4037 l2cap_recv_frame(conn, conn->rx_skb);
4038 conn->rx_skb = NULL;
4039 }
4040 }
4041
4042drop:
4043 kfree_skb(skb);
4044 return 0;
4045}
4046
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004047static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004048{
4049 struct sock *sk;
4050 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051
4052 read_lock_bh(&l2cap_sk_list.lock);
4053
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004054 sk_for_each(sk, node, &l2cap_sk_list.head) {
4055 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004057 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 +01004058 batostr(&bt_sk(sk)->src),
4059 batostr(&bt_sk(sk)->dst),
4060 sk->sk_state, __le16_to_cpu(pi->psm),
4061 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004062 pi->imtu, pi->omtu, pi->sec_level,
4063 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004064 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004067
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004068 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069}
4070
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004071static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4072{
4073 return single_open(file, l2cap_debugfs_show, inode->i_private);
4074}
4075
4076static const struct file_operations l2cap_debugfs_fops = {
4077 .open = l2cap_debugfs_open,
4078 .read = seq_read,
4079 .llseek = seq_lseek,
4080 .release = single_release,
4081};
4082
4083static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085static struct hci_proto l2cap_hci_proto = {
4086 .name = "L2CAP",
4087 .id = HCI_PROTO_L2CAP,
4088 .connect_ind = l2cap_connect_ind,
4089 .connect_cfm = l2cap_connect_cfm,
4090 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004091 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004092 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093 .recv_acldata = l2cap_recv_acldata
4094};
4095
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004096int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097{
4098 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004099
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004100 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101 if (err < 0)
4102 return err;
4103
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004104 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004105 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004106 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107 goto error;
4108 }
4109
4110 err = hci_register_proto(&l2cap_hci_proto);
4111 if (err < 0) {
4112 BT_ERR("L2CAP protocol registration failed");
4113 bt_sock_unregister(BTPROTO_L2CAP);
4114 goto error;
4115 }
4116
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004117 if (bt_debugfs) {
4118 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4119 bt_debugfs, NULL, &l2cap_debugfs_fops);
4120 if (!l2cap_debugfs)
4121 BT_ERR("Failed to create L2CAP debug file");
4122 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124 return 0;
4125
4126error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004127 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004128 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129 return err;
4130}
4131
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004132void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004134 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004136 flush_workqueue(_busy_wq);
4137 destroy_workqueue(_busy_wq);
4138
Linus Torvalds1da177e2005-04-16 15:20:36 -07004139 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4140 BT_ERR("L2CAP protocol unregistration failed");
4141
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004142 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143}
4144
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004145module_param(disable_ertm, bool, 0644);
4146MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");