blob: 8cfa2a663028900e6b0fe8107398faeb9af39d37 [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. Padovan710f9b0a2011-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. Padovan58d35f82011-04-04 16:16:44 -0300243 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300244
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 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300481 del_timer(&chan->retrans_timer);
482 del_timer(&chan->monitor_timer);
483 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300484 }
485
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300486 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
487 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
488 l2cap_send_cmd(conn, l2cap_get_ident(conn),
489 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300490
491 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300492 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300493}
494
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200496static void l2cap_conn_start(struct l2cap_conn *conn)
497{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300498 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200499
500 BT_DBG("conn %p", conn);
501
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300502 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200503
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300504 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300505 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300506
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200507 bh_lock_sock(sk);
508
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300509 if (sk->sk_type != SOCK_SEQPACKET &&
510 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200511 bh_unlock_sock(sk);
512 continue;
513 }
514
515 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300516 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300517
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300518 if (!l2cap_check_security(sk) ||
519 !__l2cap_no_conn_pending(sk)) {
520 bh_unlock_sock(sk);
521 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200522 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300523
524 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
525 conn->feat_mask)
526 && l2cap_pi(sk)->conf_state &
527 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300528 /* __l2cap_sock_close() calls list_del(chan)
529 * so release the lock */
530 read_unlock_bh(&conn->chan_lock);
531 __l2cap_sock_close(sk, ECONNRESET);
532 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300533 bh_unlock_sock(sk);
534 continue;
535 }
536
537 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
538 req.psm = l2cap_pi(sk)->psm;
539
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300540 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300541 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
542
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300543 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
544 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300545
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200546 } else if (sk->sk_state == BT_CONNECT2) {
547 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300548 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200549 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
550 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
551
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100552 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100553 if (bt_sk(sk)->defer_setup) {
554 struct sock *parent = bt_sk(sk)->parent;
555 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
556 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
557 parent->sk_data_ready(parent, 0);
558
559 } else {
560 sk->sk_state = BT_CONFIG;
561 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
562 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
563 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200564 } else {
565 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
566 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
567 }
568
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300569 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
570 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300571
572 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
573 rsp.result != L2CAP_CR_SUCCESS) {
574 bh_unlock_sock(sk);
575 continue;
576 }
577
578 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
579 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300580 l2cap_build_conf_req(chan, buf), buf);
581 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200582 }
583
584 bh_unlock_sock(sk);
585 }
586
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300587 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200588}
589
Ville Tervob62f3282011-02-10 22:38:50 -0300590/* Find socket with cid and source bdaddr.
591 * Returns closest match, locked.
592 */
593static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
594{
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300595 struct sock *sk = NULL, *sk1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300596 struct hlist_node *node;
597
598 read_lock(&l2cap_sk_list.lock);
599
600 sk_for_each(sk, node, &l2cap_sk_list.head) {
601 if (state && sk->sk_state != state)
602 continue;
603
604 if (l2cap_pi(sk)->scid == cid) {
605 /* Exact match. */
606 if (!bacmp(&bt_sk(sk)->src, src))
607 break;
608
609 /* Closest match */
610 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
611 sk1 = sk;
612 }
613 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300614
Ville Tervob62f3282011-02-10 22:38:50 -0300615 read_unlock(&l2cap_sk_list.lock);
616
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300617 return node ? sk : sk1;
Ville Tervob62f3282011-02-10 22:38:50 -0300618}
619
620static void l2cap_le_conn_ready(struct l2cap_conn *conn)
621{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300622 struct sock *parent, *sk;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300623 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300624
625 BT_DBG("");
626
627 /* Check if we have socket listening on cid */
628 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
629 conn->src);
630 if (!parent)
631 return;
632
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300633 bh_lock_sock(parent);
634
Ville Tervob62f3282011-02-10 22:38:50 -0300635 /* Check for backlog size */
636 if (sk_acceptq_is_full(parent)) {
637 BT_DBG("backlog full %d", parent->sk_ack_backlog);
638 goto clean;
639 }
640
641 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
642 if (!sk)
643 goto clean;
644
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300645 chan = l2cap_chan_alloc(sk);
646 if (!chan) {
647 l2cap_sock_kill(sk);
648 goto clean;
649 }
650
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300651 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300652
653 hci_conn_hold(conn->hcon);
654
655 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300656
Ville Tervob62f3282011-02-10 22:38:50 -0300657 bacpy(&bt_sk(sk)->src, conn->src);
658 bacpy(&bt_sk(sk)->dst, conn->dst);
659
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300660 bt_accept_enqueue(parent, sk);
661
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300662 __l2cap_chan_add(conn, chan);
663
664 l2cap_pi(sk)->chan = chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300665
666 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
667
668 sk->sk_state = BT_CONNECTED;
669 parent->sk_data_ready(parent, 0);
670
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300671 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300672
673clean:
674 bh_unlock_sock(parent);
675}
676
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200677static void l2cap_conn_ready(struct l2cap_conn *conn)
678{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300679 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200680
681 BT_DBG("conn %p", conn);
682
Ville Tervob62f3282011-02-10 22:38:50 -0300683 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
684 l2cap_le_conn_ready(conn);
685
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300686 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200687
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300688 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300689 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300690
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200691 bh_lock_sock(sk);
692
Ville Tervoacd7d372011-02-10 22:38:49 -0300693 if (conn->hcon->type == LE_LINK) {
694 l2cap_sock_clear_timer(sk);
695 sk->sk_state = BT_CONNECTED;
696 sk->sk_state_change(sk);
697 }
698
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300699 if (sk->sk_type != SOCK_SEQPACKET &&
700 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200701 l2cap_sock_clear_timer(sk);
702 sk->sk_state = BT_CONNECTED;
703 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200704 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300705 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200706
707 bh_unlock_sock(sk);
708 }
709
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300710 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200711}
712
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200713/* Notify sockets that we cannot guaranty reliability anymore */
714static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
715{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300716 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200717
718 BT_DBG("conn %p", conn);
719
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300720 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200721
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300722 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300723 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300724
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100725 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200726 sk->sk_err = err;
727 }
728
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300729 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200730}
731
732static void l2cap_info_timeout(unsigned long arg)
733{
734 struct l2cap_conn *conn = (void *) arg;
735
Marcel Holtmann984947d2009-02-06 23:35:19 +0100736 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100737 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100738
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200739 l2cap_conn_start(conn);
740}
741
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
743{
Marcel Holtmann01394182006-07-03 10:02:46 +0200744 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745
Marcel Holtmann01394182006-07-03 10:02:46 +0200746 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 return conn;
748
Marcel Holtmann01394182006-07-03 10:02:46 +0200749 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
750 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752
753 hcon->l2cap_data = conn;
754 conn->hcon = hcon;
755
Marcel Holtmann01394182006-07-03 10:02:46 +0200756 BT_DBG("hcon %p conn %p", hcon, conn);
757
Ville Tervoacd7d372011-02-10 22:38:49 -0300758 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
759 conn->mtu = hcon->hdev->le_mtu;
760 else
761 conn->mtu = hcon->hdev->acl_mtu;
762
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 conn->src = &hcon->hdev->bdaddr;
764 conn->dst = &hcon->dst;
765
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200766 conn->feat_mask = 0;
767
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300769 rwlock_init(&conn->chan_lock);
770
771 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772
Ville Tervob62f3282011-02-10 22:38:50 -0300773 if (hcon->type != LE_LINK)
774 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000775 (unsigned long) conn);
776
Marcel Holtmann2950f212009-02-12 14:02:50 +0100777 conn->disc_reason = 0x13;
778
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 return conn;
780}
781
Marcel Holtmann01394182006-07-03 10:02:46 +0200782static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783{
Marcel Holtmann01394182006-07-03 10:02:46 +0200784 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300785 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 struct sock *sk;
787
Marcel Holtmann01394182006-07-03 10:02:46 +0200788 if (!conn)
789 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
791 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
792
Wei Yongjun7585b972009-02-25 18:29:52 +0800793 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794
795 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300796 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300797 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300799 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 bh_unlock_sock(sk);
801 l2cap_sock_kill(sk);
802 }
803
Dave Young8e8440f2008-03-03 12:18:55 -0800804 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
805 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800806
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 hcon->l2cap_data = NULL;
808 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809}
810
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300811static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300813 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300814 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300815 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816}
817
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819
820/* Find socket with psm and source bdaddr.
821 * Returns closest match.
822 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000823static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824{
825 struct sock *sk = NULL, *sk1 = NULL;
826 struct hlist_node *node;
827
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000828 read_lock(&l2cap_sk_list.lock);
829
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 sk_for_each(sk, node, &l2cap_sk_list.head) {
831 if (state && sk->sk_state != state)
832 continue;
833
834 if (l2cap_pi(sk)->psm == psm) {
835 /* Exact match. */
836 if (!bacmp(&bt_sk(sk)->src, src))
837 break;
838
839 /* Closest match */
840 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
841 sk1 = sk;
842 }
843 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000846
847 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848}
849
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200850int l2cap_do_connect(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851{
852 bdaddr_t *src = &bt_sk(sk)->src;
853 bdaddr_t *dst = &bt_sk(sk)->dst;
854 struct l2cap_conn *conn;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300855 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 struct hci_conn *hcon;
857 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200858 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200859 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100861 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
862 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300864 hdev = hci_get_route(dst, src);
865 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 return -EHOSTUNREACH;
867
868 hci_dev_lock_bh(hdev);
869
Johan Hedberg8556edd32011-01-19 12:06:50 +0530870 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200871
Ville Tervoacd7d372011-02-10 22:38:49 -0300872 if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
873 hcon = hci_connect(hdev, LE_LINK, dst,
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100874 l2cap_pi(sk)->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300875 else
876 hcon = hci_connect(hdev, ACL_LINK, dst,
877 l2cap_pi(sk)->sec_level, auth_type);
878
Ville Tervo30e76272011-02-22 16:10:53 -0300879 if (IS_ERR(hcon)) {
880 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300882 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883
884 conn = l2cap_conn_add(hcon, 0);
885 if (!conn) {
886 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300887 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 goto done;
889 }
890
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300891 chan = l2cap_chan_alloc(sk);
892 if (!chan) {
893 hci_conn_put(hcon);
894 err = -ENOMEM;
895 goto done;
896 }
897
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 /* Update source addr of the socket */
899 bacpy(src, conn->src);
900
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300901 l2cap_chan_add(conn, chan);
902
903 l2cap_pi(sk)->chan = chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904
905 sk->sk_state = BT_CONNECT;
906 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
907
908 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300909 if (sk->sk_type != SOCK_SEQPACKET &&
910 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530912 if (l2cap_check_security(sk))
913 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200914 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300915 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 }
917
Ville Tervo30e76272011-02-22 16:10:53 -0300918 err = 0;
919
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920done:
921 hci_dev_unlock_bh(hdev);
922 hci_dev_put(hdev);
923 return err;
924}
925
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200926int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300927{
928 DECLARE_WAITQUEUE(wait, current);
929 int err = 0;
930 int timeo = HZ/5;
931
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200932 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300933 while ((l2cap_pi(sk)->chan->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300934 set_current_state(TASK_INTERRUPTIBLE);
935
936 if (!timeo)
937 timeo = HZ/5;
938
939 if (signal_pending(current)) {
940 err = sock_intr_errno(timeo);
941 break;
942 }
943
944 release_sock(sk);
945 timeo = schedule_timeout(timeo);
946 lock_sock(sk);
947
948 err = sock_error(sk);
949 if (err)
950 break;
951 }
952 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200953 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300954 return err;
955}
956
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300957static void l2cap_monitor_timeout(unsigned long arg)
958{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300959 struct l2cap_chan *chan = (void *) arg;
960 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300961
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300962 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300963
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300964 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -0300965 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300966 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200967 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300968 return;
969 }
970
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300971 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300972 __mod_monitor_timer();
973
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300974 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300975 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300976}
977
978static void l2cap_retrans_timeout(unsigned long arg)
979{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300980 struct l2cap_chan *chan = (void *) arg;
981 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300982
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300983 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300984
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300985 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300986 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300987 __mod_monitor_timer();
988
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300989 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300990
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300991 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300992 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300993}
994
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300995static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300996{
997 struct sk_buff *skb;
998
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300999 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001000 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001001 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001002 break;
1003
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001004 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001005 kfree_skb(skb);
1006
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001007 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001008 }
1009
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001010 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001011 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001012}
1013
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001014void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001015{
1016 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001017 struct hci_conn *hcon = pi->conn->hcon;
1018 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001019
1020 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1021
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001022 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
1023 flags = ACL_START_NO_FLUSH;
1024 else
1025 flags = ACL_START;
1026
1027 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001028}
1029
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001030void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001031{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001032 struct sock *sk = chan->sk;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001033 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001034 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001035 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001036
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001037 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001038 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001039 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001040 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001041
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001042 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001043 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1044 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001045 }
1046
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001047 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001048
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001049 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001050 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001051}
1052
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001053static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001054{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001055 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001056 struct l2cap_pinfo *pi = l2cap_pi(sk);
1057 struct sk_buff *skb, *tx_skb;
1058 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001059
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001060 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001061 if (!skb)
1062 return;
1063
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001064 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001065 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001066 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001067
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001068 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001069 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001070
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001071 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001072
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001073 if (chan->remote_max_tx &&
1074 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001075 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001076 return;
1077 }
1078
1079 tx_skb = skb_clone(skb, GFP_ATOMIC);
1080 bt_cb(skb)->retries++;
1081 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001082
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001083 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001084 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001085 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001086 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001087
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001088 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001089 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001090
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001091 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1092
1093 if (pi->fcs == L2CAP_FCS_CRC16) {
1094 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1095 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1096 }
1097
1098 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001099}
1100
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001101int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001102{
1103 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001104 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001105 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001106 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001107 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001108
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001109 if (sk->sk_state != BT_CONNECTED)
1110 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001111
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001112 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001113
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001114 if (chan->remote_max_tx &&
1115 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001116 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001117 break;
1118 }
1119
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001120 tx_skb = skb_clone(skb, GFP_ATOMIC);
1121
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001122 bt_cb(skb)->retries++;
1123
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001124 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001125 control &= L2CAP_CTRL_SAR;
1126
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001127 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001128 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001129 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001130 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001131 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1132 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001133 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1134
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001135
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001136 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001137 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1138 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1139 }
1140
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001141 l2cap_do_send(sk, tx_skb);
1142
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001143 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001144
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001145 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1146 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001147
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301148 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001149 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301150
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001151 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001152
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001153 if (skb_queue_is_last(&chan->tx_q, skb))
1154 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001155 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001156 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001157
1158 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001159 }
1160
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001161 return nsent;
1162}
1163
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001164static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001165{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001166 int ret;
1167
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001168 if (!skb_queue_empty(&chan->tx_q))
1169 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001170
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001171 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001172 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001173 return ret;
1174}
1175
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001176static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001177{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001178 u16 control = 0;
1179
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001180 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001181
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001182 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001183 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001184 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1185 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001186 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001187 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001188
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001189 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001190 return;
1191
1192 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001193 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001194}
1195
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001196static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001197{
1198 struct srej_list *tail;
1199 u16 control;
1200
1201 control = L2CAP_SUPER_SELECT_REJECT;
1202 control |= L2CAP_CTRL_FINAL;
1203
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001204 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001205 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1206
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001207 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001208}
1209
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001210static 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 -07001211{
1212 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001213 struct sk_buff **frag;
1214 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001216 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001217 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218
1219 sent += count;
1220 len -= count;
1221
1222 /* Continuation fragments (no L2CAP header) */
1223 frag = &skb_shinfo(skb)->frag_list;
1224 while (len) {
1225 count = min_t(unsigned int, conn->mtu, len);
1226
1227 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1228 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001229 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001230 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1231 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232
1233 sent += count;
1234 len -= count;
1235
1236 frag = &(*frag)->next;
1237 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238
1239 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001240}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001242struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001243{
1244 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1245 struct sk_buff *skb;
1246 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1247 struct l2cap_hdr *lh;
1248
1249 BT_DBG("sk %p len %d", sk, (int)len);
1250
1251 count = min_t(unsigned int, (conn->mtu - hlen), len);
1252 skb = bt_skb_send_alloc(sk, count + hlen,
1253 msg->msg_flags & MSG_DONTWAIT, &err);
1254 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001255 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001256
1257 /* Create L2CAP header */
1258 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1259 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1260 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1261 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1262
1263 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1264 if (unlikely(err < 0)) {
1265 kfree_skb(skb);
1266 return ERR_PTR(err);
1267 }
1268 return skb;
1269}
1270
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001271struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001272{
1273 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1274 struct sk_buff *skb;
1275 int err, count, hlen = L2CAP_HDR_SIZE;
1276 struct l2cap_hdr *lh;
1277
1278 BT_DBG("sk %p len %d", sk, (int)len);
1279
1280 count = min_t(unsigned int, (conn->mtu - hlen), len);
1281 skb = bt_skb_send_alloc(sk, count + hlen,
1282 msg->msg_flags & MSG_DONTWAIT, &err);
1283 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001284 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001285
1286 /* Create L2CAP header */
1287 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1288 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1289 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1290
1291 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1292 if (unlikely(err < 0)) {
1293 kfree_skb(skb);
1294 return ERR_PTR(err);
1295 }
1296 return skb;
1297}
1298
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001299struct 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 -03001300{
1301 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1302 struct sk_buff *skb;
1303 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1304 struct l2cap_hdr *lh;
1305
1306 BT_DBG("sk %p len %d", sk, (int)len);
1307
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001308 if (!conn)
1309 return ERR_PTR(-ENOTCONN);
1310
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001311 if (sdulen)
1312 hlen += 2;
1313
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001314 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1315 hlen += 2;
1316
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001317 count = min_t(unsigned int, (conn->mtu - hlen), len);
1318 skb = bt_skb_send_alloc(sk, count + hlen,
1319 msg->msg_flags & MSG_DONTWAIT, &err);
1320 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001321 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001322
1323 /* Create L2CAP header */
1324 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1325 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1326 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1327 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001328 if (sdulen)
1329 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001330
1331 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1332 if (unlikely(err < 0)) {
1333 kfree_skb(skb);
1334 return ERR_PTR(err);
1335 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001336
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001337 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1338 put_unaligned_le16(0, skb_put(skb, 2));
1339
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001340 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001341 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342}
1343
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001344int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001345{
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001346 struct sock *sk = chan->sk;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001347 struct sk_buff *skb;
1348 struct sk_buff_head sar_queue;
1349 u16 control;
1350 size_t size = 0;
1351
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001352 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001353 control = L2CAP_SDU_START;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001354 skb = l2cap_create_iframe_pdu(sk, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001355 if (IS_ERR(skb))
1356 return PTR_ERR(skb);
1357
1358 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001359 len -= chan->remote_mps;
1360 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001361
1362 while (len > 0) {
1363 size_t buflen;
1364
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001365 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001366 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001367 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001368 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001369 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001370 buflen = len;
1371 }
1372
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001373 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001374 if (IS_ERR(skb)) {
1375 skb_queue_purge(&sar_queue);
1376 return PTR_ERR(skb);
1377 }
1378
1379 __skb_queue_tail(&sar_queue, skb);
1380 len -= buflen;
1381 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001382 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001383 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1384 if (chan->tx_send_head == NULL)
1385 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001386
1387 return size;
1388}
1389
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390static void l2cap_chan_ready(struct sock *sk)
1391{
1392 struct sock *parent = bt_sk(sk)->parent;
1393
1394 BT_DBG("sk %p, parent %p", sk, parent);
1395
1396 l2cap_pi(sk)->conf_state = 0;
1397 l2cap_sock_clear_timer(sk);
1398
1399 if (!parent) {
1400 /* Outgoing channel.
1401 * Wake up socket sleeping on connect.
1402 */
1403 sk->sk_state = BT_CONNECTED;
1404 sk->sk_state_change(sk);
1405 } else {
1406 /* Incoming channel.
1407 * Wake up socket sleeping on accept.
1408 */
1409 parent->sk_data_ready(parent, 0);
1410 }
1411}
1412
1413/* Copy frame to all raw sockets on that connection */
1414static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1415{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001417 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418
1419 BT_DBG("conn %p", conn);
1420
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001421 read_lock(&conn->chan_lock);
1422 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001423 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 if (sk->sk_type != SOCK_RAW)
1425 continue;
1426
1427 /* Don't send frame to the socket it came from */
1428 if (skb->sk == sk)
1429 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001430 nskb = skb_clone(skb, GFP_ATOMIC);
1431 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 continue;
1433
1434 if (sock_queue_rcv_skb(sk, nskb))
1435 kfree_skb(nskb);
1436 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001437 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438}
1439
1440/* ---- L2CAP signalling commands ---- */
1441static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1442 u8 code, u8 ident, u16 dlen, void *data)
1443{
1444 struct sk_buff *skb, **frag;
1445 struct l2cap_cmd_hdr *cmd;
1446 struct l2cap_hdr *lh;
1447 int len, count;
1448
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001449 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1450 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451
1452 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1453 count = min_t(unsigned int, conn->mtu, len);
1454
1455 skb = bt_skb_alloc(count, GFP_ATOMIC);
1456 if (!skb)
1457 return NULL;
1458
1459 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001460 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001461
1462 if (conn->hcon->type == LE_LINK)
1463 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1464 else
1465 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
1467 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1468 cmd->code = code;
1469 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001470 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471
1472 if (dlen) {
1473 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1474 memcpy(skb_put(skb, count), data, count);
1475 data += count;
1476 }
1477
1478 len -= skb->len;
1479
1480 /* Continuation fragments (no L2CAP header) */
1481 frag = &skb_shinfo(skb)->frag_list;
1482 while (len) {
1483 count = min_t(unsigned int, conn->mtu, len);
1484
1485 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1486 if (!*frag)
1487 goto fail;
1488
1489 memcpy(skb_put(*frag, count), data, count);
1490
1491 len -= count;
1492 data += count;
1493
1494 frag = &(*frag)->next;
1495 }
1496
1497 return skb;
1498
1499fail:
1500 kfree_skb(skb);
1501 return NULL;
1502}
1503
1504static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1505{
1506 struct l2cap_conf_opt *opt = *ptr;
1507 int len;
1508
1509 len = L2CAP_CONF_OPT_SIZE + opt->len;
1510 *ptr += len;
1511
1512 *type = opt->type;
1513 *olen = opt->len;
1514
1515 switch (opt->len) {
1516 case 1:
1517 *val = *((u8 *) opt->val);
1518 break;
1519
1520 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001521 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 break;
1523
1524 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001525 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 break;
1527
1528 default:
1529 *val = (unsigned long) opt->val;
1530 break;
1531 }
1532
1533 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1534 return len;
1535}
1536
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1538{
1539 struct l2cap_conf_opt *opt = *ptr;
1540
1541 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1542
1543 opt->type = type;
1544 opt->len = len;
1545
1546 switch (len) {
1547 case 1:
1548 *((u8 *) opt->val) = val;
1549 break;
1550
1551 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001552 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 break;
1554
1555 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001556 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 break;
1558
1559 default:
1560 memcpy(opt->val, (void *) val, len);
1561 break;
1562 }
1563
1564 *ptr += L2CAP_CONF_OPT_SIZE + len;
1565}
1566
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001567static void l2cap_ack_timeout(unsigned long arg)
1568{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001569 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001570
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001571 bh_lock_sock(chan->sk);
1572 l2cap_send_ack(chan);
1573 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001574}
1575
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001576static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001577{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001578 struct sock *sk = chan->sk;
1579
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001580 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001581 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001582 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001583 chan->num_acked = 0;
1584 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001585
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001586 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1587 (unsigned long) chan);
1588 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1589 (unsigned long) chan);
1590 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001591
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001592 skb_queue_head_init(&chan->srej_q);
1593 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001594
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001595 INIT_LIST_HEAD(&chan->srej_l);
1596
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001597 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001598
1599 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001600}
1601
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001602static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1603{
1604 switch (mode) {
1605 case L2CAP_MODE_STREAMING:
1606 case L2CAP_MODE_ERTM:
1607 if (l2cap_mode_supported(mode, remote_feat_mask))
1608 return mode;
1609 /* fall through */
1610 default:
1611 return L2CAP_MODE_BASIC;
1612 }
1613}
1614
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03001615static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001617 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001619 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 void *ptr = req->data;
1621
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001622 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001624 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001625 goto done;
1626
1627 switch (pi->mode) {
1628 case L2CAP_MODE_STREAMING:
1629 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001630 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001631 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001632
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001633 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001634 default:
1635 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1636 break;
1637 }
1638
1639done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001640 if (pi->imtu != L2CAP_DEFAULT_MTU)
1641 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1642
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001643 switch (pi->mode) {
1644 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001645 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1646 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1647 break;
1648
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001649 rfc.mode = L2CAP_MODE_BASIC;
1650 rfc.txwin_size = 0;
1651 rfc.max_transmit = 0;
1652 rfc.retrans_timeout = 0;
1653 rfc.monitor_timeout = 0;
1654 rfc.max_pdu_size = 0;
1655
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001656 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1657 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001658 break;
1659
1660 case L2CAP_MODE_ERTM:
1661 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001662 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001663 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001664 rfc.retrans_timeout = 0;
1665 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001666 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001667 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001668 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001669
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001670 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1671 (unsigned long) &rfc);
1672
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001673 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1674 break;
1675
1676 if (pi->fcs == L2CAP_FCS_NONE ||
1677 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1678 pi->fcs = L2CAP_FCS_NONE;
1679 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1680 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001681 break;
1682
1683 case L2CAP_MODE_STREAMING:
1684 rfc.mode = L2CAP_MODE_STREAMING;
1685 rfc.txwin_size = 0;
1686 rfc.max_transmit = 0;
1687 rfc.retrans_timeout = 0;
1688 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001689 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001690 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001691 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001692
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001693 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1694 (unsigned long) &rfc);
1695
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001696 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1697 break;
1698
1699 if (pi->fcs == L2CAP_FCS_NONE ||
1700 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1701 pi->fcs = L2CAP_FCS_NONE;
1702 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1703 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001704 break;
1705 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001707 req->dcid = cpu_to_le16(pi->dcid);
1708 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709
1710 return ptr - data;
1711}
1712
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001713static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001715 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001716 struct l2cap_conf_rsp *rsp = data;
1717 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001718 void *req = chan->conf_req;
1719 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001720 int type, hint, olen;
1721 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001722 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001723 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001724 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001726 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001727
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001728 while (len >= L2CAP_CONF_OPT_SIZE) {
1729 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001731 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001732 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001733
1734 switch (type) {
1735 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001736 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001737 break;
1738
1739 case L2CAP_CONF_FLUSH_TO:
1740 pi->flush_to = val;
1741 break;
1742
1743 case L2CAP_CONF_QOS:
1744 break;
1745
Marcel Holtmann6464f352007-10-20 13:39:51 +02001746 case L2CAP_CONF_RFC:
1747 if (olen == sizeof(rfc))
1748 memcpy(&rfc, (void *) val, olen);
1749 break;
1750
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001751 case L2CAP_CONF_FCS:
1752 if (val == L2CAP_FCS_NONE)
1753 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1754
1755 break;
1756
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001757 default:
1758 if (hint)
1759 break;
1760
1761 result = L2CAP_CONF_UNKNOWN;
1762 *((u8 *) ptr++) = type;
1763 break;
1764 }
1765 }
1766
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001767 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001768 goto done;
1769
1770 switch (pi->mode) {
1771 case L2CAP_MODE_STREAMING:
1772 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001773 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1774 pi->mode = l2cap_select_mode(rfc.mode,
1775 pi->conn->feat_mask);
1776 break;
1777 }
1778
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001779 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001780 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001781
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001782 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001783 }
1784
1785done:
1786 if (pi->mode != rfc.mode) {
1787 result = L2CAP_CONF_UNACCEPT;
1788 rfc.mode = pi->mode;
1789
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001790 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001791 return -ECONNREFUSED;
1792
1793 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1794 sizeof(rfc), (unsigned long) &rfc);
1795 }
1796
1797
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001798 if (result == L2CAP_CONF_SUCCESS) {
1799 /* Configure output options and let the other side know
1800 * which ones we don't like. */
1801
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001802 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1803 result = L2CAP_CONF_UNACCEPT;
1804 else {
1805 pi->omtu = mtu;
1806 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1807 }
1808 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001809
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001810 switch (rfc.mode) {
1811 case L2CAP_MODE_BASIC:
1812 pi->fcs = L2CAP_FCS_NONE;
1813 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1814 break;
1815
1816 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001817 chan->remote_tx_win = rfc.txwin_size;
1818 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001819
1820 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1821 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001822
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001823 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001824
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001825 rfc.retrans_timeout =
1826 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1827 rfc.monitor_timeout =
1828 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001829
1830 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001831
1832 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1833 sizeof(rfc), (unsigned long) &rfc);
1834
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001835 break;
1836
1837 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001838 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1839 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001840
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001841 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001842
1843 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001844
1845 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1846 sizeof(rfc), (unsigned long) &rfc);
1847
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001848 break;
1849
1850 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001851 result = L2CAP_CONF_UNACCEPT;
1852
1853 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001854 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001855 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001856
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001857 if (result == L2CAP_CONF_SUCCESS)
1858 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1859 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001860 rsp->scid = cpu_to_le16(pi->dcid);
1861 rsp->result = cpu_to_le16(result);
1862 rsp->flags = cpu_to_le16(0x0000);
1863
1864 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865}
1866
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001867static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1868{
1869 struct l2cap_pinfo *pi = l2cap_pi(sk);
1870 struct l2cap_conf_req *req = data;
1871 void *ptr = req->data;
1872 int type, olen;
1873 unsigned long val;
1874 struct l2cap_conf_rfc rfc;
1875
1876 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1877
1878 while (len >= L2CAP_CONF_OPT_SIZE) {
1879 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1880
1881 switch (type) {
1882 case L2CAP_CONF_MTU:
1883 if (val < L2CAP_DEFAULT_MIN_MTU) {
1884 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001885 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001886 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001887 pi->imtu = val;
1888 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001889 break;
1890
1891 case L2CAP_CONF_FLUSH_TO:
1892 pi->flush_to = val;
1893 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1894 2, pi->flush_to);
1895 break;
1896
1897 case L2CAP_CONF_RFC:
1898 if (olen == sizeof(rfc))
1899 memcpy(&rfc, (void *)val, olen);
1900
1901 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1902 rfc.mode != pi->mode)
1903 return -ECONNREFUSED;
1904
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001905 pi->fcs = 0;
1906
1907 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1908 sizeof(rfc), (unsigned long) &rfc);
1909 break;
1910 }
1911 }
1912
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001913 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1914 return -ECONNREFUSED;
1915
1916 pi->mode = rfc.mode;
1917
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001918 if (*result == L2CAP_CONF_SUCCESS) {
1919 switch (rfc.mode) {
1920 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001921 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1922 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001923 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001924 break;
1925 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001926 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001927 }
1928 }
1929
1930 req->dcid = cpu_to_le16(pi->dcid);
1931 req->flags = cpu_to_le16(0x0000);
1932
1933 return ptr - data;
1934}
1935
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001936static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937{
1938 struct l2cap_conf_rsp *rsp = data;
1939 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001941 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001943 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001944 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001945 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946
1947 return ptr - data;
1948}
1949
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03001950void __l2cap_connect_rsp_defer(struct sock *sk)
1951{
1952 struct l2cap_conn_rsp rsp;
1953 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1954 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
1955 u8 buf[128];
1956
1957 sk->sk_state = BT_CONFIG;
1958
1959 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1960 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1961 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1962 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1963 l2cap_send_cmd(conn, chan->ident,
1964 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1965
1966 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
1967 return;
1968
1969 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
1970 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1971 l2cap_build_conf_req(chan, buf), buf);
1972 chan->num_conf_req++;
1973}
1974
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001975static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1976{
1977 struct l2cap_pinfo *pi = l2cap_pi(sk);
1978 int type, olen;
1979 unsigned long val;
1980 struct l2cap_conf_rfc rfc;
1981
1982 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1983
1984 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1985 return;
1986
1987 while (len >= L2CAP_CONF_OPT_SIZE) {
1988 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1989
1990 switch (type) {
1991 case L2CAP_CONF_RFC:
1992 if (olen == sizeof(rfc))
1993 memcpy(&rfc, (void *)val, olen);
1994 goto done;
1995 }
1996 }
1997
1998done:
1999 switch (rfc.mode) {
2000 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002001 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2002 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002003 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2004 break;
2005 case L2CAP_MODE_STREAMING:
2006 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2007 }
2008}
2009
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002010static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2011{
2012 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2013
2014 if (rej->reason != 0x0000)
2015 return 0;
2016
2017 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2018 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002019 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002020
2021 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002022 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002023
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002024 l2cap_conn_start(conn);
2025 }
2026
2027 return 0;
2028}
2029
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2031{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2033 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002034 struct l2cap_chan *chan = NULL;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002035 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002036 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037
2038 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002039 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040
2041 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2042
2043 /* Check if we have socket listening on psm */
2044 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2045 if (!parent) {
2046 result = L2CAP_CR_BAD_PSM;
2047 goto sendresp;
2048 }
2049
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002050 bh_lock_sock(parent);
2051
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002052 /* Check if the ACL is secure enough (if not SDP) */
2053 if (psm != cpu_to_le16(0x0001) &&
2054 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002055 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002056 result = L2CAP_CR_SEC_BLOCK;
2057 goto response;
2058 }
2059
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 result = L2CAP_CR_NO_MEM;
2061
2062 /* Check for backlog size */
2063 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002064 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 goto response;
2066 }
2067
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002068 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069 if (!sk)
2070 goto response;
2071
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002072 chan = l2cap_chan_alloc(sk);
2073 if (!chan) {
2074 l2cap_sock_kill(sk);
2075 goto response;
2076 }
2077
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002078 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079
2080 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002081 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2082 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 sock_set_flag(sk, SOCK_ZAPPED);
2084 l2cap_sock_kill(sk);
2085 goto response;
2086 }
2087
2088 hci_conn_hold(conn->hcon);
2089
2090 l2cap_sock_init(sk, parent);
2091 bacpy(&bt_sk(sk)->src, conn->src);
2092 bacpy(&bt_sk(sk)->dst, conn->dst);
2093 l2cap_pi(sk)->psm = psm;
2094 l2cap_pi(sk)->dcid = scid;
2095
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002096 bt_accept_enqueue(parent, sk);
2097
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002098 __l2cap_chan_add(conn, chan);
2099
2100 l2cap_pi(sk)->chan = chan;
2101
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 dcid = l2cap_pi(sk)->scid;
2103
2104 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2105
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002106 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107
Marcel Holtmann984947d2009-02-06 23:35:19 +01002108 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002109 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002110 if (bt_sk(sk)->defer_setup) {
2111 sk->sk_state = BT_CONNECT2;
2112 result = L2CAP_CR_PEND;
2113 status = L2CAP_CS_AUTHOR_PEND;
2114 parent->sk_data_ready(parent, 0);
2115 } else {
2116 sk->sk_state = BT_CONFIG;
2117 result = L2CAP_CR_SUCCESS;
2118 status = L2CAP_CS_NO_INFO;
2119 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002120 } else {
2121 sk->sk_state = BT_CONNECT2;
2122 result = L2CAP_CR_PEND;
2123 status = L2CAP_CS_AUTHEN_PEND;
2124 }
2125 } else {
2126 sk->sk_state = BT_CONNECT2;
2127 result = L2CAP_CR_PEND;
2128 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129 }
2130
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002131 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132
2133response:
2134 bh_unlock_sock(parent);
2135
2136sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002137 rsp.scid = cpu_to_le16(scid);
2138 rsp.dcid = cpu_to_le16(dcid);
2139 rsp.result = cpu_to_le16(result);
2140 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002142
2143 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2144 struct l2cap_info_req info;
2145 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2146
2147 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2148 conn->info_ident = l2cap_get_ident(conn);
2149
2150 mod_timer(&conn->info_timer, jiffies +
2151 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2152
2153 l2cap_send_cmd(conn, conn->info_ident,
2154 L2CAP_INFO_REQ, sizeof(info), &info);
2155 }
2156
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002157 if (chan && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002158 result == L2CAP_CR_SUCCESS) {
2159 u8 buf[128];
2160 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2161 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002162 l2cap_build_conf_req(chan, buf), buf);
2163 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002164 }
2165
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 return 0;
2167}
2168
2169static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2170{
2171 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2172 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002173 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174 struct sock *sk;
2175 u8 req[128];
2176
2177 scid = __le16_to_cpu(rsp->scid);
2178 dcid = __le16_to_cpu(rsp->dcid);
2179 result = __le16_to_cpu(rsp->result);
2180 status = __le16_to_cpu(rsp->status);
2181
2182 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2183
2184 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002185 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002186 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002187 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002189 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
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 }
2193
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002194 sk = chan->sk;
2195
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 switch (result) {
2197 case L2CAP_CR_SUCCESS:
2198 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002199 chan->ident = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002201 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2202
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002203 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2204 break;
2205
2206 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2207
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002209 l2cap_build_conf_req(chan, req), req);
2210 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 break;
2212
2213 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002214 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 break;
2216
2217 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002218 /* don't delete l2cap channel if sk is owned by user */
2219 if (sock_owned_by_user(sk)) {
2220 sk->sk_state = BT_DISCONN;
2221 l2cap_sock_clear_timer(sk);
2222 l2cap_sock_set_timer(sk, HZ / 5);
2223 break;
2224 }
2225
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002226 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227 break;
2228 }
2229
2230 bh_unlock_sock(sk);
2231 return 0;
2232}
2233
Mat Martineau8c462b62010-08-24 15:35:42 -07002234static inline void set_default_fcs(struct l2cap_pinfo *pi)
2235{
2236 /* FCS is enabled only in ERTM or streaming mode, if one or both
2237 * sides request it.
2238 */
2239 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2240 pi->fcs = L2CAP_FCS_NONE;
2241 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2242 pi->fcs = L2CAP_FCS_CRC16;
2243}
2244
Al Viro88219a02007-07-29 00:17:25 -07002245static 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 -07002246{
2247 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2248 u16 dcid, flags;
2249 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002250 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002252 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253
2254 dcid = __le16_to_cpu(req->dcid);
2255 flags = __le16_to_cpu(req->flags);
2256
2257 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2258
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002259 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002260 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 return -ENOENT;
2262
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002263 sk = chan->sk;
2264
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002265 if (sk->sk_state != BT_CONFIG) {
2266 struct l2cap_cmd_rej rej;
2267
2268 rej.reason = cpu_to_le16(0x0002);
2269 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2270 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002271 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002272 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002273
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002274 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002275 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002276 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002277 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2278 l2cap_build_conf_rsp(sk, rsp,
2279 L2CAP_CONF_REJECT, flags), rsp);
2280 goto unlock;
2281 }
2282
2283 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002284 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2285 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286
2287 if (flags & 0x0001) {
2288 /* Incomplete config. Send empty response. */
2289 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002290 l2cap_build_conf_rsp(sk, rsp,
2291 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 goto unlock;
2293 }
2294
2295 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002296 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002297 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002298 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002300 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002302 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002303 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002304
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002305 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002306 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002307
Marcel Holtmann876d9482007-10-20 13:35:42 +02002308 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2309 goto unlock;
2310
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002312 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002313
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002315
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002316 chan->next_tx_seq = 0;
2317 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002318 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002319 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002320 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002321
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002323 goto unlock;
2324 }
2325
2326 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002327 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002328 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002330 l2cap_build_conf_req(chan, buf), buf);
2331 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 }
2333
2334unlock:
2335 bh_unlock_sock(sk);
2336 return 0;
2337}
2338
2339static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2340{
2341 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2342 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002343 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002345 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346
2347 scid = __le16_to_cpu(rsp->scid);
2348 flags = __le16_to_cpu(rsp->flags);
2349 result = __le16_to_cpu(rsp->result);
2350
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002351 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2352 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002354 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002355 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 return 0;
2357
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002358 sk = chan->sk;
2359
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 switch (result) {
2361 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002362 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 break;
2364
2365 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002366 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002367 char req[64];
2368
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002369 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002370 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002371 goto done;
2372 }
2373
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002374 /* throw out any old stored conf requests */
2375 result = L2CAP_CONF_SUCCESS;
2376 len = l2cap_parse_conf_rsp(sk, rsp->data,
2377 len, req, &result);
2378 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002379 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002380 goto done;
2381 }
2382
2383 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2384 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002385 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002386 if (result != L2CAP_CONF_SUCCESS)
2387 goto done;
2388 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389 }
2390
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002391 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002392 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002394 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 goto done;
2396 }
2397
2398 if (flags & 0x01)
2399 goto done;
2400
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2402
2403 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002404 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002405
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002407 chan->next_tx_seq = 0;
2408 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002409 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002410 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002411 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002412
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 l2cap_chan_ready(sk);
2414 }
2415
2416done:
2417 bh_unlock_sock(sk);
2418 return 0;
2419}
2420
2421static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2422{
2423 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2424 struct l2cap_disconn_rsp rsp;
2425 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002426 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427 struct sock *sk;
2428
2429 scid = __le16_to_cpu(req->scid);
2430 dcid = __le16_to_cpu(req->dcid);
2431
2432 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2433
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002434 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002435 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 return 0;
2437
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002438 sk = chan->sk;
2439
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002440 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2441 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2443
2444 sk->sk_shutdown = SHUTDOWN_MASK;
2445
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002446 /* don't delete l2cap channel if sk is owned by user */
2447 if (sock_owned_by_user(sk)) {
2448 sk->sk_state = BT_DISCONN;
2449 l2cap_sock_clear_timer(sk);
2450 l2cap_sock_set_timer(sk, HZ / 5);
2451 bh_unlock_sock(sk);
2452 return 0;
2453 }
2454
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002455 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456 bh_unlock_sock(sk);
2457
2458 l2cap_sock_kill(sk);
2459 return 0;
2460}
2461
2462static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2463{
2464 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2465 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002466 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 struct sock *sk;
2468
2469 scid = __le16_to_cpu(rsp->scid);
2470 dcid = __le16_to_cpu(rsp->dcid);
2471
2472 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2473
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002474 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002475 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476 return 0;
2477
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002478 sk = chan->sk;
2479
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002480 /* don't delete l2cap channel if sk is owned by user */
2481 if (sock_owned_by_user(sk)) {
2482 sk->sk_state = BT_DISCONN;
2483 l2cap_sock_clear_timer(sk);
2484 l2cap_sock_set_timer(sk, HZ / 5);
2485 bh_unlock_sock(sk);
2486 return 0;
2487 }
2488
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002489 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 bh_unlock_sock(sk);
2491
2492 l2cap_sock_kill(sk);
2493 return 0;
2494}
2495
2496static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2497{
2498 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 u16 type;
2500
2501 type = __le16_to_cpu(req->type);
2502
2503 BT_DBG("type 0x%4.4x", type);
2504
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002505 if (type == L2CAP_IT_FEAT_MASK) {
2506 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002507 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002508 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2509 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2510 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002511 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002512 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2513 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002514 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002515 l2cap_send_cmd(conn, cmd->ident,
2516 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002517 } else if (type == L2CAP_IT_FIXED_CHAN) {
2518 u8 buf[12];
2519 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2520 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2521 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2522 memcpy(buf + 4, l2cap_fixed_chan, 8);
2523 l2cap_send_cmd(conn, cmd->ident,
2524 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002525 } else {
2526 struct l2cap_info_rsp rsp;
2527 rsp.type = cpu_to_le16(type);
2528 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2529 l2cap_send_cmd(conn, cmd->ident,
2530 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2531 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532
2533 return 0;
2534}
2535
2536static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2537{
2538 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2539 u16 type, result;
2540
2541 type = __le16_to_cpu(rsp->type);
2542 result = __le16_to_cpu(rsp->result);
2543
2544 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2545
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002546 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2547 if (cmd->ident != conn->info_ident ||
2548 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2549 return 0;
2550
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002551 del_timer(&conn->info_timer);
2552
Ville Tervoadb08ed2010-08-04 09:43:33 +03002553 if (result != L2CAP_IR_SUCCESS) {
2554 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2555 conn->info_ident = 0;
2556
2557 l2cap_conn_start(conn);
2558
2559 return 0;
2560 }
2561
Marcel Holtmann984947d2009-02-06 23:35:19 +01002562 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002563 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002564
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002565 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002566 struct l2cap_info_req req;
2567 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2568
2569 conn->info_ident = l2cap_get_ident(conn);
2570
2571 l2cap_send_cmd(conn, conn->info_ident,
2572 L2CAP_INFO_REQ, sizeof(req), &req);
2573 } else {
2574 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2575 conn->info_ident = 0;
2576
2577 l2cap_conn_start(conn);
2578 }
2579 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002580 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002581 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002582
2583 l2cap_conn_start(conn);
2584 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002585
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 return 0;
2587}
2588
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002589static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002590 u16 to_multiplier)
2591{
2592 u16 max_latency;
2593
2594 if (min > max || min < 6 || max > 3200)
2595 return -EINVAL;
2596
2597 if (to_multiplier < 10 || to_multiplier > 3200)
2598 return -EINVAL;
2599
2600 if (max >= to_multiplier * 8)
2601 return -EINVAL;
2602
2603 max_latency = (to_multiplier * 8 / max) - 1;
2604 if (latency > 499 || latency > max_latency)
2605 return -EINVAL;
2606
2607 return 0;
2608}
2609
2610static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2611 struct l2cap_cmd_hdr *cmd, u8 *data)
2612{
2613 struct hci_conn *hcon = conn->hcon;
2614 struct l2cap_conn_param_update_req *req;
2615 struct l2cap_conn_param_update_rsp rsp;
2616 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002617 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002618
2619 if (!(hcon->link_mode & HCI_LM_MASTER))
2620 return -EINVAL;
2621
2622 cmd_len = __le16_to_cpu(cmd->len);
2623 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2624 return -EPROTO;
2625
2626 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002627 min = __le16_to_cpu(req->min);
2628 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002629 latency = __le16_to_cpu(req->latency);
2630 to_multiplier = __le16_to_cpu(req->to_multiplier);
2631
2632 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2633 min, max, latency, to_multiplier);
2634
2635 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002636
2637 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2638 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002639 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2640 else
2641 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2642
2643 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2644 sizeof(rsp), &rsp);
2645
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002646 if (!err)
2647 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2648
Claudio Takahaside731152011-02-11 19:28:55 -02002649 return 0;
2650}
2651
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002652static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2653 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2654{
2655 int err = 0;
2656
2657 switch (cmd->code) {
2658 case L2CAP_COMMAND_REJ:
2659 l2cap_command_rej(conn, cmd, data);
2660 break;
2661
2662 case L2CAP_CONN_REQ:
2663 err = l2cap_connect_req(conn, cmd, data);
2664 break;
2665
2666 case L2CAP_CONN_RSP:
2667 err = l2cap_connect_rsp(conn, cmd, data);
2668 break;
2669
2670 case L2CAP_CONF_REQ:
2671 err = l2cap_config_req(conn, cmd, cmd_len, data);
2672 break;
2673
2674 case L2CAP_CONF_RSP:
2675 err = l2cap_config_rsp(conn, cmd, data);
2676 break;
2677
2678 case L2CAP_DISCONN_REQ:
2679 err = l2cap_disconnect_req(conn, cmd, data);
2680 break;
2681
2682 case L2CAP_DISCONN_RSP:
2683 err = l2cap_disconnect_rsp(conn, cmd, data);
2684 break;
2685
2686 case L2CAP_ECHO_REQ:
2687 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2688 break;
2689
2690 case L2CAP_ECHO_RSP:
2691 break;
2692
2693 case L2CAP_INFO_REQ:
2694 err = l2cap_information_req(conn, cmd, data);
2695 break;
2696
2697 case L2CAP_INFO_RSP:
2698 err = l2cap_information_rsp(conn, cmd, data);
2699 break;
2700
2701 default:
2702 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2703 err = -EINVAL;
2704 break;
2705 }
2706
2707 return err;
2708}
2709
2710static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2711 struct l2cap_cmd_hdr *cmd, u8 *data)
2712{
2713 switch (cmd->code) {
2714 case L2CAP_COMMAND_REJ:
2715 return 0;
2716
2717 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002718 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002719
2720 case L2CAP_CONN_PARAM_UPDATE_RSP:
2721 return 0;
2722
2723 default:
2724 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2725 return -EINVAL;
2726 }
2727}
2728
2729static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2730 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731{
2732 u8 *data = skb->data;
2733 int len = skb->len;
2734 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002735 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736
2737 l2cap_raw_recv(conn, skb);
2738
2739 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002740 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2742 data += L2CAP_CMD_HDR_SIZE;
2743 len -= L2CAP_CMD_HDR_SIZE;
2744
Al Viro88219a02007-07-29 00:17:25 -07002745 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746
Al Viro88219a02007-07-29 00:17:25 -07002747 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 -07002748
Al Viro88219a02007-07-29 00:17:25 -07002749 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750 BT_DBG("corrupted command");
2751 break;
2752 }
2753
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002754 if (conn->hcon->type == LE_LINK)
2755 err = l2cap_le_sig_cmd(conn, &cmd, data);
2756 else
2757 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758
2759 if (err) {
2760 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002761
2762 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763
2764 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002765 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2767 }
2768
Al Viro88219a02007-07-29 00:17:25 -07002769 data += cmd_len;
2770 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 }
2772
2773 kfree_skb(skb);
2774}
2775
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002776static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2777{
2778 u16 our_fcs, rcv_fcs;
2779 int hdr_size = L2CAP_HDR_SIZE + 2;
2780
2781 if (pi->fcs == L2CAP_FCS_CRC16) {
2782 skb_trim(skb, skb->len - 2);
2783 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2784 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2785
2786 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002787 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002788 }
2789 return 0;
2790}
2791
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002792static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002793{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002794 u16 control = 0;
2795
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002796 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002797
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002798 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002799
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002800 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002801 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002802 l2cap_send_sframe(chan, control);
2803 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002804 }
2805
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002806 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2807 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002808
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002809 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002810
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002811 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002812 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002813 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002814 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002815 }
2816}
2817
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002818static 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 -03002819{
2820 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002821 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002822
2823 bt_cb(skb)->tx_seq = tx_seq;
2824 bt_cb(skb)->sar = sar;
2825
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002826 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002827 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002828 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002829 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002830 }
2831
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002832 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002833 if (tx_seq_offset < 0)
2834 tx_seq_offset += 64;
2835
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002836 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002837 if (bt_cb(next_skb)->tx_seq == tx_seq)
2838 return -EINVAL;
2839
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002840 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002841 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002842 if (next_tx_seq_offset < 0)
2843 next_tx_seq_offset += 64;
2844
2845 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002846 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002847 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002848 }
2849
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002850 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002851 break;
2852
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002853 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002854
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002855 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002856
2857 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002858}
2859
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002860static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002861{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002862 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002863 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002864 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002865
2866 switch (control & L2CAP_CTRL_SAR) {
2867 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002868 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002869 goto drop;
2870
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002871 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002872 if (!err)
2873 return err;
2874
2875 break;
2876
2877 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002878 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002879 goto drop;
2880
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002881 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002882
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002883 if (chan->sdu_len > pi->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002884 goto disconnect;
2885
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002886 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
2887 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002888 return -ENOMEM;
2889
2890 /* pull sdu_len bytes only after alloc, because of Local Busy
2891 * condition we have to be sure that this will be executed
2892 * only once, i.e., when alloc does not fail */
2893 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002894
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002895 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002896
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002897 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002898 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002899 break;
2900
2901 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002902 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002903 goto disconnect;
2904
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002905 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002906 goto disconnect;
2907
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002908 chan->partial_sdu_len += skb->len;
2909 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002910 goto drop;
2911
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002912 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002913
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002914 break;
2915
2916 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002917 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002918 goto disconnect;
2919
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002920 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002921 goto disconnect;
2922
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002923 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002924 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002925
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002926 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002927 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002928
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002929 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002930 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002931
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002932 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002933 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002934
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002935 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002936 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002937 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002938 return -ENOMEM;
2939 }
2940
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002941 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002942 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002943 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002944 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002945 return err;
2946 }
2947
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002948 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2949 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002950
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002951 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002952 break;
2953 }
2954
2955 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002956 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002957
2958drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002959 kfree_skb(chan->sdu);
2960 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002961
2962disconnect:
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002963 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002964 kfree_skb(skb);
2965 return 0;
2966}
2967
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002968static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002969{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002970 struct sk_buff *skb;
2971 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002972 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002973
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002974 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002975 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002976 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002977 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002978 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002979 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002980 }
2981
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002982 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002983 }
2984
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002985 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002986 goto done;
2987
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002988 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002989 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002990 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002991 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002992
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002993 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002994 __mod_monitor_timer();
2995
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002996 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002997
2998done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002999 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3000 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003001
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003002 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003003
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003004 return 0;
3005}
3006
3007static void l2cap_busy_work(struct work_struct *work)
3008{
3009 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003010 struct l2cap_chan *chan =
3011 container_of(work, struct l2cap_chan, busy_work);
3012 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003013 int n_tries = 0, timeo = HZ/5, err;
3014 struct sk_buff *skb;
3015
3016 lock_sock(sk);
3017
3018 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003019 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003020 set_current_state(TASK_INTERRUPTIBLE);
3021
3022 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3023 err = -EBUSY;
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003024 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003025 break;
3026 }
3027
3028 if (!timeo)
3029 timeo = HZ/5;
3030
3031 if (signal_pending(current)) {
3032 err = sock_intr_errno(timeo);
3033 break;
3034 }
3035
3036 release_sock(sk);
3037 timeo = schedule_timeout(timeo);
3038 lock_sock(sk);
3039
3040 err = sock_error(sk);
3041 if (err)
3042 break;
3043
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003044 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003045 break;
3046 }
3047
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003048 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003049 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003050
3051 release_sock(sk);
3052}
3053
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003054static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003055{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003056 int sctrl, err;
3057
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003058 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003059 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003060 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003061 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003062
3063
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003064 }
3065
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003066 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003067 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003068 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003069 return err;
3070 }
3071
3072 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003073 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003074
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003075 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003076 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003077 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003078
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003079 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003080 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003081 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003082
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003083 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003084
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003085 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003086
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003087 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003088
3089 return err;
3090}
3091
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003092static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003093{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003094 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003095 struct sk_buff *_skb;
3096 int err = -EINVAL;
3097
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003098 /*
3099 * TODO: We have to notify the userland if some data is lost with the
3100 * Streaming Mode.
3101 */
3102
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003103 switch (control & L2CAP_CTRL_SAR) {
3104 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003105 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003106 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003107 break;
3108 }
3109
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003110 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003111 if (!err)
3112 return 0;
3113
3114 break;
3115
3116 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003117 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003118 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003119 break;
3120 }
3121
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003122 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003123 skb_pull(skb, 2);
3124
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003125 if (chan->sdu_len > pi->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003126 err = -EMSGSIZE;
3127 break;
3128 }
3129
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003130 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3131 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003132 err = -ENOMEM;
3133 break;
3134 }
3135
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003136 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003137
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003138 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003139 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003140 err = 0;
3141 break;
3142
3143 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003144 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003145 break;
3146
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003147 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003148
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003149 chan->partial_sdu_len += skb->len;
3150 if (chan->partial_sdu_len > chan->sdu_len)
3151 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003152 else
3153 err = 0;
3154
3155 break;
3156
3157 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003158 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003159 break;
3160
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003161 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003162
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003163 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003164 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003165
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003166 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003167 goto drop;
3168
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003169 if (chan->partial_sdu_len == chan->sdu_len) {
3170 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003171 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003172 if (err < 0)
3173 kfree_skb(_skb);
3174 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003175 err = 0;
3176
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003177drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003178 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003179 break;
3180 }
3181
3182 kfree_skb(skb);
3183 return err;
3184}
3185
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003186static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003187{
3188 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003189 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003190
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003191 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003192 if (bt_cb(skb)->tx_seq != tx_seq)
3193 break;
3194
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003195 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003196 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003197 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003198 chan->buffer_seq_srej =
3199 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003200 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003201 }
3202}
3203
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003204static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003205{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003206 struct srej_list *l, *tmp;
3207 u16 control;
3208
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003209 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003210 if (l->tx_seq == tx_seq) {
3211 list_del(&l->list);
3212 kfree(l);
3213 return;
3214 }
3215 control = L2CAP_SUPER_SELECT_REJECT;
3216 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003217 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003218 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003219 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003220 }
3221}
3222
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003223static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003224{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003225 struct srej_list *new;
3226 u16 control;
3227
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003228 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003229 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003230 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003231 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003232
3233 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003234 new->tx_seq = chan->expected_tx_seq;
3235 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003236 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003237 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003238 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003239}
3240
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003241static 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 -03003242{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003243 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003244 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003245 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003246 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003247 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003248 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003249 int err = 0;
3250
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003251 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3252 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003253
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003254 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003255 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003256 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003257 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003258 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003259 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003260 }
3261
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003262 chan->expected_ack_seq = req_seq;
3263 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003264
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003265 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003266 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003267
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003268 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003269 if (tx_seq_offset < 0)
3270 tx_seq_offset += 64;
3271
3272 /* invalid tx_seq */
3273 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003274 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003275 goto drop;
3276 }
3277
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003278 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003279 goto drop;
3280
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003281 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003282 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003283
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003284 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003285 struct srej_list, list);
3286 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003287 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003288 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003289
3290 list_del(&first->list);
3291 kfree(first);
3292
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003293 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003294 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003295 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3296 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003297 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003298 }
3299 } else {
3300 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003301
3302 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003303 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003304 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003305
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003306 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003307 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003308 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003309 return 0;
3310 }
3311 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003312 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003313 }
3314 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003315 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003316 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003317 if (expected_tx_seq_offset < 0)
3318 expected_tx_seq_offset += 64;
3319
3320 /* duplicated tx_seq */
3321 if (tx_seq_offset < expected_tx_seq_offset)
3322 goto drop;
3323
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003324 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003325
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003326 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003327
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003328 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003329 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003330
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003331 __skb_queue_head_init(&chan->srej_q);
3332 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003333 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003334
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003335 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003336
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003337 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003338
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003339 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003340 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003341 return 0;
3342
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003343expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003344 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003345
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003346 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003347 bt_cb(skb)->tx_seq = tx_seq;
3348 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003349 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003350 return 0;
3351 }
3352
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003353 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003354 if (err < 0)
3355 return 0;
3356
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003357 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003358 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3359 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003360 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003361 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003362 }
3363
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003364 __mod_ack_timer();
3365
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003366 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3367 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003368 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003369
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003370 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003371
3372drop:
3373 kfree_skb(skb);
3374 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003375}
3376
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003377static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003378{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003379 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003380 rx_control);
3381
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003382 chan->expected_ack_seq = __get_reqseq(rx_control);
3383 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003384
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003385 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003386 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3387 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3388 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003389 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003390 __mod_retrans_timer();
3391
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003392 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3393 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003394 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003395 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003396 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003397
3398 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003399 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003400
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003401 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3402 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003403 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003404 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003405
3406 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003407 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003408 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003409 __mod_retrans_timer();
3410
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003411 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3412 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3413 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003414 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003415 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003416 }
3417}
3418
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003419static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003420{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003421 u8 tx_seq = __get_reqseq(rx_control);
3422
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003423 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003424
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003425 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003426
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003427 chan->expected_ack_seq = tx_seq;
3428 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003429
3430 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003431 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3432 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003433 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003434 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003435 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003436 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003437
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003438 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3439 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003440 }
3441}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003442static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003443{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003444 u8 tx_seq = __get_reqseq(rx_control);
3445
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003446 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003447
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003448 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003449
3450 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003451 chan->expected_ack_seq = tx_seq;
3452 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003453
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003454 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3455 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003456
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003457 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003458
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003459 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003460 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003461 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003462 }
3463 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003464 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003465 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003466 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003467 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003468 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003469 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003470 l2cap_retransmit_one_frame(chan, tx_seq);
3471 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003472 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003473 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003474 }
3475 }
3476}
3477
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003478static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003479{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003480 u8 tx_seq = __get_reqseq(rx_control);
3481
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003482 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003483
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003484 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003485 chan->expected_ack_seq = tx_seq;
3486 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003487
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003488 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003489 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003490
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003491 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003492 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003493 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003494 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003495 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003496 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003497
3498 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003499 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003500 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003501 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003502}
3503
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003504static 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 -03003505{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003506 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003507
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003508 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003509 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003510 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003511 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003512 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003513 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003514 }
3515
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003516 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3517 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003518 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003519 break;
3520
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003521 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003522 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003523 break;
3524
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003525 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003526 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003527 break;
3528
3529 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003530 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003531 break;
3532 }
3533
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003534 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003535 return 0;
3536}
3537
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003538static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3539{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003540 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003541 struct l2cap_pinfo *pi = l2cap_pi(sk);
3542 u16 control;
3543 u8 req_seq;
3544 int len, next_tx_seq_offset, req_seq_offset;
3545
3546 control = get_unaligned_le16(skb->data);
3547 skb_pull(skb, 2);
3548 len = skb->len;
3549
3550 /*
3551 * We can just drop the corrupted I-frame here.
3552 * Receiver will miss it and start proper recovery
3553 * procedures and ask retransmission.
3554 */
3555 if (l2cap_check_fcs(pi, skb))
3556 goto drop;
3557
3558 if (__is_sar_start(control) && __is_iframe(control))
3559 len -= 2;
3560
3561 if (pi->fcs == L2CAP_FCS_CRC16)
3562 len -= 2;
3563
3564 if (len > pi->mps) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003565 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003566 goto drop;
3567 }
3568
3569 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003570 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003571 if (req_seq_offset < 0)
3572 req_seq_offset += 64;
3573
3574 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003575 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003576 if (next_tx_seq_offset < 0)
3577 next_tx_seq_offset += 64;
3578
3579 /* check for invalid req-seq */
3580 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003581 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003582 goto drop;
3583 }
3584
3585 if (__is_iframe(control)) {
3586 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003587 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003588 goto drop;
3589 }
3590
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003591 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003592 } else {
3593 if (len != 0) {
3594 BT_ERR("%d", len);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003595 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003596 goto drop;
3597 }
3598
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003599 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003600 }
3601
3602 return 0;
3603
3604drop:
3605 kfree_skb(skb);
3606 return 0;
3607}
3608
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3610{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003611 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003612 struct sock *sk = NULL;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003613 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003614 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003615 u8 tx_seq;
3616 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003618 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003619 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003620 BT_DBG("unknown cid 0x%4.4x", cid);
3621 goto drop;
3622 }
3623
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003624 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003625 pi = l2cap_pi(sk);
3626
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003627 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003628
3629 if (sk->sk_state != BT_CONNECTED)
3630 goto drop;
3631
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003632 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003633 case L2CAP_MODE_BASIC:
3634 /* If socket recv buffers overflows we drop data here
3635 * which is *bad* because L2CAP has to be reliable.
3636 * But we don't have any other choice. L2CAP doesn't
3637 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003639 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003640 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003641
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003642 if (!sock_queue_rcv_skb(sk, skb))
3643 goto done;
3644 break;
3645
3646 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003647 if (!sock_owned_by_user(sk)) {
3648 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003649 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003650 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003651 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003652 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003653
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003654 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003655
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003656 case L2CAP_MODE_STREAMING:
3657 control = get_unaligned_le16(skb->data);
3658 skb_pull(skb, 2);
3659 len = skb->len;
3660
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003661 if (l2cap_check_fcs(pi, skb))
3662 goto drop;
3663
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003664 if (__is_sar_start(control))
3665 len -= 2;
3666
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003667 if (pi->fcs == L2CAP_FCS_CRC16)
3668 len -= 2;
3669
Nathan Holstein51893f82010-06-09 15:46:25 -04003670 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003671 goto drop;
3672
3673 tx_seq = __get_txseq(control);
3674
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003675 if (chan->expected_tx_seq == tx_seq)
3676 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003677 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003678 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003679
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003680 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003681
3682 goto done;
3683
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003684 default:
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003685 BT_DBG("chan %p: bad mode 0x%2.2x", chan, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003686 break;
3687 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003688
3689drop:
3690 kfree_skb(skb);
3691
3692done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003693 if (sk)
3694 bh_unlock_sock(sk);
3695
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696 return 0;
3697}
3698
Al Viro8e036fc2007-07-29 00:16:36 -07003699static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700{
3701 struct sock *sk;
3702
3703 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3704 if (!sk)
3705 goto drop;
3706
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003707 bh_lock_sock(sk);
3708
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709 BT_DBG("sk %p, len %d", sk, skb->len);
3710
3711 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3712 goto drop;
3713
3714 if (l2cap_pi(sk)->imtu < skb->len)
3715 goto drop;
3716
3717 if (!sock_queue_rcv_skb(sk, skb))
3718 goto done;
3719
3720drop:
3721 kfree_skb(skb);
3722
3723done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003724 if (sk)
3725 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726 return 0;
3727}
3728
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003729static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3730{
3731 struct sock *sk;
3732
3733 sk = l2cap_get_sock_by_scid(0, cid, conn->src);
3734 if (!sk)
3735 goto drop;
3736
3737 bh_lock_sock(sk);
3738
3739 BT_DBG("sk %p, len %d", sk, skb->len);
3740
3741 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3742 goto drop;
3743
3744 if (l2cap_pi(sk)->imtu < skb->len)
3745 goto drop;
3746
3747 if (!sock_queue_rcv_skb(sk, skb))
3748 goto done;
3749
3750drop:
3751 kfree_skb(skb);
3752
3753done:
3754 if (sk)
3755 bh_unlock_sock(sk);
3756 return 0;
3757}
3758
Linus Torvalds1da177e2005-04-16 15:20:36 -07003759static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3760{
3761 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003762 u16 cid, len;
3763 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764
3765 skb_pull(skb, L2CAP_HDR_SIZE);
3766 cid = __le16_to_cpu(lh->cid);
3767 len = __le16_to_cpu(lh->len);
3768
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003769 if (len != skb->len) {
3770 kfree_skb(skb);
3771 return;
3772 }
3773
Linus Torvalds1da177e2005-04-16 15:20:36 -07003774 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3775
3776 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003777 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003778 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779 l2cap_sig_channel(conn, skb);
3780 break;
3781
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003782 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003783 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784 skb_pull(skb, 2);
3785 l2cap_conless_channel(conn, psm, skb);
3786 break;
3787
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003788 case L2CAP_CID_LE_DATA:
3789 l2cap_att_channel(conn, cid, skb);
3790 break;
3791
Linus Torvalds1da177e2005-04-16 15:20:36 -07003792 default:
3793 l2cap_data_channel(conn, cid, skb);
3794 break;
3795 }
3796}
3797
3798/* ---- L2CAP interface with lower layer (HCI) ---- */
3799
3800static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3801{
3802 int exact = 0, lm1 = 0, lm2 = 0;
3803 register struct sock *sk;
3804 struct hlist_node *node;
3805
3806 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003807 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808
3809 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3810
3811 /* Find listening sockets and check their link_mode */
3812 read_lock(&l2cap_sk_list.lock);
3813 sk_for_each(sk, node, &l2cap_sk_list.head) {
3814 if (sk->sk_state != BT_LISTEN)
3815 continue;
3816
3817 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003818 lm1 |= HCI_LM_ACCEPT;
3819 if (l2cap_pi(sk)->role_switch)
3820 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003822 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3823 lm2 |= HCI_LM_ACCEPT;
3824 if (l2cap_pi(sk)->role_switch)
3825 lm2 |= HCI_LM_MASTER;
3826 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827 }
3828 read_unlock(&l2cap_sk_list.lock);
3829
3830 return exact ? lm1 : lm2;
3831}
3832
3833static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3834{
Marcel Holtmann01394182006-07-03 10:02:46 +02003835 struct l2cap_conn *conn;
3836
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3838
Ville Tervoacd7d372011-02-10 22:38:49 -03003839 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003840 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841
3842 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843 conn = l2cap_conn_add(hcon, status);
3844 if (conn)
3845 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003846 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003847 l2cap_conn_del(hcon, bt_err(status));
3848
3849 return 0;
3850}
3851
Marcel Holtmann2950f212009-02-12 14:02:50 +01003852static int l2cap_disconn_ind(struct hci_conn *hcon)
3853{
3854 struct l2cap_conn *conn = hcon->l2cap_data;
3855
3856 BT_DBG("hcon %p", hcon);
3857
3858 if (hcon->type != ACL_LINK || !conn)
3859 return 0x13;
3860
3861 return conn->disc_reason;
3862}
3863
3864static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865{
3866 BT_DBG("hcon %p reason %d", hcon, reason);
3867
Ville Tervoacd7d372011-02-10 22:38:49 -03003868 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003869 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870
3871 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003872
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873 return 0;
3874}
3875
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003876static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3877{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003878 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003879 return;
3880
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003881 if (encrypt == 0x00) {
3882 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3883 l2cap_sock_clear_timer(sk);
3884 l2cap_sock_set_timer(sk, HZ * 5);
3885 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3886 __l2cap_sock_close(sk, ECONNREFUSED);
3887 } else {
3888 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3889 l2cap_sock_clear_timer(sk);
3890 }
3891}
3892
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003893static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003895 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003896 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897
Marcel Holtmann01394182006-07-03 10:02:46 +02003898 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003900
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901 BT_DBG("conn %p", conn);
3902
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003903 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003905 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003906 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003907
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908 bh_lock_sock(sk);
3909
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003910 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3911 bh_unlock_sock(sk);
3912 continue;
3913 }
3914
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003915 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003916 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003917 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003918 bh_unlock_sock(sk);
3919 continue;
3920 }
3921
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003922 if (sk->sk_state == BT_CONNECT) {
3923 if (!status) {
3924 struct l2cap_conn_req req;
3925 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3926 req.psm = l2cap_pi(sk)->psm;
3927
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003928 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003929 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003930
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003931 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003932 L2CAP_CONN_REQ, sizeof(req), &req);
3933 } else {
3934 l2cap_sock_clear_timer(sk);
3935 l2cap_sock_set_timer(sk, HZ / 10);
3936 }
3937 } else if (sk->sk_state == BT_CONNECT2) {
3938 struct l2cap_conn_rsp rsp;
3939 __u16 result;
3940
3941 if (!status) {
3942 sk->sk_state = BT_CONFIG;
3943 result = L2CAP_CR_SUCCESS;
3944 } else {
3945 sk->sk_state = BT_DISCONN;
3946 l2cap_sock_set_timer(sk, HZ / 10);
3947 result = L2CAP_CR_SEC_BLOCK;
3948 }
3949
3950 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3951 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3952 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003953 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003954 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
3955 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956 }
3957
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 bh_unlock_sock(sk);
3959 }
3960
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003961 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003962
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963 return 0;
3964}
3965
3966static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3967{
3968 struct l2cap_conn *conn = hcon->l2cap_data;
3969
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003970 if (!conn)
3971 conn = l2cap_conn_add(hcon, 0);
3972
3973 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974 goto drop;
3975
3976 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3977
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003978 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003979 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003980 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003981 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982 int len;
3983
3984 if (conn->rx_len) {
3985 BT_ERR("Unexpected start frame (len %d)", skb->len);
3986 kfree_skb(conn->rx_skb);
3987 conn->rx_skb = NULL;
3988 conn->rx_len = 0;
3989 l2cap_conn_unreliable(conn, ECOMM);
3990 }
3991
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003992 /* Start fragment always begin with Basic L2CAP header */
3993 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994 BT_ERR("Frame is too short (len %d)", skb->len);
3995 l2cap_conn_unreliable(conn, ECOMM);
3996 goto drop;
3997 }
3998
3999 hdr = (struct l2cap_hdr *) skb->data;
4000 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004001 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002
4003 if (len == skb->len) {
4004 /* Complete frame received */
4005 l2cap_recv_frame(conn, skb);
4006 return 0;
4007 }
4008
4009 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4010
4011 if (skb->len > len) {
4012 BT_ERR("Frame is too long (len %d, expected len %d)",
4013 skb->len, len);
4014 l2cap_conn_unreliable(conn, ECOMM);
4015 goto drop;
4016 }
4017
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004018 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004019
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004020 if (chan && chan->sk) {
4021 struct sock *sk = chan->sk;
4022
4023 if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
4024 BT_ERR("Frame exceeding recv MTU (len %d, "
4025 "MTU %d)", len,
4026 l2cap_pi(sk)->imtu);
4027 bh_unlock_sock(sk);
4028 l2cap_conn_unreliable(conn, ECOMM);
4029 goto drop;
4030 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004031 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004032 }
4033
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004035 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4036 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037 goto drop;
4038
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004039 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004040 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041 conn->rx_len = len - skb->len;
4042 } else {
4043 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4044
4045 if (!conn->rx_len) {
4046 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4047 l2cap_conn_unreliable(conn, ECOMM);
4048 goto drop;
4049 }
4050
4051 if (skb->len > conn->rx_len) {
4052 BT_ERR("Fragment is too long (len %d, expected %d)",
4053 skb->len, conn->rx_len);
4054 kfree_skb(conn->rx_skb);
4055 conn->rx_skb = NULL;
4056 conn->rx_len = 0;
4057 l2cap_conn_unreliable(conn, ECOMM);
4058 goto drop;
4059 }
4060
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004061 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004062 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063 conn->rx_len -= skb->len;
4064
4065 if (!conn->rx_len) {
4066 /* Complete frame received */
4067 l2cap_recv_frame(conn, conn->rx_skb);
4068 conn->rx_skb = NULL;
4069 }
4070 }
4071
4072drop:
4073 kfree_skb(skb);
4074 return 0;
4075}
4076
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004077static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078{
4079 struct sock *sk;
4080 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081
4082 read_lock_bh(&l2cap_sk_list.lock);
4083
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004084 sk_for_each(sk, node, &l2cap_sk_list.head) {
4085 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004087 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 +01004088 batostr(&bt_sk(sk)->src),
4089 batostr(&bt_sk(sk)->dst),
4090 sk->sk_state, __le16_to_cpu(pi->psm),
4091 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004092 pi->imtu, pi->omtu, pi->sec_level,
4093 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004094 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004097
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004098 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099}
4100
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004101static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4102{
4103 return single_open(file, l2cap_debugfs_show, inode->i_private);
4104}
4105
4106static const struct file_operations l2cap_debugfs_fops = {
4107 .open = l2cap_debugfs_open,
4108 .read = seq_read,
4109 .llseek = seq_lseek,
4110 .release = single_release,
4111};
4112
4113static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115static struct hci_proto l2cap_hci_proto = {
4116 .name = "L2CAP",
4117 .id = HCI_PROTO_L2CAP,
4118 .connect_ind = l2cap_connect_ind,
4119 .connect_cfm = l2cap_connect_cfm,
4120 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004121 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004122 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123 .recv_acldata = l2cap_recv_acldata
4124};
4125
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004126int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127{
4128 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004129
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004130 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131 if (err < 0)
4132 return err;
4133
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004134 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004135 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004136 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137 goto error;
4138 }
4139
4140 err = hci_register_proto(&l2cap_hci_proto);
4141 if (err < 0) {
4142 BT_ERR("L2CAP protocol registration failed");
4143 bt_sock_unregister(BTPROTO_L2CAP);
4144 goto error;
4145 }
4146
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004147 if (bt_debugfs) {
4148 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4149 bt_debugfs, NULL, &l2cap_debugfs_fops);
4150 if (!l2cap_debugfs)
4151 BT_ERR("Failed to create L2CAP debug file");
4152 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154 return 0;
4155
4156error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004157 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004158 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159 return err;
4160}
4161
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004162void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004163{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004164 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004166 flush_workqueue(_busy_wq);
4167 destroy_workqueue(_busy_wq);
4168
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4170 BT_ERR("L2CAP protocol unregistration failed");
4171
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004172 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173}
4174
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004175module_param(disable_ertm, bool, 0644);
4176MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");