blob: 97827506dc940d2a19d1640d4d38b2e182da69ca [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
7 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation;
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
16 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090017 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090022 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
23 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 SOFTWARE IS DISCLAIMED.
25*/
26
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020027/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30
31#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080032#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
34#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/poll.h>
38#include <linux/fcntl.h>
39#include <linux/init.h>
40#include <linux/interrupt.h>
41#include <linux/socket.h>
42#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080044#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010045#include <linux/debugfs.h>
46#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030047#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030048#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/sock.h>
50
51#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
57
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020058int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020059
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070060static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010061static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030063static struct workqueue_struct *_busy_wq;
64
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020065struct bt_sock_list l2cap_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070066 .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070067};
68
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030069static void l2cap_busy_work(struct work_struct *work);
70
Linus Torvalds1da177e2005-04-16 15:20:36 -070071static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
72 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030073static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030075static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
76
Marcel Holtmann01394182006-07-03 10:02:46 +020077/* ---- L2CAP channels ---- */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030078static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020079{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030080 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030081
82 list_for_each_entry(c, &conn->chan_l, list) {
83 struct sock *s = c->sk;
84 if (l2cap_pi(s)->dcid == cid)
85 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020086 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030087 return NULL;
88
Marcel Holtmann01394182006-07-03 10:02:46 +020089}
90
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030091static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020092{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030093 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030094
95 list_for_each_entry(c, &conn->chan_l, list) {
96 struct sock *s = c->sk;
97 if (l2cap_pi(s)->scid == cid)
98 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020099 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300100 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200101}
102
103/* Find channel with given SCID.
104 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300105static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200106{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300107 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300108
109 read_lock(&conn->chan_lock);
110 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300111 if (c)
112 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300113 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300114 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200115}
116
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300117static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200118{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300119 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300120
121 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300122 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300123 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200124 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300125 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200126}
127
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300128static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200129{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300130 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300131
132 read_lock(&conn->chan_lock);
133 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300134 if (c)
135 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300136 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300137 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200138}
139
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300140static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200141{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300142 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200143
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300144 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300145 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200146 return cid;
147 }
148
149 return 0;
150}
151
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300152static struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200153{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300154 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200155
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300156 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
157 if (!chan)
158 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200159
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300160 chan->sk = sk;
161
162 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200163}
164
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300165static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200166{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300167 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200168
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300169 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
170 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200171
Marcel Holtmann2950f212009-02-12 14:02:50 +0100172 conn->disc_reason = 0x13;
173
Marcel Holtmann01394182006-07-03 10:02:46 +0200174 l2cap_pi(sk)->conn = conn;
175
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300176 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Ville Tervob62f3282011-02-10 22:38:50 -0300177 if (conn->hcon->type == LE_LINK) {
178 /* LE connection */
179 l2cap_pi(sk)->omtu = L2CAP_LE_DEFAULT_MTU;
180 l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA;
181 l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA;
182 } else {
183 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300184 l2cap_pi(sk)->scid = l2cap_alloc_cid(conn);
Ville Tervob62f3282011-02-10 22:38:50 -0300185 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
186 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200187 } else if (sk->sk_type == SOCK_DGRAM) {
188 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300189 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
190 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200191 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
192 } else {
193 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300194 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
195 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200196 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
197 }
198
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300199 sock_hold(sk);
200
201 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200202}
203
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900204/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200205 * Must be called on the locked socket. */
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300206void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200207{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300208 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200209 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
210 struct sock *parent = bt_sk(sk)->parent;
211
212 l2cap_sock_clear_timer(sk);
213
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300214 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200215
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900216 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300217 /* Delete from channel list */
218 write_lock_bh(&conn->chan_lock);
219 list_del(&chan->list);
220 write_unlock_bh(&conn->chan_lock);
221 __sock_put(sk);
222
Marcel Holtmann01394182006-07-03 10:02:46 +0200223 l2cap_pi(sk)->conn = NULL;
224 hci_conn_put(conn->hcon);
225 }
226
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200227 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200228 sock_set_flag(sk, SOCK_ZAPPED);
229
230 if (err)
231 sk->sk_err = err;
232
233 if (parent) {
234 bt_accept_unlink(sk);
235 parent->sk_data_ready(parent, 0);
236 } else
237 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300238
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300239 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE &&
240 l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE))
241 goto free;
242
Gustavo F. 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. Padovan58d35f82011-04-04 16:16:44 -0300480 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300481
482 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300483 del_timer(&chan->retrans_timer);
484 del_timer(&chan->monitor_timer);
485 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300486 }
487
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300488 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
489 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
490 l2cap_send_cmd(conn, l2cap_get_ident(conn),
491 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300492
493 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300494 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300495}
496
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200498static void l2cap_conn_start(struct l2cap_conn *conn)
499{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300500 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200501
502 BT_DBG("conn %p", conn);
503
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300504 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200505
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300506 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300507 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300508
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200509 bh_lock_sock(sk);
510
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300511 if (sk->sk_type != SOCK_SEQPACKET &&
512 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200513 bh_unlock_sock(sk);
514 continue;
515 }
516
517 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300518 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300519
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300520 if (!l2cap_check_security(sk) ||
521 !__l2cap_no_conn_pending(sk)) {
522 bh_unlock_sock(sk);
523 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200524 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300525
526 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
527 conn->feat_mask)
528 && l2cap_pi(sk)->conf_state &
529 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300530 /* __l2cap_sock_close() calls list_del(chan)
531 * so release the lock */
532 read_unlock_bh(&conn->chan_lock);
533 __l2cap_sock_close(sk, ECONNRESET);
534 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300535 bh_unlock_sock(sk);
536 continue;
537 }
538
539 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
540 req.psm = l2cap_pi(sk)->psm;
541
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300542 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300543 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
544
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300545 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
546 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300547
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200548 } else if (sk->sk_state == BT_CONNECT2) {
549 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300550 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200551 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
552 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
553
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100554 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100555 if (bt_sk(sk)->defer_setup) {
556 struct sock *parent = bt_sk(sk)->parent;
557 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
558 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
559 parent->sk_data_ready(parent, 0);
560
561 } else {
562 sk->sk_state = BT_CONFIG;
563 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
564 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
565 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200566 } else {
567 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
568 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
569 }
570
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300571 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
572 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300573
574 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
575 rsp.result != L2CAP_CR_SUCCESS) {
576 bh_unlock_sock(sk);
577 continue;
578 }
579
580 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
581 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300582 l2cap_build_conf_req(chan, buf), buf);
583 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200584 }
585
586 bh_unlock_sock(sk);
587 }
588
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300589 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200590}
591
Ville Tervob62f3282011-02-10 22:38:50 -0300592/* Find socket with cid and source bdaddr.
593 * Returns closest match, locked.
594 */
595static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
596{
597 struct sock *s, *sk = NULL, *sk1 = NULL;
598 struct hlist_node *node;
599
600 read_lock(&l2cap_sk_list.lock);
601
602 sk_for_each(sk, node, &l2cap_sk_list.head) {
603 if (state && sk->sk_state != state)
604 continue;
605
606 if (l2cap_pi(sk)->scid == cid) {
607 /* Exact match. */
608 if (!bacmp(&bt_sk(sk)->src, src))
609 break;
610
611 /* Closest match */
612 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
613 sk1 = sk;
614 }
615 }
616 s = node ? sk : sk1;
617 if (s)
618 bh_lock_sock(s);
619 read_unlock(&l2cap_sk_list.lock);
620
621 return s;
622}
623
624static void l2cap_le_conn_ready(struct l2cap_conn *conn)
625{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300626 struct sock *parent, *sk;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300627 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300628
629 BT_DBG("");
630
631 /* Check if we have socket listening on cid */
632 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
633 conn->src);
634 if (!parent)
635 return;
636
637 /* Check for backlog size */
638 if (sk_acceptq_is_full(parent)) {
639 BT_DBG("backlog full %d", parent->sk_ack_backlog);
640 goto clean;
641 }
642
643 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
644 if (!sk)
645 goto clean;
646
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300647 chan = l2cap_chan_alloc(sk);
648 if (!chan) {
649 l2cap_sock_kill(sk);
650 goto clean;
651 }
652
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300653 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300654
655 hci_conn_hold(conn->hcon);
656
657 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300658
Ville Tervob62f3282011-02-10 22:38:50 -0300659 bacpy(&bt_sk(sk)->src, conn->src);
660 bacpy(&bt_sk(sk)->dst, conn->dst);
661
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300662 bt_accept_enqueue(parent, sk);
663
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300664 __l2cap_chan_add(conn, chan);
665
666 l2cap_pi(sk)->chan = chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300667
668 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
669
670 sk->sk_state = BT_CONNECTED;
671 parent->sk_data_ready(parent, 0);
672
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300673 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300674
675clean:
676 bh_unlock_sock(parent);
677}
678
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200679static void l2cap_conn_ready(struct l2cap_conn *conn)
680{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300681 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200682
683 BT_DBG("conn %p", conn);
684
Ville Tervob62f3282011-02-10 22:38:50 -0300685 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
686 l2cap_le_conn_ready(conn);
687
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300688 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200689
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300690 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300691 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300692
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200693 bh_lock_sock(sk);
694
Ville Tervoacd7d372011-02-10 22:38:49 -0300695 if (conn->hcon->type == LE_LINK) {
696 l2cap_sock_clear_timer(sk);
697 sk->sk_state = BT_CONNECTED;
698 sk->sk_state_change(sk);
699 }
700
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300701 if (sk->sk_type != SOCK_SEQPACKET &&
702 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200703 l2cap_sock_clear_timer(sk);
704 sk->sk_state = BT_CONNECTED;
705 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200706 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300707 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200708
709 bh_unlock_sock(sk);
710 }
711
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300712 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200713}
714
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200715/* Notify sockets that we cannot guaranty reliability anymore */
716static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
717{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300718 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200719
720 BT_DBG("conn %p", conn);
721
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300722 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200723
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300724 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300725 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300726
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100727 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200728 sk->sk_err = err;
729 }
730
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300731 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200732}
733
734static void l2cap_info_timeout(unsigned long arg)
735{
736 struct l2cap_conn *conn = (void *) arg;
737
Marcel Holtmann984947d2009-02-06 23:35:19 +0100738 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100739 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100740
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200741 l2cap_conn_start(conn);
742}
743
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
745{
Marcel Holtmann01394182006-07-03 10:02:46 +0200746 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
Marcel Holtmann01394182006-07-03 10:02:46 +0200748 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 return conn;
750
Marcel Holtmann01394182006-07-03 10:02:46 +0200751 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
752 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
755 hcon->l2cap_data = conn;
756 conn->hcon = hcon;
757
Marcel Holtmann01394182006-07-03 10:02:46 +0200758 BT_DBG("hcon %p conn %p", hcon, conn);
759
Ville Tervoacd7d372011-02-10 22:38:49 -0300760 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
761 conn->mtu = hcon->hdev->le_mtu;
762 else
763 conn->mtu = hcon->hdev->acl_mtu;
764
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 conn->src = &hcon->hdev->bdaddr;
766 conn->dst = &hcon->dst;
767
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200768 conn->feat_mask = 0;
769
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300771 rwlock_init(&conn->chan_lock);
772
773 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774
Ville Tervob62f3282011-02-10 22:38:50 -0300775 if (hcon->type != LE_LINK)
776 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000777 (unsigned long) conn);
778
Marcel Holtmann2950f212009-02-12 14:02:50 +0100779 conn->disc_reason = 0x13;
780
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 return conn;
782}
783
Marcel Holtmann01394182006-07-03 10:02:46 +0200784static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785{
Marcel Holtmann01394182006-07-03 10:02:46 +0200786 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300787 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 struct sock *sk;
789
Marcel Holtmann01394182006-07-03 10:02:46 +0200790 if (!conn)
791 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
793 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
794
Wei Yongjun7585b972009-02-25 18:29:52 +0800795 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796
797 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300798 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300799 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300801 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 bh_unlock_sock(sk);
803 l2cap_sock_kill(sk);
804 }
805
Dave Young8e8440f2008-03-03 12:18:55 -0800806 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
807 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800808
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 hcon->l2cap_data = NULL;
810 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811}
812
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300813static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300815 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300816 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300817 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818}
819
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
822/* Find socket with psm and source bdaddr.
823 * Returns closest match.
824 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000825static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826{
827 struct sock *sk = NULL, *sk1 = NULL;
828 struct hlist_node *node;
829
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000830 read_lock(&l2cap_sk_list.lock);
831
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 sk_for_each(sk, node, &l2cap_sk_list.head) {
833 if (state && sk->sk_state != state)
834 continue;
835
836 if (l2cap_pi(sk)->psm == psm) {
837 /* Exact match. */
838 if (!bacmp(&bt_sk(sk)->src, src))
839 break;
840
841 /* Closest match */
842 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
843 sk1 = sk;
844 }
845 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000848
849 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850}
851
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200852int l2cap_do_connect(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853{
854 bdaddr_t *src = &bt_sk(sk)->src;
855 bdaddr_t *dst = &bt_sk(sk)->dst;
856 struct l2cap_conn *conn;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300857 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 struct hci_conn *hcon;
859 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200860 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200861 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100863 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
864 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300866 hdev = hci_get_route(dst, src);
867 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 return -EHOSTUNREACH;
869
870 hci_dev_lock_bh(hdev);
871
Johan Hedberg8556edd32011-01-19 12:06:50 +0530872 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200873
Ville Tervoacd7d372011-02-10 22:38:49 -0300874 if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
875 hcon = hci_connect(hdev, LE_LINK, dst,
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100876 l2cap_pi(sk)->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300877 else
878 hcon = hci_connect(hdev, ACL_LINK, dst,
879 l2cap_pi(sk)->sec_level, auth_type);
880
Ville Tervo30e76272011-02-22 16:10:53 -0300881 if (IS_ERR(hcon)) {
882 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300884 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885
886 conn = l2cap_conn_add(hcon, 0);
887 if (!conn) {
888 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300889 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 goto done;
891 }
892
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300893 chan = l2cap_chan_alloc(sk);
894 if (!chan) {
895 hci_conn_put(hcon);
896 err = -ENOMEM;
897 goto done;
898 }
899
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 /* Update source addr of the socket */
901 bacpy(src, conn->src);
902
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300903 l2cap_chan_add(conn, chan);
904
905 l2cap_pi(sk)->chan = chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906
907 sk->sk_state = BT_CONNECT;
908 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
909
910 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300911 if (sk->sk_type != SOCK_SEQPACKET &&
912 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530914 if (l2cap_check_security(sk))
915 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200916 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300917 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 }
919
Ville Tervo30e76272011-02-22 16:10:53 -0300920 err = 0;
921
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922done:
923 hci_dev_unlock_bh(hdev);
924 hci_dev_put(hdev);
925 return err;
926}
927
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200928int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300929{
930 DECLARE_WAITQUEUE(wait, current);
931 int err = 0;
932 int timeo = HZ/5;
933
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200934 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300935 while ((l2cap_pi(sk)->chan->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300936 set_current_state(TASK_INTERRUPTIBLE);
937
938 if (!timeo)
939 timeo = HZ/5;
940
941 if (signal_pending(current)) {
942 err = sock_intr_errno(timeo);
943 break;
944 }
945
946 release_sock(sk);
947 timeo = schedule_timeout(timeo);
948 lock_sock(sk);
949
950 err = sock_error(sk);
951 if (err)
952 break;
953 }
954 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200955 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300956 return err;
957}
958
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300959static void l2cap_monitor_timeout(unsigned long arg)
960{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300961 struct l2cap_chan *chan = (void *) arg;
962 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300963
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300964 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300965
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300966 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -0300967 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300968 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200969 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300970 return;
971 }
972
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300973 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300974 __mod_monitor_timer();
975
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300976 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300977 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300978}
979
980static void l2cap_retrans_timeout(unsigned long arg)
981{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300982 struct l2cap_chan *chan = (void *) arg;
983 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300984
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300985 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300986
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300987 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300988 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300989 __mod_monitor_timer();
990
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300991 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300992
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300993 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300994 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300995}
996
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300997static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300998{
999 struct sk_buff *skb;
1000
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001001 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001002 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001003 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001004 break;
1005
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001006 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001007 kfree_skb(skb);
1008
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001009 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001010 }
1011
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001012 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001013 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001014}
1015
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001016void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001017{
1018 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001019 struct hci_conn *hcon = pi->conn->hcon;
1020 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001021
1022 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1023
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001024 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
1025 flags = ACL_START_NO_FLUSH;
1026 else
1027 flags = ACL_START;
1028
1029 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001030}
1031
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001032void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001033{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001034 struct sock *sk = chan->sk;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001035 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001036 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001037 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001038
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001039 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001040 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001041 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001042 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001043
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001044 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001045 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1046 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001047 }
1048
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001049 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001050
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001051 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001052 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001053}
1054
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001055static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001056{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001057 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001058 struct l2cap_pinfo *pi = l2cap_pi(sk);
1059 struct sk_buff *skb, *tx_skb;
1060 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001061
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001062 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001063 if (!skb)
1064 return;
1065
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001066 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001067 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001068 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001069
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001070 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001071 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001072
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001073 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001074
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001075 if (chan->remote_max_tx &&
1076 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001077 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001078 return;
1079 }
1080
1081 tx_skb = skb_clone(skb, GFP_ATOMIC);
1082 bt_cb(skb)->retries++;
1083 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001084
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001085 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001086 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001087 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001088 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001089
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001090 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001091 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001092
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001093 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1094
1095 if (pi->fcs == L2CAP_FCS_CRC16) {
1096 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1097 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1098 }
1099
1100 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001101}
1102
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001103int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001104{
1105 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001106 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001107 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001108 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001109 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001110
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001111 if (sk->sk_state != BT_CONNECTED)
1112 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001113
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001114 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001115
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001116 if (chan->remote_max_tx &&
1117 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001118 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001119 break;
1120 }
1121
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001122 tx_skb = skb_clone(skb, GFP_ATOMIC);
1123
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001124 bt_cb(skb)->retries++;
1125
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001126 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001127 control &= L2CAP_CTRL_SAR;
1128
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001129 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001130 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001131 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001132 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001133 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1134 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001135 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1136
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001137
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001138 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001139 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1140 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1141 }
1142
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001143 l2cap_do_send(sk, tx_skb);
1144
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001145 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001146
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001147 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1148 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001149
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301150 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001151 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301152
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001153 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001154
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001155 if (skb_queue_is_last(&chan->tx_q, skb))
1156 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001157 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001158 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001159
1160 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001161 }
1162
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001163 return nsent;
1164}
1165
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001166static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001167{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001168 int ret;
1169
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001170 if (!skb_queue_empty(&chan->tx_q))
1171 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001172
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001173 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001174 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001175 return ret;
1176}
1177
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001178static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001179{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001180 u16 control = 0;
1181
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001182 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001183
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001184 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001185 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001186 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1187 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001188 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001189 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001190
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001191 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001192 return;
1193
1194 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001195 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001196}
1197
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001198static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001199{
1200 struct srej_list *tail;
1201 u16 control;
1202
1203 control = L2CAP_SUPER_SELECT_REJECT;
1204 control |= L2CAP_CTRL_FINAL;
1205
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001206 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001207 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1208
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001209 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001210}
1211
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001212static 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 -07001213{
1214 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001215 struct sk_buff **frag;
1216 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001218 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001219 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220
1221 sent += count;
1222 len -= count;
1223
1224 /* Continuation fragments (no L2CAP header) */
1225 frag = &skb_shinfo(skb)->frag_list;
1226 while (len) {
1227 count = min_t(unsigned int, conn->mtu, len);
1228
1229 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1230 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001231 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001232 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1233 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234
1235 sent += count;
1236 len -= count;
1237
1238 frag = &(*frag)->next;
1239 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240
1241 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001242}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001244struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001245{
1246 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1247 struct sk_buff *skb;
1248 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1249 struct l2cap_hdr *lh;
1250
1251 BT_DBG("sk %p len %d", sk, (int)len);
1252
1253 count = min_t(unsigned int, (conn->mtu - hlen), len);
1254 skb = bt_skb_send_alloc(sk, count + hlen,
1255 msg->msg_flags & MSG_DONTWAIT, &err);
1256 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001257 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001258
1259 /* Create L2CAP header */
1260 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1261 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1262 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1263 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1264
1265 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1266 if (unlikely(err < 0)) {
1267 kfree_skb(skb);
1268 return ERR_PTR(err);
1269 }
1270 return skb;
1271}
1272
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001273struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001274{
1275 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1276 struct sk_buff *skb;
1277 int err, count, hlen = L2CAP_HDR_SIZE;
1278 struct l2cap_hdr *lh;
1279
1280 BT_DBG("sk %p len %d", sk, (int)len);
1281
1282 count = min_t(unsigned int, (conn->mtu - hlen), len);
1283 skb = bt_skb_send_alloc(sk, count + hlen,
1284 msg->msg_flags & MSG_DONTWAIT, &err);
1285 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001286 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001287
1288 /* Create L2CAP header */
1289 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1290 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1291 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1292
1293 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1294 if (unlikely(err < 0)) {
1295 kfree_skb(skb);
1296 return ERR_PTR(err);
1297 }
1298 return skb;
1299}
1300
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001301struct 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 -03001302{
1303 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1304 struct sk_buff *skb;
1305 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1306 struct l2cap_hdr *lh;
1307
1308 BT_DBG("sk %p len %d", sk, (int)len);
1309
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001310 if (!conn)
1311 return ERR_PTR(-ENOTCONN);
1312
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001313 if (sdulen)
1314 hlen += 2;
1315
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001316 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1317 hlen += 2;
1318
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001319 count = min_t(unsigned int, (conn->mtu - hlen), len);
1320 skb = bt_skb_send_alloc(sk, count + hlen,
1321 msg->msg_flags & MSG_DONTWAIT, &err);
1322 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001323 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001324
1325 /* Create L2CAP header */
1326 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1327 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1328 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1329 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001330 if (sdulen)
1331 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001332
1333 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1334 if (unlikely(err < 0)) {
1335 kfree_skb(skb);
1336 return ERR_PTR(err);
1337 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001338
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001339 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1340 put_unaligned_le16(0, skb_put(skb, 2));
1341
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001342 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001343 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344}
1345
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001346int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001347{
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001348 struct sock *sk = chan->sk;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001349 struct sk_buff *skb;
1350 struct sk_buff_head sar_queue;
1351 u16 control;
1352 size_t size = 0;
1353
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001354 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001355 control = L2CAP_SDU_START;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001356 skb = l2cap_create_iframe_pdu(sk, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001357 if (IS_ERR(skb))
1358 return PTR_ERR(skb);
1359
1360 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001361 len -= chan->remote_mps;
1362 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001363
1364 while (len > 0) {
1365 size_t buflen;
1366
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001367 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001368 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001369 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001370 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001371 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001372 buflen = len;
1373 }
1374
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001375 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001376 if (IS_ERR(skb)) {
1377 skb_queue_purge(&sar_queue);
1378 return PTR_ERR(skb);
1379 }
1380
1381 __skb_queue_tail(&sar_queue, skb);
1382 len -= buflen;
1383 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001384 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001385 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1386 if (chan->tx_send_head == NULL)
1387 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001388
1389 return size;
1390}
1391
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392static void l2cap_chan_ready(struct sock *sk)
1393{
1394 struct sock *parent = bt_sk(sk)->parent;
1395
1396 BT_DBG("sk %p, parent %p", sk, parent);
1397
1398 l2cap_pi(sk)->conf_state = 0;
1399 l2cap_sock_clear_timer(sk);
1400
1401 if (!parent) {
1402 /* Outgoing channel.
1403 * Wake up socket sleeping on connect.
1404 */
1405 sk->sk_state = BT_CONNECTED;
1406 sk->sk_state_change(sk);
1407 } else {
1408 /* Incoming channel.
1409 * Wake up socket sleeping on accept.
1410 */
1411 parent->sk_data_ready(parent, 0);
1412 }
1413}
1414
1415/* Copy frame to all raw sockets on that connection */
1416static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1417{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001419 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420
1421 BT_DBG("conn %p", conn);
1422
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001423 read_lock(&conn->chan_lock);
1424 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001425 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 if (sk->sk_type != SOCK_RAW)
1427 continue;
1428
1429 /* Don't send frame to the socket it came from */
1430 if (skb->sk == sk)
1431 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001432 nskb = skb_clone(skb, GFP_ATOMIC);
1433 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 continue;
1435
1436 if (sock_queue_rcv_skb(sk, nskb))
1437 kfree_skb(nskb);
1438 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001439 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440}
1441
1442/* ---- L2CAP signalling commands ---- */
1443static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1444 u8 code, u8 ident, u16 dlen, void *data)
1445{
1446 struct sk_buff *skb, **frag;
1447 struct l2cap_cmd_hdr *cmd;
1448 struct l2cap_hdr *lh;
1449 int len, count;
1450
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001451 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1452 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
1454 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1455 count = min_t(unsigned int, conn->mtu, len);
1456
1457 skb = bt_skb_alloc(count, GFP_ATOMIC);
1458 if (!skb)
1459 return NULL;
1460
1461 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001462 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001463
1464 if (conn->hcon->type == LE_LINK)
1465 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1466 else
1467 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
1469 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1470 cmd->code = code;
1471 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001472 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473
1474 if (dlen) {
1475 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1476 memcpy(skb_put(skb, count), data, count);
1477 data += count;
1478 }
1479
1480 len -= skb->len;
1481
1482 /* Continuation fragments (no L2CAP header) */
1483 frag = &skb_shinfo(skb)->frag_list;
1484 while (len) {
1485 count = min_t(unsigned int, conn->mtu, len);
1486
1487 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1488 if (!*frag)
1489 goto fail;
1490
1491 memcpy(skb_put(*frag, count), data, count);
1492
1493 len -= count;
1494 data += count;
1495
1496 frag = &(*frag)->next;
1497 }
1498
1499 return skb;
1500
1501fail:
1502 kfree_skb(skb);
1503 return NULL;
1504}
1505
1506static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1507{
1508 struct l2cap_conf_opt *opt = *ptr;
1509 int len;
1510
1511 len = L2CAP_CONF_OPT_SIZE + opt->len;
1512 *ptr += len;
1513
1514 *type = opt->type;
1515 *olen = opt->len;
1516
1517 switch (opt->len) {
1518 case 1:
1519 *val = *((u8 *) opt->val);
1520 break;
1521
1522 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001523 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 break;
1525
1526 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001527 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 break;
1529
1530 default:
1531 *val = (unsigned long) opt->val;
1532 break;
1533 }
1534
1535 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1536 return len;
1537}
1538
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1540{
1541 struct l2cap_conf_opt *opt = *ptr;
1542
1543 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1544
1545 opt->type = type;
1546 opt->len = len;
1547
1548 switch (len) {
1549 case 1:
1550 *((u8 *) opt->val) = val;
1551 break;
1552
1553 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001554 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 break;
1556
1557 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001558 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 break;
1560
1561 default:
1562 memcpy(opt->val, (void *) val, len);
1563 break;
1564 }
1565
1566 *ptr += L2CAP_CONF_OPT_SIZE + len;
1567}
1568
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001569static void l2cap_ack_timeout(unsigned long arg)
1570{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001571 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001572
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001573 bh_lock_sock(chan->sk);
1574 l2cap_send_ack(chan);
1575 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001576}
1577
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001578static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001579{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001580 struct sock *sk = chan->sk;
1581
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001582 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001583 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001584 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001585 chan->num_acked = 0;
1586 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001587
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001588 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1589 (unsigned long) chan);
1590 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1591 (unsigned long) chan);
1592 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001593
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001594 skb_queue_head_init(&chan->srej_q);
1595 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001596
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001597 INIT_LIST_HEAD(&chan->srej_l);
1598
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001599 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001600
1601 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001602}
1603
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001604static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1605{
1606 switch (mode) {
1607 case L2CAP_MODE_STREAMING:
1608 case L2CAP_MODE_ERTM:
1609 if (l2cap_mode_supported(mode, remote_feat_mask))
1610 return mode;
1611 /* fall through */
1612 default:
1613 return L2CAP_MODE_BASIC;
1614 }
1615}
1616
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001617static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001619 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001621 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 void *ptr = req->data;
1623
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001624 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001626 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001627 goto done;
1628
1629 switch (pi->mode) {
1630 case L2CAP_MODE_STREAMING:
1631 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001632 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001633 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001634
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001635 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001636 default:
1637 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1638 break;
1639 }
1640
1641done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001642 if (pi->imtu != L2CAP_DEFAULT_MTU)
1643 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1644
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001645 switch (pi->mode) {
1646 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001647 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1648 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1649 break;
1650
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001651 rfc.mode = L2CAP_MODE_BASIC;
1652 rfc.txwin_size = 0;
1653 rfc.max_transmit = 0;
1654 rfc.retrans_timeout = 0;
1655 rfc.monitor_timeout = 0;
1656 rfc.max_pdu_size = 0;
1657
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001658 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1659 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001660 break;
1661
1662 case L2CAP_MODE_ERTM:
1663 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001664 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001665 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001666 rfc.retrans_timeout = 0;
1667 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001668 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001669 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001670 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001671
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001672 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1673 (unsigned long) &rfc);
1674
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001675 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1676 break;
1677
1678 if (pi->fcs == L2CAP_FCS_NONE ||
1679 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1680 pi->fcs = L2CAP_FCS_NONE;
1681 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1682 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001683 break;
1684
1685 case L2CAP_MODE_STREAMING:
1686 rfc.mode = L2CAP_MODE_STREAMING;
1687 rfc.txwin_size = 0;
1688 rfc.max_transmit = 0;
1689 rfc.retrans_timeout = 0;
1690 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001691 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001692 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001693 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001694
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001695 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1696 (unsigned long) &rfc);
1697
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001698 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1699 break;
1700
1701 if (pi->fcs == L2CAP_FCS_NONE ||
1702 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1703 pi->fcs = L2CAP_FCS_NONE;
1704 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1705 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001706 break;
1707 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001709 req->dcid = cpu_to_le16(pi->dcid);
1710 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711
1712 return ptr - data;
1713}
1714
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001715static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001717 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001718 struct l2cap_conf_rsp *rsp = data;
1719 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001720 void *req = chan->conf_req;
1721 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001722 int type, hint, olen;
1723 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001724 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001725 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001726 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001728 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001729
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001730 while (len >= L2CAP_CONF_OPT_SIZE) {
1731 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001733 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001734 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001735
1736 switch (type) {
1737 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001738 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001739 break;
1740
1741 case L2CAP_CONF_FLUSH_TO:
1742 pi->flush_to = val;
1743 break;
1744
1745 case L2CAP_CONF_QOS:
1746 break;
1747
Marcel Holtmann6464f352007-10-20 13:39:51 +02001748 case L2CAP_CONF_RFC:
1749 if (olen == sizeof(rfc))
1750 memcpy(&rfc, (void *) val, olen);
1751 break;
1752
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001753 case L2CAP_CONF_FCS:
1754 if (val == L2CAP_FCS_NONE)
1755 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1756
1757 break;
1758
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001759 default:
1760 if (hint)
1761 break;
1762
1763 result = L2CAP_CONF_UNKNOWN;
1764 *((u8 *) ptr++) = type;
1765 break;
1766 }
1767 }
1768
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001769 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001770 goto done;
1771
1772 switch (pi->mode) {
1773 case L2CAP_MODE_STREAMING:
1774 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001775 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1776 pi->mode = l2cap_select_mode(rfc.mode,
1777 pi->conn->feat_mask);
1778 break;
1779 }
1780
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001781 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001782 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001783
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001784 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001785 }
1786
1787done:
1788 if (pi->mode != rfc.mode) {
1789 result = L2CAP_CONF_UNACCEPT;
1790 rfc.mode = pi->mode;
1791
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001792 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001793 return -ECONNREFUSED;
1794
1795 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1796 sizeof(rfc), (unsigned long) &rfc);
1797 }
1798
1799
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001800 if (result == L2CAP_CONF_SUCCESS) {
1801 /* Configure output options and let the other side know
1802 * which ones we don't like. */
1803
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001804 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1805 result = L2CAP_CONF_UNACCEPT;
1806 else {
1807 pi->omtu = mtu;
1808 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1809 }
1810 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001811
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001812 switch (rfc.mode) {
1813 case L2CAP_MODE_BASIC:
1814 pi->fcs = L2CAP_FCS_NONE;
1815 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1816 break;
1817
1818 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001819 chan->remote_tx_win = rfc.txwin_size;
1820 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001821
1822 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1823 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001824
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001825 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001826
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001827 rfc.retrans_timeout =
1828 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1829 rfc.monitor_timeout =
1830 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001831
1832 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001833
1834 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1835 sizeof(rfc), (unsigned long) &rfc);
1836
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001837 break;
1838
1839 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001840 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1841 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001842
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001843 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001844
1845 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001846
1847 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1848 sizeof(rfc), (unsigned long) &rfc);
1849
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001850 break;
1851
1852 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001853 result = L2CAP_CONF_UNACCEPT;
1854
1855 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001856 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001857 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001858
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001859 if (result == L2CAP_CONF_SUCCESS)
1860 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1861 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001862 rsp->scid = cpu_to_le16(pi->dcid);
1863 rsp->result = cpu_to_le16(result);
1864 rsp->flags = cpu_to_le16(0x0000);
1865
1866 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867}
1868
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001869static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1870{
1871 struct l2cap_pinfo *pi = l2cap_pi(sk);
1872 struct l2cap_conf_req *req = data;
1873 void *ptr = req->data;
1874 int type, olen;
1875 unsigned long val;
1876 struct l2cap_conf_rfc rfc;
1877
1878 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1879
1880 while (len >= L2CAP_CONF_OPT_SIZE) {
1881 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1882
1883 switch (type) {
1884 case L2CAP_CONF_MTU:
1885 if (val < L2CAP_DEFAULT_MIN_MTU) {
1886 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001887 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001888 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001889 pi->imtu = val;
1890 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001891 break;
1892
1893 case L2CAP_CONF_FLUSH_TO:
1894 pi->flush_to = val;
1895 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1896 2, pi->flush_to);
1897 break;
1898
1899 case L2CAP_CONF_RFC:
1900 if (olen == sizeof(rfc))
1901 memcpy(&rfc, (void *)val, olen);
1902
1903 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1904 rfc.mode != pi->mode)
1905 return -ECONNREFUSED;
1906
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001907 pi->fcs = 0;
1908
1909 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1910 sizeof(rfc), (unsigned long) &rfc);
1911 break;
1912 }
1913 }
1914
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001915 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1916 return -ECONNREFUSED;
1917
1918 pi->mode = rfc.mode;
1919
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001920 if (*result == L2CAP_CONF_SUCCESS) {
1921 switch (rfc.mode) {
1922 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001923 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1924 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001925 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001926 break;
1927 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001928 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001929 }
1930 }
1931
1932 req->dcid = cpu_to_le16(pi->dcid);
1933 req->flags = cpu_to_le16(0x0000);
1934
1935 return ptr - data;
1936}
1937
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001938static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939{
1940 struct l2cap_conf_rsp *rsp = data;
1941 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001943 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001945 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001946 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001947 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948
1949 return ptr - data;
1950}
1951
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001952void __l2cap_connect_rsp_defer(struct sock *sk)
1953{
1954 struct l2cap_conn_rsp rsp;
1955 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1956 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
1957 u8 buf[128];
1958
1959 sk->sk_state = BT_CONFIG;
1960
1961 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1962 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1963 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1964 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1965 l2cap_send_cmd(conn, chan->ident,
1966 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1967
1968 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
1969 return;
1970
1971 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
1972 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1973 l2cap_build_conf_req(chan, buf), buf);
1974 chan->num_conf_req++;
1975}
1976
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001977static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1978{
1979 struct l2cap_pinfo *pi = l2cap_pi(sk);
1980 int type, olen;
1981 unsigned long val;
1982 struct l2cap_conf_rfc rfc;
1983
1984 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1985
1986 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1987 return;
1988
1989 while (len >= L2CAP_CONF_OPT_SIZE) {
1990 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1991
1992 switch (type) {
1993 case L2CAP_CONF_RFC:
1994 if (olen == sizeof(rfc))
1995 memcpy(&rfc, (void *)val, olen);
1996 goto done;
1997 }
1998 }
1999
2000done:
2001 switch (rfc.mode) {
2002 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002003 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2004 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002005 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2006 break;
2007 case L2CAP_MODE_STREAMING:
2008 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2009 }
2010}
2011
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002012static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2013{
2014 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2015
2016 if (rej->reason != 0x0000)
2017 return 0;
2018
2019 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2020 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002021 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002022
2023 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002024 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002025
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002026 l2cap_conn_start(conn);
2027 }
2028
2029 return 0;
2030}
2031
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2033{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2035 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002036 struct l2cap_chan *chan = NULL;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002037 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002038 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039
2040 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002041 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042
2043 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2044
2045 /* Check if we have socket listening on psm */
2046 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2047 if (!parent) {
2048 result = L2CAP_CR_BAD_PSM;
2049 goto sendresp;
2050 }
2051
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002052 bh_lock_sock(parent);
2053
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002054 /* Check if the ACL is secure enough (if not SDP) */
2055 if (psm != cpu_to_le16(0x0001) &&
2056 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002057 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002058 result = L2CAP_CR_SEC_BLOCK;
2059 goto response;
2060 }
2061
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 result = L2CAP_CR_NO_MEM;
2063
2064 /* Check for backlog size */
2065 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002066 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 goto response;
2068 }
2069
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002070 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 if (!sk)
2072 goto response;
2073
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002074 chan = l2cap_chan_alloc(sk);
2075 if (!chan) {
2076 l2cap_sock_kill(sk);
2077 goto response;
2078 }
2079
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002080 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081
2082 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002083 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2084 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085 sock_set_flag(sk, SOCK_ZAPPED);
2086 l2cap_sock_kill(sk);
2087 goto response;
2088 }
2089
2090 hci_conn_hold(conn->hcon);
2091
2092 l2cap_sock_init(sk, parent);
2093 bacpy(&bt_sk(sk)->src, conn->src);
2094 bacpy(&bt_sk(sk)->dst, conn->dst);
2095 l2cap_pi(sk)->psm = psm;
2096 l2cap_pi(sk)->dcid = scid;
2097
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002098 bt_accept_enqueue(parent, sk);
2099
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002100 __l2cap_chan_add(conn, chan);
2101
2102 l2cap_pi(sk)->chan = chan;
2103
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 dcid = l2cap_pi(sk)->scid;
2105
2106 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2107
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002108 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109
Marcel Holtmann984947d2009-02-06 23:35:19 +01002110 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002111 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002112 if (bt_sk(sk)->defer_setup) {
2113 sk->sk_state = BT_CONNECT2;
2114 result = L2CAP_CR_PEND;
2115 status = L2CAP_CS_AUTHOR_PEND;
2116 parent->sk_data_ready(parent, 0);
2117 } else {
2118 sk->sk_state = BT_CONFIG;
2119 result = L2CAP_CR_SUCCESS;
2120 status = L2CAP_CS_NO_INFO;
2121 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002122 } else {
2123 sk->sk_state = BT_CONNECT2;
2124 result = L2CAP_CR_PEND;
2125 status = L2CAP_CS_AUTHEN_PEND;
2126 }
2127 } else {
2128 sk->sk_state = BT_CONNECT2;
2129 result = L2CAP_CR_PEND;
2130 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 }
2132
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002133 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134
2135response:
2136 bh_unlock_sock(parent);
2137
2138sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002139 rsp.scid = cpu_to_le16(scid);
2140 rsp.dcid = cpu_to_le16(dcid);
2141 rsp.result = cpu_to_le16(result);
2142 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002144
2145 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2146 struct l2cap_info_req info;
2147 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2148
2149 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2150 conn->info_ident = l2cap_get_ident(conn);
2151
2152 mod_timer(&conn->info_timer, jiffies +
2153 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2154
2155 l2cap_send_cmd(conn, conn->info_ident,
2156 L2CAP_INFO_REQ, sizeof(info), &info);
2157 }
2158
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002159 if (chan && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002160 result == L2CAP_CR_SUCCESS) {
2161 u8 buf[128];
2162 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2163 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002164 l2cap_build_conf_req(chan, buf), buf);
2165 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002166 }
2167
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 return 0;
2169}
2170
2171static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2172{
2173 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2174 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002175 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 struct sock *sk;
2177 u8 req[128];
2178
2179 scid = __le16_to_cpu(rsp->scid);
2180 dcid = __le16_to_cpu(rsp->dcid);
2181 result = __le16_to_cpu(rsp->result);
2182 status = __le16_to_cpu(rsp->status);
2183
2184 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2185
2186 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002187 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002188 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002189 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002191 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002192 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002193 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 }
2195
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002196 sk = chan->sk;
2197
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 switch (result) {
2199 case L2CAP_CR_SUCCESS:
2200 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002201 chan->ident = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002203 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2204
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002205 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2206 break;
2207
2208 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2209
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002211 l2cap_build_conf_req(chan, req), req);
2212 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 break;
2214
2215 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002216 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 break;
2218
2219 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002220 /* don't delete l2cap channel if sk is owned by user */
2221 if (sock_owned_by_user(sk)) {
2222 sk->sk_state = BT_DISCONN;
2223 l2cap_sock_clear_timer(sk);
2224 l2cap_sock_set_timer(sk, HZ / 5);
2225 break;
2226 }
2227
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002228 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 break;
2230 }
2231
2232 bh_unlock_sock(sk);
2233 return 0;
2234}
2235
Mat Martineau8c462b62010-08-24 15:35:42 -07002236static inline void set_default_fcs(struct l2cap_pinfo *pi)
2237{
2238 /* FCS is enabled only in ERTM or streaming mode, if one or both
2239 * sides request it.
2240 */
2241 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2242 pi->fcs = L2CAP_FCS_NONE;
2243 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2244 pi->fcs = L2CAP_FCS_CRC16;
2245}
2246
Al Viro88219a02007-07-29 00:17:25 -07002247static 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 -07002248{
2249 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2250 u16 dcid, flags;
2251 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002252 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002254 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255
2256 dcid = __le16_to_cpu(req->dcid);
2257 flags = __le16_to_cpu(req->flags);
2258
2259 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2260
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002261 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002262 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 return -ENOENT;
2264
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002265 sk = chan->sk;
2266
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002267 if (sk->sk_state != BT_CONFIG) {
2268 struct l2cap_cmd_rej rej;
2269
2270 rej.reason = cpu_to_le16(0x0002);
2271 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2272 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002273 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002274 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002275
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002276 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002277 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002278 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002279 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2280 l2cap_build_conf_rsp(sk, rsp,
2281 L2CAP_CONF_REJECT, flags), rsp);
2282 goto unlock;
2283 }
2284
2285 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002286 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2287 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288
2289 if (flags & 0x0001) {
2290 /* Incomplete config. Send empty response. */
2291 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002292 l2cap_build_conf_rsp(sk, rsp,
2293 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 goto unlock;
2295 }
2296
2297 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002298 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002299 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002300 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002302 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002304 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002305 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002306
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002307 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002308 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002309
Marcel Holtmann876d9482007-10-20 13:35:42 +02002310 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2311 goto unlock;
2312
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002314 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002315
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002317
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002318 chan->next_tx_seq = 0;
2319 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002320 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002321 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002322 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002323
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002325 goto unlock;
2326 }
2327
2328 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002329 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002330 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002332 l2cap_build_conf_req(chan, buf), buf);
2333 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 }
2335
2336unlock:
2337 bh_unlock_sock(sk);
2338 return 0;
2339}
2340
2341static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2342{
2343 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2344 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002345 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002347 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348
2349 scid = __le16_to_cpu(rsp->scid);
2350 flags = __le16_to_cpu(rsp->flags);
2351 result = __le16_to_cpu(rsp->result);
2352
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002353 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2354 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002356 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002357 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 return 0;
2359
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002360 sk = chan->sk;
2361
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362 switch (result) {
2363 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002364 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 break;
2366
2367 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002368 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002369 char req[64];
2370
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002371 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002372 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002373 goto done;
2374 }
2375
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002376 /* throw out any old stored conf requests */
2377 result = L2CAP_CONF_SUCCESS;
2378 len = l2cap_parse_conf_rsp(sk, rsp->data,
2379 len, req, &result);
2380 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002381 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002382 goto done;
2383 }
2384
2385 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2386 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002387 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002388 if (result != L2CAP_CONF_SUCCESS)
2389 goto done;
2390 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 }
2392
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002393 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002394 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002396 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397 goto done;
2398 }
2399
2400 if (flags & 0x01)
2401 goto done;
2402
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2404
2405 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002406 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002407
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002409 chan->next_tx_seq = 0;
2410 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002411 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002412 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002413 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002414
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415 l2cap_chan_ready(sk);
2416 }
2417
2418done:
2419 bh_unlock_sock(sk);
2420 return 0;
2421}
2422
2423static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2424{
2425 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2426 struct l2cap_disconn_rsp rsp;
2427 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002428 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 struct sock *sk;
2430
2431 scid = __le16_to_cpu(req->scid);
2432 dcid = __le16_to_cpu(req->dcid);
2433
2434 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2435
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002436 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002437 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438 return 0;
2439
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002440 sk = chan->sk;
2441
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002442 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2443 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2445
2446 sk->sk_shutdown = SHUTDOWN_MASK;
2447
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002448 /* don't delete l2cap channel if sk is owned by user */
2449 if (sock_owned_by_user(sk)) {
2450 sk->sk_state = BT_DISCONN;
2451 l2cap_sock_clear_timer(sk);
2452 l2cap_sock_set_timer(sk, HZ / 5);
2453 bh_unlock_sock(sk);
2454 return 0;
2455 }
2456
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002457 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 bh_unlock_sock(sk);
2459
2460 l2cap_sock_kill(sk);
2461 return 0;
2462}
2463
2464static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2465{
2466 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2467 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002468 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 struct sock *sk;
2470
2471 scid = __le16_to_cpu(rsp->scid);
2472 dcid = __le16_to_cpu(rsp->dcid);
2473
2474 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2475
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002476 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002477 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 return 0;
2479
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002480 sk = chan->sk;
2481
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002482 /* don't delete l2cap channel if sk is owned by user */
2483 if (sock_owned_by_user(sk)) {
2484 sk->sk_state = BT_DISCONN;
2485 l2cap_sock_clear_timer(sk);
2486 l2cap_sock_set_timer(sk, HZ / 5);
2487 bh_unlock_sock(sk);
2488 return 0;
2489 }
2490
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002491 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492 bh_unlock_sock(sk);
2493
2494 l2cap_sock_kill(sk);
2495 return 0;
2496}
2497
2498static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2499{
2500 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501 u16 type;
2502
2503 type = __le16_to_cpu(req->type);
2504
2505 BT_DBG("type 0x%4.4x", type);
2506
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002507 if (type == L2CAP_IT_FEAT_MASK) {
2508 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002509 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002510 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2511 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2512 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002513 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002514 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2515 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002516 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002517 l2cap_send_cmd(conn, cmd->ident,
2518 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002519 } else if (type == L2CAP_IT_FIXED_CHAN) {
2520 u8 buf[12];
2521 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2522 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2523 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2524 memcpy(buf + 4, l2cap_fixed_chan, 8);
2525 l2cap_send_cmd(conn, cmd->ident,
2526 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002527 } else {
2528 struct l2cap_info_rsp rsp;
2529 rsp.type = cpu_to_le16(type);
2530 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2531 l2cap_send_cmd(conn, cmd->ident,
2532 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2533 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002534
2535 return 0;
2536}
2537
2538static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2539{
2540 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2541 u16 type, result;
2542
2543 type = __le16_to_cpu(rsp->type);
2544 result = __le16_to_cpu(rsp->result);
2545
2546 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2547
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002548 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2549 if (cmd->ident != conn->info_ident ||
2550 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2551 return 0;
2552
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002553 del_timer(&conn->info_timer);
2554
Ville Tervoadb08ed2010-08-04 09:43:33 +03002555 if (result != L2CAP_IR_SUCCESS) {
2556 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2557 conn->info_ident = 0;
2558
2559 l2cap_conn_start(conn);
2560
2561 return 0;
2562 }
2563
Marcel Holtmann984947d2009-02-06 23:35:19 +01002564 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002565 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002566
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002567 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002568 struct l2cap_info_req req;
2569 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2570
2571 conn->info_ident = l2cap_get_ident(conn);
2572
2573 l2cap_send_cmd(conn, conn->info_ident,
2574 L2CAP_INFO_REQ, sizeof(req), &req);
2575 } else {
2576 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2577 conn->info_ident = 0;
2578
2579 l2cap_conn_start(conn);
2580 }
2581 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002582 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002583 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002584
2585 l2cap_conn_start(conn);
2586 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002587
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588 return 0;
2589}
2590
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002591static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002592 u16 to_multiplier)
2593{
2594 u16 max_latency;
2595
2596 if (min > max || min < 6 || max > 3200)
2597 return -EINVAL;
2598
2599 if (to_multiplier < 10 || to_multiplier > 3200)
2600 return -EINVAL;
2601
2602 if (max >= to_multiplier * 8)
2603 return -EINVAL;
2604
2605 max_latency = (to_multiplier * 8 / max) - 1;
2606 if (latency > 499 || latency > max_latency)
2607 return -EINVAL;
2608
2609 return 0;
2610}
2611
2612static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2613 struct l2cap_cmd_hdr *cmd, u8 *data)
2614{
2615 struct hci_conn *hcon = conn->hcon;
2616 struct l2cap_conn_param_update_req *req;
2617 struct l2cap_conn_param_update_rsp rsp;
2618 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002619 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002620
2621 if (!(hcon->link_mode & HCI_LM_MASTER))
2622 return -EINVAL;
2623
2624 cmd_len = __le16_to_cpu(cmd->len);
2625 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2626 return -EPROTO;
2627
2628 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002629 min = __le16_to_cpu(req->min);
2630 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002631 latency = __le16_to_cpu(req->latency);
2632 to_multiplier = __le16_to_cpu(req->to_multiplier);
2633
2634 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2635 min, max, latency, to_multiplier);
2636
2637 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002638
2639 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2640 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002641 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2642 else
2643 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2644
2645 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2646 sizeof(rsp), &rsp);
2647
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002648 if (!err)
2649 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2650
Claudio Takahaside731152011-02-11 19:28:55 -02002651 return 0;
2652}
2653
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002654static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2655 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2656{
2657 int err = 0;
2658
2659 switch (cmd->code) {
2660 case L2CAP_COMMAND_REJ:
2661 l2cap_command_rej(conn, cmd, data);
2662 break;
2663
2664 case L2CAP_CONN_REQ:
2665 err = l2cap_connect_req(conn, cmd, data);
2666 break;
2667
2668 case L2CAP_CONN_RSP:
2669 err = l2cap_connect_rsp(conn, cmd, data);
2670 break;
2671
2672 case L2CAP_CONF_REQ:
2673 err = l2cap_config_req(conn, cmd, cmd_len, data);
2674 break;
2675
2676 case L2CAP_CONF_RSP:
2677 err = l2cap_config_rsp(conn, cmd, data);
2678 break;
2679
2680 case L2CAP_DISCONN_REQ:
2681 err = l2cap_disconnect_req(conn, cmd, data);
2682 break;
2683
2684 case L2CAP_DISCONN_RSP:
2685 err = l2cap_disconnect_rsp(conn, cmd, data);
2686 break;
2687
2688 case L2CAP_ECHO_REQ:
2689 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2690 break;
2691
2692 case L2CAP_ECHO_RSP:
2693 break;
2694
2695 case L2CAP_INFO_REQ:
2696 err = l2cap_information_req(conn, cmd, data);
2697 break;
2698
2699 case L2CAP_INFO_RSP:
2700 err = l2cap_information_rsp(conn, cmd, data);
2701 break;
2702
2703 default:
2704 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2705 err = -EINVAL;
2706 break;
2707 }
2708
2709 return err;
2710}
2711
2712static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2713 struct l2cap_cmd_hdr *cmd, u8 *data)
2714{
2715 switch (cmd->code) {
2716 case L2CAP_COMMAND_REJ:
2717 return 0;
2718
2719 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002720 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002721
2722 case L2CAP_CONN_PARAM_UPDATE_RSP:
2723 return 0;
2724
2725 default:
2726 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2727 return -EINVAL;
2728 }
2729}
2730
2731static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2732 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733{
2734 u8 *data = skb->data;
2735 int len = skb->len;
2736 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002737 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738
2739 l2cap_raw_recv(conn, skb);
2740
2741 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002742 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2744 data += L2CAP_CMD_HDR_SIZE;
2745 len -= L2CAP_CMD_HDR_SIZE;
2746
Al Viro88219a02007-07-29 00:17:25 -07002747 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748
Al Viro88219a02007-07-29 00:17:25 -07002749 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 -07002750
Al Viro88219a02007-07-29 00:17:25 -07002751 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752 BT_DBG("corrupted command");
2753 break;
2754 }
2755
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002756 if (conn->hcon->type == LE_LINK)
2757 err = l2cap_le_sig_cmd(conn, &cmd, data);
2758 else
2759 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760
2761 if (err) {
2762 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002763
2764 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765
2766 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002767 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2769 }
2770
Al Viro88219a02007-07-29 00:17:25 -07002771 data += cmd_len;
2772 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773 }
2774
2775 kfree_skb(skb);
2776}
2777
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002778static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2779{
2780 u16 our_fcs, rcv_fcs;
2781 int hdr_size = L2CAP_HDR_SIZE + 2;
2782
2783 if (pi->fcs == L2CAP_FCS_CRC16) {
2784 skb_trim(skb, skb->len - 2);
2785 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2786 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2787
2788 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002789 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002790 }
2791 return 0;
2792}
2793
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002794static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002795{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002796 u16 control = 0;
2797
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002798 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002799
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002800 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002801
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002802 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002803 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002804 l2cap_send_sframe(chan, control);
2805 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002806 }
2807
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002808 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2809 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002810
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002811 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002812
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002813 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002814 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002815 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002816 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002817 }
2818}
2819
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002820static 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 -03002821{
2822 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002823 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002824
2825 bt_cb(skb)->tx_seq = tx_seq;
2826 bt_cb(skb)->sar = sar;
2827
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002828 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002829 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002830 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002831 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002832 }
2833
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002834 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002835 if (tx_seq_offset < 0)
2836 tx_seq_offset += 64;
2837
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002838 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002839 if (bt_cb(next_skb)->tx_seq == tx_seq)
2840 return -EINVAL;
2841
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002842 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002843 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002844 if (next_tx_seq_offset < 0)
2845 next_tx_seq_offset += 64;
2846
2847 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002848 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002849 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002850 }
2851
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002852 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002853 break;
2854
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002855 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002856
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002857 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002858
2859 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002860}
2861
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002862static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002863{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002864 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002865 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002866 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002867
2868 switch (control & L2CAP_CTRL_SAR) {
2869 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002870 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002871 goto drop;
2872
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002873 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002874 if (!err)
2875 return err;
2876
2877 break;
2878
2879 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002880 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002881 goto drop;
2882
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002883 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002884
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002885 if (chan->sdu_len > pi->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002886 goto disconnect;
2887
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002888 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
2889 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002890 return -ENOMEM;
2891
2892 /* pull sdu_len bytes only after alloc, because of Local Busy
2893 * condition we have to be sure that this will be executed
2894 * only once, i.e., when alloc does not fail */
2895 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002896
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002897 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002898
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002899 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002900 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002901 break;
2902
2903 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002904 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002905 goto disconnect;
2906
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002907 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002908 goto disconnect;
2909
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002910 chan->partial_sdu_len += skb->len;
2911 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002912 goto drop;
2913
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002914 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002915
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002916 break;
2917
2918 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002919 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002920 goto disconnect;
2921
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002922 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002923 goto disconnect;
2924
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002925 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002926 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002927
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002928 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002929 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002930
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002931 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002932 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002933
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002934 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002935 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002936
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002937 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002938 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002939 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002940 return -ENOMEM;
2941 }
2942
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002943 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002944 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002945 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002946 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002947 return err;
2948 }
2949
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002950 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2951 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002952
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002953 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002954 break;
2955 }
2956
2957 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002958 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002959
2960drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002961 kfree_skb(chan->sdu);
2962 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002963
2964disconnect:
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002965 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002966 kfree_skb(skb);
2967 return 0;
2968}
2969
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002970static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002971{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002972 struct sk_buff *skb;
2973 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002974 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002975
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002976 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002977 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002978 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002979 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002980 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002981 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002982 }
2983
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002984 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002985 }
2986
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002987 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002988 goto done;
2989
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002990 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002991 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002992 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002993 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002994
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002995 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002996 __mod_monitor_timer();
2997
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002998 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002999
3000done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003001 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3002 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003003
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003004 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003005
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003006 return 0;
3007}
3008
3009static void l2cap_busy_work(struct work_struct *work)
3010{
3011 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003012 struct l2cap_chan *chan =
3013 container_of(work, struct l2cap_chan, busy_work);
3014 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003015 int n_tries = 0, timeo = HZ/5, err;
3016 struct sk_buff *skb;
3017
3018 lock_sock(sk);
3019
3020 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003021 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003022 set_current_state(TASK_INTERRUPTIBLE);
3023
3024 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3025 err = -EBUSY;
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003026 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003027 break;
3028 }
3029
3030 if (!timeo)
3031 timeo = HZ/5;
3032
3033 if (signal_pending(current)) {
3034 err = sock_intr_errno(timeo);
3035 break;
3036 }
3037
3038 release_sock(sk);
3039 timeo = schedule_timeout(timeo);
3040 lock_sock(sk);
3041
3042 err = sock_error(sk);
3043 if (err)
3044 break;
3045
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003046 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003047 break;
3048 }
3049
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003050 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003051 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003052
3053 release_sock(sk);
3054}
3055
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003056static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003057{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003058 int sctrl, err;
3059
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003060 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003061 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003062 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003063 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003064
3065
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003066 }
3067
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003068 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003069 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003070 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003071 return err;
3072 }
3073
3074 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003075 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003076
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003077 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003078 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003079 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003080
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003081 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003082 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003083 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003084
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003085 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003086
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003087 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003088
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003089 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003090
3091 return err;
3092}
3093
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003094static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003095{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003096 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003097 struct sk_buff *_skb;
3098 int err = -EINVAL;
3099
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003100 /*
3101 * TODO: We have to notify the userland if some data is lost with the
3102 * Streaming Mode.
3103 */
3104
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003105 switch (control & L2CAP_CTRL_SAR) {
3106 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003107 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003108 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003109 break;
3110 }
3111
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003112 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003113 if (!err)
3114 return 0;
3115
3116 break;
3117
3118 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003119 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003120 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003121 break;
3122 }
3123
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003124 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003125 skb_pull(skb, 2);
3126
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003127 if (chan->sdu_len > pi->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003128 err = -EMSGSIZE;
3129 break;
3130 }
3131
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003132 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3133 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003134 err = -ENOMEM;
3135 break;
3136 }
3137
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003138 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003139
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003140 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003141 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003142 err = 0;
3143 break;
3144
3145 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003146 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003147 break;
3148
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003149 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003150
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003151 chan->partial_sdu_len += skb->len;
3152 if (chan->partial_sdu_len > chan->sdu_len)
3153 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003154 else
3155 err = 0;
3156
3157 break;
3158
3159 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003160 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003161 break;
3162
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003163 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003164
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003165 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003166 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003167
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003168 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003169 goto drop;
3170
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003171 if (chan->partial_sdu_len == chan->sdu_len) {
3172 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003173 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003174 if (err < 0)
3175 kfree_skb(_skb);
3176 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003177 err = 0;
3178
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003179drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003180 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003181 break;
3182 }
3183
3184 kfree_skb(skb);
3185 return err;
3186}
3187
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003188static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003189{
3190 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003191 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003192
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003193 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003194 if (bt_cb(skb)->tx_seq != tx_seq)
3195 break;
3196
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003197 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003198 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003199 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003200 chan->buffer_seq_srej =
3201 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003202 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003203 }
3204}
3205
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003206static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003207{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003208 struct srej_list *l, *tmp;
3209 u16 control;
3210
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003211 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003212 if (l->tx_seq == tx_seq) {
3213 list_del(&l->list);
3214 kfree(l);
3215 return;
3216 }
3217 control = L2CAP_SUPER_SELECT_REJECT;
3218 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003219 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003220 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003221 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003222 }
3223}
3224
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003225static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003226{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003227 struct srej_list *new;
3228 u16 control;
3229
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003230 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003231 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003232 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003233 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003234
3235 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003236 new->tx_seq = chan->expected_tx_seq;
3237 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003238 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003239 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003240 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003241}
3242
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003243static 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 -03003244{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003245 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003246 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003247 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003248 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003249 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003250 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003251 int err = 0;
3252
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003253 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3254 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003255
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003256 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003257 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003258 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003259 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003260 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003261 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003262 }
3263
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003264 chan->expected_ack_seq = req_seq;
3265 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003266
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003267 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003268 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003269
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003270 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003271 if (tx_seq_offset < 0)
3272 tx_seq_offset += 64;
3273
3274 /* invalid tx_seq */
3275 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003276 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003277 goto drop;
3278 }
3279
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003280 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003281 goto drop;
3282
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003283 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003284 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003285
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003286 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003287 struct srej_list, list);
3288 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003289 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003290 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003291
3292 list_del(&first->list);
3293 kfree(first);
3294
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003295 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003296 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003297 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3298 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003299 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003300 }
3301 } else {
3302 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003303
3304 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003305 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003306 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003307
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003308 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003309 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003310 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003311 return 0;
3312 }
3313 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003314 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003315 }
3316 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003317 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003318 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003319 if (expected_tx_seq_offset < 0)
3320 expected_tx_seq_offset += 64;
3321
3322 /* duplicated tx_seq */
3323 if (tx_seq_offset < expected_tx_seq_offset)
3324 goto drop;
3325
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003326 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003327
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003328 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003329
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003330 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003331 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003332
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003333 __skb_queue_head_init(&chan->srej_q);
3334 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003335 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003336
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003337 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003338
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003339 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003340
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003341 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003342 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003343 return 0;
3344
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003345expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003346 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003347
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003348 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003349 bt_cb(skb)->tx_seq = tx_seq;
3350 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003351 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003352 return 0;
3353 }
3354
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003355 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003356 if (err < 0)
3357 return 0;
3358
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003359 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003360 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3361 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003362 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003363 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003364 }
3365
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003366 __mod_ack_timer();
3367
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003368 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3369 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003370 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003371
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003372 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003373
3374drop:
3375 kfree_skb(skb);
3376 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003377}
3378
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003379static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003380{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003381 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003382 rx_control);
3383
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003384 chan->expected_ack_seq = __get_reqseq(rx_control);
3385 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003386
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003387 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003388 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3389 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3390 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003391 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003392 __mod_retrans_timer();
3393
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003394 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3395 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003396 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003397 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003398 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003399
3400 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003401 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003402
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003403 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3404 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003405 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003406 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003407
3408 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003409 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003410 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003411 __mod_retrans_timer();
3412
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003413 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3414 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3415 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003416 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003417 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003418 }
3419}
3420
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003421static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003422{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003423 u8 tx_seq = __get_reqseq(rx_control);
3424
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003425 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003426
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003427 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003428
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003429 chan->expected_ack_seq = tx_seq;
3430 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003431
3432 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003433 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3434 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003435 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003436 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003437 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003438 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003439
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003440 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3441 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003442 }
3443}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003444static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003445{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003446 u8 tx_seq = __get_reqseq(rx_control);
3447
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003448 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003449
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003450 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003451
3452 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003453 chan->expected_ack_seq = tx_seq;
3454 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003455
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003456 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3457 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003458
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003459 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003460
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003461 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003462 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003463 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003464 }
3465 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003466 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003467 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003468 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
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);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003471 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003472 l2cap_retransmit_one_frame(chan, tx_seq);
3473 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003474 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003475 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003476 }
3477 }
3478}
3479
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003480static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003481{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003482 u8 tx_seq = __get_reqseq(rx_control);
3483
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003484 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003485
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003486 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003487 chan->expected_ack_seq = tx_seq;
3488 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003489
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003490 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003491 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003492
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003493 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003494 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003495 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003496 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003497 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003498 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003499
3500 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003501 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003502 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003503 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003504}
3505
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003506static 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 -03003507{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003508 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003509
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003510 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003511 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003512 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003513 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003514 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003515 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003516 }
3517
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003518 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3519 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003520 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003521 break;
3522
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003523 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003524 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003525 break;
3526
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003527 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003528 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003529 break;
3530
3531 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003532 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003533 break;
3534 }
3535
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003536 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003537 return 0;
3538}
3539
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003540static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3541{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003542 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003543 struct l2cap_pinfo *pi = l2cap_pi(sk);
3544 u16 control;
3545 u8 req_seq;
3546 int len, next_tx_seq_offset, req_seq_offset;
3547
3548 control = get_unaligned_le16(skb->data);
3549 skb_pull(skb, 2);
3550 len = skb->len;
3551
3552 /*
3553 * We can just drop the corrupted I-frame here.
3554 * Receiver will miss it and start proper recovery
3555 * procedures and ask retransmission.
3556 */
3557 if (l2cap_check_fcs(pi, skb))
3558 goto drop;
3559
3560 if (__is_sar_start(control) && __is_iframe(control))
3561 len -= 2;
3562
3563 if (pi->fcs == L2CAP_FCS_CRC16)
3564 len -= 2;
3565
3566 if (len > pi->mps) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003567 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003568 goto drop;
3569 }
3570
3571 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003572 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003573 if (req_seq_offset < 0)
3574 req_seq_offset += 64;
3575
3576 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003577 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003578 if (next_tx_seq_offset < 0)
3579 next_tx_seq_offset += 64;
3580
3581 /* check for invalid req-seq */
3582 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003583 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003584 goto drop;
3585 }
3586
3587 if (__is_iframe(control)) {
3588 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003589 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003590 goto drop;
3591 }
3592
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003593 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003594 } else {
3595 if (len != 0) {
3596 BT_ERR("%d", len);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003597 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003598 goto drop;
3599 }
3600
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003601 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003602 }
3603
3604 return 0;
3605
3606drop:
3607 kfree_skb(skb);
3608 return 0;
3609}
3610
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3612{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003613 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003615 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003616 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003617 u8 tx_seq;
3618 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003620 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003621 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622 BT_DBG("unknown cid 0x%4.4x", cid);
3623 goto drop;
3624 }
3625
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003626 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003627 pi = l2cap_pi(sk);
3628
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003629 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630
3631 if (sk->sk_state != BT_CONNECTED)
3632 goto drop;
3633
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003634 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003635 case L2CAP_MODE_BASIC:
3636 /* If socket recv buffers overflows we drop data here
3637 * which is *bad* because L2CAP has to be reliable.
3638 * But we don't have any other choice. L2CAP doesn't
3639 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003640
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003641 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003642 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003644 if (!sock_queue_rcv_skb(sk, skb))
3645 goto done;
3646 break;
3647
3648 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003649 if (!sock_owned_by_user(sk)) {
3650 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003651 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003652 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003653 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003654 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003655
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003656 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003657
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003658 case L2CAP_MODE_STREAMING:
3659 control = get_unaligned_le16(skb->data);
3660 skb_pull(skb, 2);
3661 len = skb->len;
3662
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003663 if (l2cap_check_fcs(pi, skb))
3664 goto drop;
3665
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003666 if (__is_sar_start(control))
3667 len -= 2;
3668
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003669 if (pi->fcs == L2CAP_FCS_CRC16)
3670 len -= 2;
3671
Nathan Holstein51893f82010-06-09 15:46:25 -04003672 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003673 goto drop;
3674
3675 tx_seq = __get_txseq(control);
3676
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003677 if (chan->expected_tx_seq == tx_seq)
3678 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003679 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003680 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003681
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003682 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003683
3684 goto done;
3685
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003686 default:
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003687 BT_DBG("chan %p: bad mode 0x%2.2x", chan, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003688 break;
3689 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003690
3691drop:
3692 kfree_skb(skb);
3693
3694done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003695 if (sk)
3696 bh_unlock_sock(sk);
3697
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698 return 0;
3699}
3700
Al Viro8e036fc2007-07-29 00:16:36 -07003701static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702{
3703 struct sock *sk;
3704
3705 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3706 if (!sk)
3707 goto drop;
3708
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003709 bh_lock_sock(sk);
3710
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711 BT_DBG("sk %p, len %d", sk, skb->len);
3712
3713 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3714 goto drop;
3715
3716 if (l2cap_pi(sk)->imtu < skb->len)
3717 goto drop;
3718
3719 if (!sock_queue_rcv_skb(sk, skb))
3720 goto done;
3721
3722drop:
3723 kfree_skb(skb);
3724
3725done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003726 if (sk)
3727 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003728 return 0;
3729}
3730
3731static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3732{
3733 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003734 u16 cid, len;
3735 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736
3737 skb_pull(skb, L2CAP_HDR_SIZE);
3738 cid = __le16_to_cpu(lh->cid);
3739 len = __le16_to_cpu(lh->len);
3740
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003741 if (len != skb->len) {
3742 kfree_skb(skb);
3743 return;
3744 }
3745
Linus Torvalds1da177e2005-04-16 15:20:36 -07003746 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3747
3748 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003749 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003750 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751 l2cap_sig_channel(conn, skb);
3752 break;
3753
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003754 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003755 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003756 skb_pull(skb, 2);
3757 l2cap_conless_channel(conn, psm, skb);
3758 break;
3759
3760 default:
3761 l2cap_data_channel(conn, cid, skb);
3762 break;
3763 }
3764}
3765
3766/* ---- L2CAP interface with lower layer (HCI) ---- */
3767
3768static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3769{
3770 int exact = 0, lm1 = 0, lm2 = 0;
3771 register struct sock *sk;
3772 struct hlist_node *node;
3773
3774 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003775 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776
3777 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3778
3779 /* Find listening sockets and check their link_mode */
3780 read_lock(&l2cap_sk_list.lock);
3781 sk_for_each(sk, node, &l2cap_sk_list.head) {
3782 if (sk->sk_state != BT_LISTEN)
3783 continue;
3784
3785 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003786 lm1 |= HCI_LM_ACCEPT;
3787 if (l2cap_pi(sk)->role_switch)
3788 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003789 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003790 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3791 lm2 |= HCI_LM_ACCEPT;
3792 if (l2cap_pi(sk)->role_switch)
3793 lm2 |= HCI_LM_MASTER;
3794 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003795 }
3796 read_unlock(&l2cap_sk_list.lock);
3797
3798 return exact ? lm1 : lm2;
3799}
3800
3801static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3802{
Marcel Holtmann01394182006-07-03 10:02:46 +02003803 struct l2cap_conn *conn;
3804
Linus Torvalds1da177e2005-04-16 15:20:36 -07003805 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3806
Ville Tervoacd7d372011-02-10 22:38:49 -03003807 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003808 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809
3810 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003811 conn = l2cap_conn_add(hcon, status);
3812 if (conn)
3813 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003814 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815 l2cap_conn_del(hcon, bt_err(status));
3816
3817 return 0;
3818}
3819
Marcel Holtmann2950f212009-02-12 14:02:50 +01003820static int l2cap_disconn_ind(struct hci_conn *hcon)
3821{
3822 struct l2cap_conn *conn = hcon->l2cap_data;
3823
3824 BT_DBG("hcon %p", hcon);
3825
3826 if (hcon->type != ACL_LINK || !conn)
3827 return 0x13;
3828
3829 return conn->disc_reason;
3830}
3831
3832static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833{
3834 BT_DBG("hcon %p reason %d", hcon, reason);
3835
Ville Tervoacd7d372011-02-10 22:38:49 -03003836 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003837 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838
3839 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003840
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 return 0;
3842}
3843
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003844static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3845{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003846 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003847 return;
3848
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003849 if (encrypt == 0x00) {
3850 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3851 l2cap_sock_clear_timer(sk);
3852 l2cap_sock_set_timer(sk, HZ * 5);
3853 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3854 __l2cap_sock_close(sk, ECONNREFUSED);
3855 } else {
3856 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3857 l2cap_sock_clear_timer(sk);
3858 }
3859}
3860
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003861static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003863 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003864 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865
Marcel Holtmann01394182006-07-03 10:02:46 +02003866 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003868
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869 BT_DBG("conn %p", conn);
3870
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003871 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003873 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003874 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003875
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876 bh_lock_sock(sk);
3877
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003878 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3879 bh_unlock_sock(sk);
3880 continue;
3881 }
3882
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003883 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003884 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003885 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003886 bh_unlock_sock(sk);
3887 continue;
3888 }
3889
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003890 if (sk->sk_state == BT_CONNECT) {
3891 if (!status) {
3892 struct l2cap_conn_req req;
3893 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3894 req.psm = l2cap_pi(sk)->psm;
3895
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003896 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003897 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003898
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003899 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003900 L2CAP_CONN_REQ, sizeof(req), &req);
3901 } else {
3902 l2cap_sock_clear_timer(sk);
3903 l2cap_sock_set_timer(sk, HZ / 10);
3904 }
3905 } else if (sk->sk_state == BT_CONNECT2) {
3906 struct l2cap_conn_rsp rsp;
3907 __u16 result;
3908
3909 if (!status) {
3910 sk->sk_state = BT_CONFIG;
3911 result = L2CAP_CR_SUCCESS;
3912 } else {
3913 sk->sk_state = BT_DISCONN;
3914 l2cap_sock_set_timer(sk, HZ / 10);
3915 result = L2CAP_CR_SEC_BLOCK;
3916 }
3917
3918 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3919 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3920 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003921 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003922 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
3923 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924 }
3925
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926 bh_unlock_sock(sk);
3927 }
3928
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003929 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003930
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931 return 0;
3932}
3933
3934static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3935{
3936 struct l2cap_conn *conn = hcon->l2cap_data;
3937
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003938 if (!conn)
3939 conn = l2cap_conn_add(hcon, 0);
3940
3941 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942 goto drop;
3943
3944 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3945
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003946 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003947 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003948 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003949 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950 int len;
3951
3952 if (conn->rx_len) {
3953 BT_ERR("Unexpected start frame (len %d)", skb->len);
3954 kfree_skb(conn->rx_skb);
3955 conn->rx_skb = NULL;
3956 conn->rx_len = 0;
3957 l2cap_conn_unreliable(conn, ECOMM);
3958 }
3959
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003960 /* Start fragment always begin with Basic L2CAP header */
3961 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962 BT_ERR("Frame is too short (len %d)", skb->len);
3963 l2cap_conn_unreliable(conn, ECOMM);
3964 goto drop;
3965 }
3966
3967 hdr = (struct l2cap_hdr *) skb->data;
3968 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003969 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970
3971 if (len == skb->len) {
3972 /* Complete frame received */
3973 l2cap_recv_frame(conn, skb);
3974 return 0;
3975 }
3976
3977 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3978
3979 if (skb->len > len) {
3980 BT_ERR("Frame is too long (len %d, expected len %d)",
3981 skb->len, len);
3982 l2cap_conn_unreliable(conn, ECOMM);
3983 goto drop;
3984 }
3985
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003986 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003987
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003988 if (chan && chan->sk) {
3989 struct sock *sk = chan->sk;
3990
3991 if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
3992 BT_ERR("Frame exceeding recv MTU (len %d, "
3993 "MTU %d)", len,
3994 l2cap_pi(sk)->imtu);
3995 bh_unlock_sock(sk);
3996 l2cap_conn_unreliable(conn, ECOMM);
3997 goto drop;
3998 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003999 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004000 }
4001
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004003 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4004 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004005 goto drop;
4006
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004007 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004008 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009 conn->rx_len = len - skb->len;
4010 } else {
4011 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4012
4013 if (!conn->rx_len) {
4014 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4015 l2cap_conn_unreliable(conn, ECOMM);
4016 goto drop;
4017 }
4018
4019 if (skb->len > conn->rx_len) {
4020 BT_ERR("Fragment is too long (len %d, expected %d)",
4021 skb->len, conn->rx_len);
4022 kfree_skb(conn->rx_skb);
4023 conn->rx_skb = NULL;
4024 conn->rx_len = 0;
4025 l2cap_conn_unreliable(conn, ECOMM);
4026 goto drop;
4027 }
4028
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004029 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004030 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031 conn->rx_len -= skb->len;
4032
4033 if (!conn->rx_len) {
4034 /* Complete frame received */
4035 l2cap_recv_frame(conn, conn->rx_skb);
4036 conn->rx_skb = NULL;
4037 }
4038 }
4039
4040drop:
4041 kfree_skb(skb);
4042 return 0;
4043}
4044
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004045static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046{
4047 struct sock *sk;
4048 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049
4050 read_lock_bh(&l2cap_sk_list.lock);
4051
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004052 sk_for_each(sk, node, &l2cap_sk_list.head) {
4053 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004055 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 +01004056 batostr(&bt_sk(sk)->src),
4057 batostr(&bt_sk(sk)->dst),
4058 sk->sk_state, __le16_to_cpu(pi->psm),
4059 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004060 pi->imtu, pi->omtu, pi->sec_level,
4061 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004062 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004065
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004066 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067}
4068
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004069static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4070{
4071 return single_open(file, l2cap_debugfs_show, inode->i_private);
4072}
4073
4074static const struct file_operations l2cap_debugfs_fops = {
4075 .open = l2cap_debugfs_open,
4076 .read = seq_read,
4077 .llseek = seq_lseek,
4078 .release = single_release,
4079};
4080
4081static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083static struct hci_proto l2cap_hci_proto = {
4084 .name = "L2CAP",
4085 .id = HCI_PROTO_L2CAP,
4086 .connect_ind = l2cap_connect_ind,
4087 .connect_cfm = l2cap_connect_cfm,
4088 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004089 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004090 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091 .recv_acldata = l2cap_recv_acldata
4092};
4093
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004094int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095{
4096 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004097
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004098 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099 if (err < 0)
4100 return err;
4101
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004102 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004103 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004104 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105 goto error;
4106 }
4107
4108 err = hci_register_proto(&l2cap_hci_proto);
4109 if (err < 0) {
4110 BT_ERR("L2CAP protocol registration failed");
4111 bt_sock_unregister(BTPROTO_L2CAP);
4112 goto error;
4113 }
4114
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004115 if (bt_debugfs) {
4116 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4117 bt_debugfs, NULL, &l2cap_debugfs_fops);
4118 if (!l2cap_debugfs)
4119 BT_ERR("Failed to create L2CAP debug file");
4120 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122 return 0;
4123
4124error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004125 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004126 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127 return err;
4128}
4129
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004130void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004132 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004134 flush_workqueue(_busy_wq);
4135 destroy_workqueue(_busy_wq);
4136
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4138 BT_ERR("L2CAP protocol unregistration failed");
4139
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004140 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004141}
4142
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004143module_param(disable_ertm, bool, 0644);
4144MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");