blob: 9580d6cd55daf17fc3225978db4e23137f3c5e5d [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
214 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
215
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900216 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300217 /* Delete from channel list */
218 write_lock_bh(&conn->chan_lock);
219 list_del(&chan->list);
220 write_unlock_bh(&conn->chan_lock);
221 __sock_put(sk);
222
Marcel Holtmann01394182006-07-03 10:02:46 +0200223 l2cap_pi(sk)->conn = NULL;
224 hci_conn_put(conn->hcon);
225 }
226
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200227 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200228 sock_set_flag(sk, SOCK_ZAPPED);
229
230 if (err)
231 sk->sk_err = err;
232
233 if (parent) {
234 bt_accept_unlink(sk);
235 parent->sk_data_ready(parent, 0);
236 } else
237 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300238
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300239 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE &&
240 l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE))
241 goto free;
242
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300243 skb_queue_purge(TX_QUEUE(sk));
244
245 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
246 struct srej_list *l, *tmp;
247
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300248 del_timer(&chan->retrans_timer);
249 del_timer(&chan->monitor_timer);
250 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300251
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300252 skb_queue_purge(&chan->srej_q);
253 skb_queue_purge(&chan->busy_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300254
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300255 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300256 list_del(&l->list);
257 kfree(l);
258 }
259 }
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300260
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300261free:
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300262 kfree(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200263}
264
Johan Hedberg8556edd32011-01-19 12:06:50 +0530265static inline u8 l2cap_get_auth_type(struct sock *sk)
266{
267 if (sk->sk_type == SOCK_RAW) {
268 switch (l2cap_pi(sk)->sec_level) {
269 case BT_SECURITY_HIGH:
270 return HCI_AT_DEDICATED_BONDING_MITM;
271 case BT_SECURITY_MEDIUM:
272 return HCI_AT_DEDICATED_BONDING;
273 default:
274 return HCI_AT_NO_BONDING;
275 }
276 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
277 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
278 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
279
280 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
281 return HCI_AT_NO_BONDING_MITM;
282 else
283 return HCI_AT_NO_BONDING;
284 } else {
285 switch (l2cap_pi(sk)->sec_level) {
286 case BT_SECURITY_HIGH:
287 return HCI_AT_GENERAL_BONDING_MITM;
288 case BT_SECURITY_MEDIUM:
289 return HCI_AT_GENERAL_BONDING;
290 default:
291 return HCI_AT_NO_BONDING;
292 }
293 }
294}
295
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200296/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100297static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200298{
299 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100300 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200301
Johan Hedberg8556edd32011-01-19 12:06:50 +0530302 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100303
304 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
305 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200306}
307
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200308u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200309{
310 u8 id;
311
312 /* Get next available identificator.
313 * 1 - 128 are used by kernel.
314 * 129 - 199 are reserved.
315 * 200 - 254 are used by utilities like l2ping, etc.
316 */
317
318 spin_lock_bh(&conn->lock);
319
320 if (++conn->tx_ident > 128)
321 conn->tx_ident = 1;
322
323 id = conn->tx_ident;
324
325 spin_unlock_bh(&conn->lock);
326
327 return id;
328}
329
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200330void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200331{
332 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200333 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200334
335 BT_DBG("code 0x%2.2x", code);
336
337 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300338 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200339
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200340 if (lmp_no_flush_capable(conn->hcon->hdev))
341 flags = ACL_START_NO_FLUSH;
342 else
343 flags = ACL_START;
344
345 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200346}
347
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300348static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300349{
350 struct sk_buff *skb;
351 struct l2cap_hdr *lh;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300352 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300353 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300354 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300355 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200356 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300357
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300358 if (sk->sk_state != BT_CONNECTED)
359 return;
360
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300361 if (pi->fcs == L2CAP_FCS_CRC16)
362 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300363
364 BT_DBG("pi %p, control 0x%2.2x", pi, control);
365
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300366 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300367 control |= L2CAP_CTRL_FRAME_TYPE;
368
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300369 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300370 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300371 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300372 }
373
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300374 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300375 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300376 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300377 }
378
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300379 skb = bt_skb_alloc(count, GFP_ATOMIC);
380 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300381 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300382
383 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300384 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300385 lh->cid = cpu_to_le16(pi->dcid);
386 put_unaligned_le16(control, skb_put(skb, 2));
387
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300388 if (pi->fcs == L2CAP_FCS_CRC16) {
389 u16 fcs = crc16(0, (u8 *)lh, count - 2);
390 put_unaligned_le16(fcs, skb_put(skb, 2));
391 }
392
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200393 if (lmp_no_flush_capable(conn->hcon->hdev))
394 flags = ACL_START_NO_FLUSH;
395 else
396 flags = ACL_START;
397
398 hci_send_acl(pi->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300399}
400
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300401static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300402{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300403 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300404 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300405 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300406 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300407 control |= L2CAP_SUPER_RCV_READY;
408
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300409 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300410
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300411 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300412}
413
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300414static inline int __l2cap_no_conn_pending(struct sock *sk)
415{
416 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
417}
418
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300419static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200420{
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300421 struct sock *sk = chan->sk;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200422 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
423
424 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100425 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
426 return;
427
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300428 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200429 struct l2cap_conn_req req;
430 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
431 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200432
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300433 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300434 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200435
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300436 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
437 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200438 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200439 } else {
440 struct l2cap_info_req req;
441 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
442
443 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
444 conn->info_ident = l2cap_get_ident(conn);
445
446 mod_timer(&conn->info_timer, jiffies +
447 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
448
449 l2cap_send_cmd(conn, conn->info_ident,
450 L2CAP_INFO_REQ, sizeof(req), &req);
451 }
452}
453
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300454static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
455{
456 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300457 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300458 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
459
460 switch (mode) {
461 case L2CAP_MODE_ERTM:
462 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
463 case L2CAP_MODE_STREAMING:
464 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
465 default:
466 return 0x00;
467 }
468}
469
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300470void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300471{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300472 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300473 struct l2cap_disconn_req req;
474
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300475 if (!conn)
476 return;
477
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300478 sk = chan->sk;
479
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300480 skb_queue_purge(TX_QUEUE(sk));
481
482 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300483 del_timer(&chan->retrans_timer);
484 del_timer(&chan->monitor_timer);
485 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300486 }
487
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300488 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
489 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
490 l2cap_send_cmd(conn, l2cap_get_ident(conn),
491 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300492
493 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300494 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300495}
496
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200498static void l2cap_conn_start(struct l2cap_conn *conn)
499{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300500 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200501
502 BT_DBG("conn %p", conn);
503
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300504 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200505
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300506 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300507 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300508
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200509 bh_lock_sock(sk);
510
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300511 if (sk->sk_type != SOCK_SEQPACKET &&
512 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200513 bh_unlock_sock(sk);
514 continue;
515 }
516
517 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300518 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300519
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300520 if (!l2cap_check_security(sk) ||
521 !__l2cap_no_conn_pending(sk)) {
522 bh_unlock_sock(sk);
523 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200524 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300525
526 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
527 conn->feat_mask)
528 && l2cap_pi(sk)->conf_state &
529 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300530 /* __l2cap_sock_close() calls list_del(chan)
531 * so release the lock */
532 read_unlock_bh(&conn->chan_lock);
533 __l2cap_sock_close(sk, ECONNRESET);
534 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300535 bh_unlock_sock(sk);
536 continue;
537 }
538
539 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
540 req.psm = l2cap_pi(sk)->psm;
541
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300542 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300543 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
544
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300545 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
546 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300547
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200548 } else if (sk->sk_state == BT_CONNECT2) {
549 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300550 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200551 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
552 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
553
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100554 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100555 if (bt_sk(sk)->defer_setup) {
556 struct sock *parent = bt_sk(sk)->parent;
557 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
558 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
559 parent->sk_data_ready(parent, 0);
560
561 } else {
562 sk->sk_state = BT_CONFIG;
563 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
564 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
565 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200566 } else {
567 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
568 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
569 }
570
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300571 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
572 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300573
574 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
575 rsp.result != L2CAP_CR_SUCCESS) {
576 bh_unlock_sock(sk);
577 continue;
578 }
579
580 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
581 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300582 l2cap_build_conf_req(chan, buf), buf);
583 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200584 }
585
586 bh_unlock_sock(sk);
587 }
588
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300589 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200590}
591
Ville Tervob62f3282011-02-10 22:38:50 -0300592/* Find socket with cid and source bdaddr.
593 * Returns closest match, locked.
594 */
595static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
596{
597 struct sock *s, *sk = NULL, *sk1 = NULL;
598 struct hlist_node *node;
599
600 read_lock(&l2cap_sk_list.lock);
601
602 sk_for_each(sk, node, &l2cap_sk_list.head) {
603 if (state && sk->sk_state != state)
604 continue;
605
606 if (l2cap_pi(sk)->scid == cid) {
607 /* Exact match. */
608 if (!bacmp(&bt_sk(sk)->src, src))
609 break;
610
611 /* Closest match */
612 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
613 sk1 = sk;
614 }
615 }
616 s = node ? sk : sk1;
617 if (s)
618 bh_lock_sock(s);
619 read_unlock(&l2cap_sk_list.lock);
620
621 return s;
622}
623
624static void l2cap_le_conn_ready(struct l2cap_conn *conn)
625{
Ville Tervob62f3282011-02-10 22:38:50 -0300626 struct sock *parent, *uninitialized_var(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300627 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300628
629 BT_DBG("");
630
631 /* Check if we have socket listening on cid */
632 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
633 conn->src);
634 if (!parent)
635 return;
636
637 /* Check for backlog size */
638 if (sk_acceptq_is_full(parent)) {
639 BT_DBG("backlog full %d", parent->sk_ack_backlog);
640 goto clean;
641 }
642
643 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
644 if (!sk)
645 goto clean;
646
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300647 chan = l2cap_chan_alloc(sk);
648 if (!chan) {
649 l2cap_sock_kill(sk);
650 goto clean;
651 }
652
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300653 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300654
655 hci_conn_hold(conn->hcon);
656
657 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300658
Ville Tervob62f3282011-02-10 22:38:50 -0300659 bacpy(&bt_sk(sk)->src, conn->src);
660 bacpy(&bt_sk(sk)->dst, conn->dst);
661
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300662 bt_accept_enqueue(parent, sk);
663
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300664 __l2cap_chan_add(conn, chan);
665
666 l2cap_pi(sk)->chan = chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300667
668 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
669
670 sk->sk_state = BT_CONNECTED;
671 parent->sk_data_ready(parent, 0);
672
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300673 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300674
675clean:
676 bh_unlock_sock(parent);
677}
678
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200679static void l2cap_conn_ready(struct l2cap_conn *conn)
680{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300681 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200682
683 BT_DBG("conn %p", conn);
684
Ville Tervob62f3282011-02-10 22:38:50 -0300685 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
686 l2cap_le_conn_ready(conn);
687
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300688 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200689
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300690 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300691 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300692
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200693 bh_lock_sock(sk);
694
Ville Tervoacd7d372011-02-10 22:38:49 -0300695 if (conn->hcon->type == LE_LINK) {
696 l2cap_sock_clear_timer(sk);
697 sk->sk_state = BT_CONNECTED;
698 sk->sk_state_change(sk);
699 }
700
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300701 if (sk->sk_type != SOCK_SEQPACKET &&
702 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200703 l2cap_sock_clear_timer(sk);
704 sk->sk_state = BT_CONNECTED;
705 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200706 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300707 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200708
709 bh_unlock_sock(sk);
710 }
711
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300712 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200713}
714
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200715/* Notify sockets that we cannot guaranty reliability anymore */
716static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
717{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300718 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200719
720 BT_DBG("conn %p", conn);
721
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300722 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200723
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300724 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300725 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300726
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100727 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200728 sk->sk_err = err;
729 }
730
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300731 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200732}
733
734static void l2cap_info_timeout(unsigned long arg)
735{
736 struct l2cap_conn *conn = (void *) arg;
737
Marcel Holtmann984947d2009-02-06 23:35:19 +0100738 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100739 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100740
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200741 l2cap_conn_start(conn);
742}
743
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
745{
Marcel Holtmann01394182006-07-03 10:02:46 +0200746 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
Marcel Holtmann01394182006-07-03 10:02:46 +0200748 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 return conn;
750
Marcel Holtmann01394182006-07-03 10:02:46 +0200751 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
752 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
755 hcon->l2cap_data = conn;
756 conn->hcon = hcon;
757
Marcel Holtmann01394182006-07-03 10:02:46 +0200758 BT_DBG("hcon %p conn %p", hcon, conn);
759
Ville Tervoacd7d372011-02-10 22:38:49 -0300760 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
761 conn->mtu = hcon->hdev->le_mtu;
762 else
763 conn->mtu = hcon->hdev->acl_mtu;
764
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 conn->src = &hcon->hdev->bdaddr;
766 conn->dst = &hcon->dst;
767
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200768 conn->feat_mask = 0;
769
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300771 rwlock_init(&conn->chan_lock);
772
773 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774
Ville Tervob62f3282011-02-10 22:38:50 -0300775 if (hcon->type != LE_LINK)
776 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000777 (unsigned long) conn);
778
Marcel Holtmann2950f212009-02-12 14:02:50 +0100779 conn->disc_reason = 0x13;
780
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 return conn;
782}
783
Marcel Holtmann01394182006-07-03 10:02:46 +0200784static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785{
Marcel Holtmann01394182006-07-03 10:02:46 +0200786 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300787 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 struct sock *sk;
789
Marcel Holtmann01394182006-07-03 10:02:46 +0200790 if (!conn)
791 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
793 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
794
Wei Yongjun7585b972009-02-25 18:29:52 +0800795 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796
797 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300798 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300799 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300801 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 bh_unlock_sock(sk);
803 l2cap_sock_kill(sk);
804 }
805
Dave Young8e8440f2008-03-03 12:18:55 -0800806 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
807 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800808
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 hcon->l2cap_data = NULL;
810 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811}
812
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300813static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300815 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300816 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300817 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818}
819
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
822/* Find socket with psm and source bdaddr.
823 * Returns closest match.
824 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000825static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826{
827 struct sock *sk = NULL, *sk1 = NULL;
828 struct hlist_node *node;
829
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000830 read_lock(&l2cap_sk_list.lock);
831
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 sk_for_each(sk, node, &l2cap_sk_list.head) {
833 if (state && sk->sk_state != state)
834 continue;
835
836 if (l2cap_pi(sk)->psm == psm) {
837 /* Exact match. */
838 if (!bacmp(&bt_sk(sk)->src, src))
839 break;
840
841 /* Closest match */
842 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
843 sk1 = sk;
844 }
845 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000848
849 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850}
851
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200852int l2cap_do_connect(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853{
854 bdaddr_t *src = &bt_sk(sk)->src;
855 bdaddr_t *dst = &bt_sk(sk)->dst;
856 struct l2cap_conn *conn;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300857 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 struct hci_conn *hcon;
859 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200860 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200861 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100863 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
864 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300866 hdev = hci_get_route(dst, src);
867 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 return -EHOSTUNREACH;
869
870 hci_dev_lock_bh(hdev);
871
Johan Hedberg8556edd32011-01-19 12:06:50 +0530872 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200873
Ville Tervoacd7d372011-02-10 22:38:49 -0300874 if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
875 hcon = hci_connect(hdev, LE_LINK, dst,
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100876 l2cap_pi(sk)->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300877 else
878 hcon = hci_connect(hdev, ACL_LINK, dst,
879 l2cap_pi(sk)->sec_level, auth_type);
880
Ville Tervo30e76272011-02-22 16:10:53 -0300881 if (IS_ERR(hcon)) {
882 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300884 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885
886 conn = l2cap_conn_add(hcon, 0);
887 if (!conn) {
888 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300889 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 goto done;
891 }
892
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300893 chan = l2cap_chan_alloc(sk);
894 if (!chan) {
895 hci_conn_put(hcon);
896 err = -ENOMEM;
897 goto done;
898 }
899
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 /* Update source addr of the socket */
901 bacpy(src, conn->src);
902
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300903 l2cap_chan_add(conn, chan);
904
905 l2cap_pi(sk)->chan = chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906
907 sk->sk_state = BT_CONNECT;
908 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
909
910 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300911 if (sk->sk_type != SOCK_SEQPACKET &&
912 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530914 if (l2cap_check_security(sk))
915 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200916 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300917 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 }
919
Ville Tervo30e76272011-02-22 16:10:53 -0300920 err = 0;
921
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922done:
923 hci_dev_unlock_bh(hdev);
924 hci_dev_put(hdev);
925 return err;
926}
927
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200928int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300929{
930 DECLARE_WAITQUEUE(wait, current);
931 int err = 0;
932 int timeo = HZ/5;
933
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200934 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300935 while ((l2cap_pi(sk)->chan->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300936 set_current_state(TASK_INTERRUPTIBLE);
937
938 if (!timeo)
939 timeo = HZ/5;
940
941 if (signal_pending(current)) {
942 err = sock_intr_errno(timeo);
943 break;
944 }
945
946 release_sock(sk);
947 timeo = schedule_timeout(timeo);
948 lock_sock(sk);
949
950 err = sock_error(sk);
951 if (err)
952 break;
953 }
954 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200955 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300956 return err;
957}
958
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300959static void l2cap_monitor_timeout(unsigned long arg)
960{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300961 struct l2cap_chan *chan = (void *) arg;
962 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300963
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300964 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300965
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300966 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -0300967 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300968 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200969 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300970 return;
971 }
972
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300973 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300974 __mod_monitor_timer();
975
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300976 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300977 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300978}
979
980static void l2cap_retrans_timeout(unsigned long arg)
981{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300982 struct l2cap_chan *chan = (void *) arg;
983 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300984
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300985 BT_DBG("sk %p", sk);
986
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300987 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300988 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300989 __mod_monitor_timer();
990
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300991 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300992
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300993 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300994 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300995}
996
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300997static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300998{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300999 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001000 struct sk_buff *skb;
1001
Gustavo F. Padovan812e7372010-05-01 16:15:42 -03001002 while ((skb = skb_peek(TX_QUEUE(sk))) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001003 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001004 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001005 break;
1006
1007 skb = skb_dequeue(TX_QUEUE(sk));
1008 kfree_skb(skb);
1009
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001010 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001011 }
1012
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001013 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001014 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001015}
1016
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001017void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001018{
1019 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001020 struct hci_conn *hcon = pi->conn->hcon;
1021 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001022
1023 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1024
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001025 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
1026 flags = ACL_START_NO_FLUSH;
1027 else
1028 flags = ACL_START;
1029
1030 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001031}
1032
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001033void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001034{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001035 struct sock *sk = chan->sk;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001036 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001037 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001038 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001039
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001040 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
1041 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001042 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001043 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001044
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001045 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001046 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1047 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001048 }
1049
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001050 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001051
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001052 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001053 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001054}
1055
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001056static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001057{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001058 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001059 struct l2cap_pinfo *pi = l2cap_pi(sk);
1060 struct sk_buff *skb, *tx_skb;
1061 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001062
1063 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001064 if (!skb)
1065 return;
1066
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001067 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001068 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001069 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001070
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001071 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1072 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001073
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001074 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001075
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001076 if (chan->remote_max_tx &&
1077 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001078 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001079 return;
1080 }
1081
1082 tx_skb = skb_clone(skb, GFP_ATOMIC);
1083 bt_cb(skb)->retries++;
1084 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001085
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001086 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001087 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001088 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001089 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001090
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001091 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001092 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001093
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001094 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1095
1096 if (pi->fcs == L2CAP_FCS_CRC16) {
1097 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1098 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1099 }
1100
1101 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001102}
1103
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001104int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001105{
1106 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001107 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001108 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001109 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001110 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001111
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001112 if (sk->sk_state != BT_CONNECTED)
1113 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001114
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001115 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001116
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001117 if (chan->remote_max_tx &&
1118 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001119 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001120 break;
1121 }
1122
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001123 tx_skb = skb_clone(skb, GFP_ATOMIC);
1124
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001125 bt_cb(skb)->retries++;
1126
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001127 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001128 control &= L2CAP_CTRL_SAR;
1129
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001130 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001131 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001132 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001133 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001134 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1135 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001136 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1137
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001138
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001139 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001140 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1141 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1142 }
1143
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001144 l2cap_do_send(sk, tx_skb);
1145
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001146 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001147
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001148 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1149 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001150
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301151 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001152 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301153
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001154 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001155
1156 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1157 sk->sk_send_head = NULL;
1158 else
1159 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001160
1161 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001162 }
1163
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001164 return nsent;
1165}
1166
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001167static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001168{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001169 struct sock *sk = chan->sk;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001170 int ret;
1171
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001172 if (!skb_queue_empty(TX_QUEUE(sk)))
1173 sk->sk_send_head = TX_QUEUE(sk)->next;
1174
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001175 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001176 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001177 return ret;
1178}
1179
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001180static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001181{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001182 u16 control = 0;
1183
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001184 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001185
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001186 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001187 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001188 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1189 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001190 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001191 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001192
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001193 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001194 return;
1195
1196 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001197 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001198}
1199
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001200static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001201{
1202 struct srej_list *tail;
1203 u16 control;
1204
1205 control = L2CAP_SUPER_SELECT_REJECT;
1206 control |= L2CAP_CTRL_FINAL;
1207
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001208 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001209 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1210
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001211 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001212}
1213
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001214static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215{
1216 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001217 struct sk_buff **frag;
1218 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001220 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001221 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222
1223 sent += count;
1224 len -= count;
1225
1226 /* Continuation fragments (no L2CAP header) */
1227 frag = &skb_shinfo(skb)->frag_list;
1228 while (len) {
1229 count = min_t(unsigned int, conn->mtu, len);
1230
1231 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1232 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001233 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001234 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1235 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236
1237 sent += count;
1238 len -= count;
1239
1240 frag = &(*frag)->next;
1241 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242
1243 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001244}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001246struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001247{
1248 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1249 struct sk_buff *skb;
1250 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1251 struct l2cap_hdr *lh;
1252
1253 BT_DBG("sk %p len %d", sk, (int)len);
1254
1255 count = min_t(unsigned int, (conn->mtu - hlen), len);
1256 skb = bt_skb_send_alloc(sk, count + hlen,
1257 msg->msg_flags & MSG_DONTWAIT, &err);
1258 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001259 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001260
1261 /* Create L2CAP header */
1262 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1263 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1264 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1265 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1266
1267 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1268 if (unlikely(err < 0)) {
1269 kfree_skb(skb);
1270 return ERR_PTR(err);
1271 }
1272 return skb;
1273}
1274
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001275struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001276{
1277 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1278 struct sk_buff *skb;
1279 int err, count, hlen = L2CAP_HDR_SIZE;
1280 struct l2cap_hdr *lh;
1281
1282 BT_DBG("sk %p len %d", sk, (int)len);
1283
1284 count = min_t(unsigned int, (conn->mtu - hlen), len);
1285 skb = bt_skb_send_alloc(sk, count + hlen,
1286 msg->msg_flags & MSG_DONTWAIT, &err);
1287 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001288 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001289
1290 /* Create L2CAP header */
1291 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1292 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1293 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1294
1295 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1296 if (unlikely(err < 0)) {
1297 kfree_skb(skb);
1298 return ERR_PTR(err);
1299 }
1300 return skb;
1301}
1302
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001303struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001304{
1305 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1306 struct sk_buff *skb;
1307 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1308 struct l2cap_hdr *lh;
1309
1310 BT_DBG("sk %p len %d", sk, (int)len);
1311
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001312 if (!conn)
1313 return ERR_PTR(-ENOTCONN);
1314
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001315 if (sdulen)
1316 hlen += 2;
1317
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001318 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1319 hlen += 2;
1320
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001321 count = min_t(unsigned int, (conn->mtu - hlen), len);
1322 skb = bt_skb_send_alloc(sk, count + hlen,
1323 msg->msg_flags & MSG_DONTWAIT, &err);
1324 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001325 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001326
1327 /* Create L2CAP header */
1328 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1329 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1330 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1331 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001332 if (sdulen)
1333 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001334
1335 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1336 if (unlikely(err < 0)) {
1337 kfree_skb(skb);
1338 return ERR_PTR(err);
1339 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001340
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001341 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1342 put_unaligned_le16(0, skb_put(skb, 2));
1343
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001344 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001345 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346}
1347
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001348int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001349{
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001350 struct sock *sk = chan->sk;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001351 struct sk_buff *skb;
1352 struct sk_buff_head sar_queue;
1353 u16 control;
1354 size_t size = 0;
1355
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001356 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001357 control = L2CAP_SDU_START;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001358 skb = l2cap_create_iframe_pdu(sk, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001359 if (IS_ERR(skb))
1360 return PTR_ERR(skb);
1361
1362 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001363 len -= chan->remote_mps;
1364 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001365
1366 while (len > 0) {
1367 size_t buflen;
1368
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001369 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001370 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001371 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001372 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001373 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001374 buflen = len;
1375 }
1376
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001377 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001378 if (IS_ERR(skb)) {
1379 skb_queue_purge(&sar_queue);
1380 return PTR_ERR(skb);
1381 }
1382
1383 __skb_queue_tail(&sar_queue, skb);
1384 len -= buflen;
1385 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001386 }
1387 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1388 if (sk->sk_send_head == NULL)
1389 sk->sk_send_head = sar_queue.next;
1390
1391 return size;
1392}
1393
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394static void l2cap_chan_ready(struct sock *sk)
1395{
1396 struct sock *parent = bt_sk(sk)->parent;
1397
1398 BT_DBG("sk %p, parent %p", sk, parent);
1399
1400 l2cap_pi(sk)->conf_state = 0;
1401 l2cap_sock_clear_timer(sk);
1402
1403 if (!parent) {
1404 /* Outgoing channel.
1405 * Wake up socket sleeping on connect.
1406 */
1407 sk->sk_state = BT_CONNECTED;
1408 sk->sk_state_change(sk);
1409 } else {
1410 /* Incoming channel.
1411 * Wake up socket sleeping on accept.
1412 */
1413 parent->sk_data_ready(parent, 0);
1414 }
1415}
1416
1417/* Copy frame to all raw sockets on that connection */
1418static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1419{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001421 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422
1423 BT_DBG("conn %p", conn);
1424
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001425 read_lock(&conn->chan_lock);
1426 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001427 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 if (sk->sk_type != SOCK_RAW)
1429 continue;
1430
1431 /* Don't send frame to the socket it came from */
1432 if (skb->sk == sk)
1433 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001434 nskb = skb_clone(skb, GFP_ATOMIC);
1435 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 continue;
1437
1438 if (sock_queue_rcv_skb(sk, nskb))
1439 kfree_skb(nskb);
1440 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001441 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442}
1443
1444/* ---- L2CAP signalling commands ---- */
1445static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1446 u8 code, u8 ident, u16 dlen, void *data)
1447{
1448 struct sk_buff *skb, **frag;
1449 struct l2cap_cmd_hdr *cmd;
1450 struct l2cap_hdr *lh;
1451 int len, count;
1452
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001453 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1454 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455
1456 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1457 count = min_t(unsigned int, conn->mtu, len);
1458
1459 skb = bt_skb_alloc(count, GFP_ATOMIC);
1460 if (!skb)
1461 return NULL;
1462
1463 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001464 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001465
1466 if (conn->hcon->type == LE_LINK)
1467 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1468 else
1469 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
1471 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1472 cmd->code = code;
1473 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001474 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475
1476 if (dlen) {
1477 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1478 memcpy(skb_put(skb, count), data, count);
1479 data += count;
1480 }
1481
1482 len -= skb->len;
1483
1484 /* Continuation fragments (no L2CAP header) */
1485 frag = &skb_shinfo(skb)->frag_list;
1486 while (len) {
1487 count = min_t(unsigned int, conn->mtu, len);
1488
1489 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1490 if (!*frag)
1491 goto fail;
1492
1493 memcpy(skb_put(*frag, count), data, count);
1494
1495 len -= count;
1496 data += count;
1497
1498 frag = &(*frag)->next;
1499 }
1500
1501 return skb;
1502
1503fail:
1504 kfree_skb(skb);
1505 return NULL;
1506}
1507
1508static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1509{
1510 struct l2cap_conf_opt *opt = *ptr;
1511 int len;
1512
1513 len = L2CAP_CONF_OPT_SIZE + opt->len;
1514 *ptr += len;
1515
1516 *type = opt->type;
1517 *olen = opt->len;
1518
1519 switch (opt->len) {
1520 case 1:
1521 *val = *((u8 *) opt->val);
1522 break;
1523
1524 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001525 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 break;
1527
1528 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001529 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 break;
1531
1532 default:
1533 *val = (unsigned long) opt->val;
1534 break;
1535 }
1536
1537 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1538 return len;
1539}
1540
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1542{
1543 struct l2cap_conf_opt *opt = *ptr;
1544
1545 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1546
1547 opt->type = type;
1548 opt->len = len;
1549
1550 switch (len) {
1551 case 1:
1552 *((u8 *) opt->val) = val;
1553 break;
1554
1555 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001556 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 break;
1558
1559 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001560 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561 break;
1562
1563 default:
1564 memcpy(opt->val, (void *) val, len);
1565 break;
1566 }
1567
1568 *ptr += L2CAP_CONF_OPT_SIZE + len;
1569}
1570
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001571static void l2cap_ack_timeout(unsigned long arg)
1572{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001573 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001574
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001575 bh_lock_sock(chan->sk);
1576 l2cap_send_ack(chan);
1577 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001578}
1579
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001580static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001581{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001582 struct sock *sk = chan->sk;
1583
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001584 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001585 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001586 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001587 chan->num_acked = 0;
1588 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001589
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001590 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1591 (unsigned long) chan);
1592 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1593 (unsigned long) chan);
1594 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001595
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001596 skb_queue_head_init(&chan->srej_q);
1597 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001598
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001599 INIT_LIST_HEAD(&chan->srej_l);
1600
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001601 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001602
1603 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001604}
1605
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001606static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1607{
1608 switch (mode) {
1609 case L2CAP_MODE_STREAMING:
1610 case L2CAP_MODE_ERTM:
1611 if (l2cap_mode_supported(mode, remote_feat_mask))
1612 return mode;
1613 /* fall through */
1614 default:
1615 return L2CAP_MODE_BASIC;
1616 }
1617}
1618
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001619static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001621 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 struct l2cap_pinfo *pi = l2cap_pi(sk);
1623 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001624 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 void *ptr = req->data;
1626
1627 BT_DBG("sk %p", sk);
1628
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001629 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001630 goto done;
1631
1632 switch (pi->mode) {
1633 case L2CAP_MODE_STREAMING:
1634 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001635 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001636 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001637
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001638 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001639 default:
1640 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1641 break;
1642 }
1643
1644done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001645 if (pi->imtu != L2CAP_DEFAULT_MTU)
1646 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1647
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001648 switch (pi->mode) {
1649 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001650 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1651 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1652 break;
1653
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001654 rfc.mode = L2CAP_MODE_BASIC;
1655 rfc.txwin_size = 0;
1656 rfc.max_transmit = 0;
1657 rfc.retrans_timeout = 0;
1658 rfc.monitor_timeout = 0;
1659 rfc.max_pdu_size = 0;
1660
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001661 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1662 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001663 break;
1664
1665 case L2CAP_MODE_ERTM:
1666 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001667 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001668 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001669 rfc.retrans_timeout = 0;
1670 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001671 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001672 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001673 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001674
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001675 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1676 (unsigned long) &rfc);
1677
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001678 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1679 break;
1680
1681 if (pi->fcs == L2CAP_FCS_NONE ||
1682 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1683 pi->fcs = L2CAP_FCS_NONE;
1684 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1685 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001686 break;
1687
1688 case L2CAP_MODE_STREAMING:
1689 rfc.mode = L2CAP_MODE_STREAMING;
1690 rfc.txwin_size = 0;
1691 rfc.max_transmit = 0;
1692 rfc.retrans_timeout = 0;
1693 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001694 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001695 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001696 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001697
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001698 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1699 (unsigned long) &rfc);
1700
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001701 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1702 break;
1703
1704 if (pi->fcs == L2CAP_FCS_NONE ||
1705 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1706 pi->fcs = L2CAP_FCS_NONE;
1707 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1708 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001709 break;
1710 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001712 req->dcid = cpu_to_le16(pi->dcid);
1713 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714
1715 return ptr - data;
1716}
1717
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001718static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001720 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001721 struct l2cap_conf_rsp *rsp = data;
1722 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001723 void *req = chan->conf_req;
1724 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001725 int type, hint, olen;
1726 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001727 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001728 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001729 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001731 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001732
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001733 while (len >= L2CAP_CONF_OPT_SIZE) {
1734 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001736 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001737 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001738
1739 switch (type) {
1740 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001741 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001742 break;
1743
1744 case L2CAP_CONF_FLUSH_TO:
1745 pi->flush_to = val;
1746 break;
1747
1748 case L2CAP_CONF_QOS:
1749 break;
1750
Marcel Holtmann6464f352007-10-20 13:39:51 +02001751 case L2CAP_CONF_RFC:
1752 if (olen == sizeof(rfc))
1753 memcpy(&rfc, (void *) val, olen);
1754 break;
1755
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001756 case L2CAP_CONF_FCS:
1757 if (val == L2CAP_FCS_NONE)
1758 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1759
1760 break;
1761
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001762 default:
1763 if (hint)
1764 break;
1765
1766 result = L2CAP_CONF_UNKNOWN;
1767 *((u8 *) ptr++) = type;
1768 break;
1769 }
1770 }
1771
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001772 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001773 goto done;
1774
1775 switch (pi->mode) {
1776 case L2CAP_MODE_STREAMING:
1777 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001778 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1779 pi->mode = l2cap_select_mode(rfc.mode,
1780 pi->conn->feat_mask);
1781 break;
1782 }
1783
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001784 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001785 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001786
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001787 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001788 }
1789
1790done:
1791 if (pi->mode != rfc.mode) {
1792 result = L2CAP_CONF_UNACCEPT;
1793 rfc.mode = pi->mode;
1794
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001795 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001796 return -ECONNREFUSED;
1797
1798 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1799 sizeof(rfc), (unsigned long) &rfc);
1800 }
1801
1802
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001803 if (result == L2CAP_CONF_SUCCESS) {
1804 /* Configure output options and let the other side know
1805 * which ones we don't like. */
1806
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001807 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1808 result = L2CAP_CONF_UNACCEPT;
1809 else {
1810 pi->omtu = mtu;
1811 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1812 }
1813 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001814
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001815 switch (rfc.mode) {
1816 case L2CAP_MODE_BASIC:
1817 pi->fcs = L2CAP_FCS_NONE;
1818 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1819 break;
1820
1821 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001822 chan->remote_tx_win = rfc.txwin_size;
1823 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001824
1825 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1826 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001827
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001828 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001829
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001830 rfc.retrans_timeout =
1831 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1832 rfc.monitor_timeout =
1833 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001834
1835 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001836
1837 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1838 sizeof(rfc), (unsigned long) &rfc);
1839
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001840 break;
1841
1842 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001843 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1844 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001845
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001846 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001847
1848 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001849
1850 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1851 sizeof(rfc), (unsigned long) &rfc);
1852
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001853 break;
1854
1855 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001856 result = L2CAP_CONF_UNACCEPT;
1857
1858 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001859 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001860 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001861
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001862 if (result == L2CAP_CONF_SUCCESS)
1863 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1864 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001865 rsp->scid = cpu_to_le16(pi->dcid);
1866 rsp->result = cpu_to_le16(result);
1867 rsp->flags = cpu_to_le16(0x0000);
1868
1869 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870}
1871
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001872static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1873{
1874 struct l2cap_pinfo *pi = l2cap_pi(sk);
1875 struct l2cap_conf_req *req = data;
1876 void *ptr = req->data;
1877 int type, olen;
1878 unsigned long val;
1879 struct l2cap_conf_rfc rfc;
1880
1881 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1882
1883 while (len >= L2CAP_CONF_OPT_SIZE) {
1884 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1885
1886 switch (type) {
1887 case L2CAP_CONF_MTU:
1888 if (val < L2CAP_DEFAULT_MIN_MTU) {
1889 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001890 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001891 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001892 pi->imtu = val;
1893 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001894 break;
1895
1896 case L2CAP_CONF_FLUSH_TO:
1897 pi->flush_to = val;
1898 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1899 2, pi->flush_to);
1900 break;
1901
1902 case L2CAP_CONF_RFC:
1903 if (olen == sizeof(rfc))
1904 memcpy(&rfc, (void *)val, olen);
1905
1906 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1907 rfc.mode != pi->mode)
1908 return -ECONNREFUSED;
1909
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001910 pi->fcs = 0;
1911
1912 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1913 sizeof(rfc), (unsigned long) &rfc);
1914 break;
1915 }
1916 }
1917
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001918 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1919 return -ECONNREFUSED;
1920
1921 pi->mode = rfc.mode;
1922
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001923 if (*result == L2CAP_CONF_SUCCESS) {
1924 switch (rfc.mode) {
1925 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001926 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1927 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
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 break;
1930 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001931 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001932 }
1933 }
1934
1935 req->dcid = cpu_to_le16(pi->dcid);
1936 req->flags = cpu_to_le16(0x0000);
1937
1938 return ptr - data;
1939}
1940
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001941static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942{
1943 struct l2cap_conf_rsp *rsp = data;
1944 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001946 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001948 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001949 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001950 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951
1952 return ptr - data;
1953}
1954
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001955void __l2cap_connect_rsp_defer(struct sock *sk)
1956{
1957 struct l2cap_conn_rsp rsp;
1958 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1959 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
1960 u8 buf[128];
1961
1962 sk->sk_state = BT_CONFIG;
1963
1964 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1965 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1966 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1967 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1968 l2cap_send_cmd(conn, chan->ident,
1969 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1970
1971 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
1972 return;
1973
1974 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
1975 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1976 l2cap_build_conf_req(chan, buf), buf);
1977 chan->num_conf_req++;
1978}
1979
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001980static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1981{
1982 struct l2cap_pinfo *pi = l2cap_pi(sk);
1983 int type, olen;
1984 unsigned long val;
1985 struct l2cap_conf_rfc rfc;
1986
1987 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1988
1989 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1990 return;
1991
1992 while (len >= L2CAP_CONF_OPT_SIZE) {
1993 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1994
1995 switch (type) {
1996 case L2CAP_CONF_RFC:
1997 if (olen == sizeof(rfc))
1998 memcpy(&rfc, (void *)val, olen);
1999 goto done;
2000 }
2001 }
2002
2003done:
2004 switch (rfc.mode) {
2005 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002006 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2007 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002008 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2009 break;
2010 case L2CAP_MODE_STREAMING:
2011 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2012 }
2013}
2014
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002015static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2016{
2017 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2018
2019 if (rej->reason != 0x0000)
2020 return 0;
2021
2022 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2023 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002024 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002025
2026 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002027 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002028
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002029 l2cap_conn_start(conn);
2030 }
2031
2032 return 0;
2033}
2034
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2036{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2038 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002039 struct l2cap_chan *chan = NULL;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002040 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002041 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042
2043 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002044 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045
2046 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2047
2048 /* Check if we have socket listening on psm */
2049 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2050 if (!parent) {
2051 result = L2CAP_CR_BAD_PSM;
2052 goto sendresp;
2053 }
2054
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002055 bh_lock_sock(parent);
2056
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002057 /* Check if the ACL is secure enough (if not SDP) */
2058 if (psm != cpu_to_le16(0x0001) &&
2059 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002060 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002061 result = L2CAP_CR_SEC_BLOCK;
2062 goto response;
2063 }
2064
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 result = L2CAP_CR_NO_MEM;
2066
2067 /* Check for backlog size */
2068 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002069 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 goto response;
2071 }
2072
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002073 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 if (!sk)
2075 goto response;
2076
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002077 chan = l2cap_chan_alloc(sk);
2078 if (!chan) {
2079 l2cap_sock_kill(sk);
2080 goto response;
2081 }
2082
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002083 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084
2085 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002086 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2087 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 sock_set_flag(sk, SOCK_ZAPPED);
2089 l2cap_sock_kill(sk);
2090 goto response;
2091 }
2092
2093 hci_conn_hold(conn->hcon);
2094
2095 l2cap_sock_init(sk, parent);
2096 bacpy(&bt_sk(sk)->src, conn->src);
2097 bacpy(&bt_sk(sk)->dst, conn->dst);
2098 l2cap_pi(sk)->psm = psm;
2099 l2cap_pi(sk)->dcid = scid;
2100
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002101 bt_accept_enqueue(parent, sk);
2102
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002103 __l2cap_chan_add(conn, chan);
2104
2105 l2cap_pi(sk)->chan = chan;
2106
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 dcid = l2cap_pi(sk)->scid;
2108
2109 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2110
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002111 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112
Marcel Holtmann984947d2009-02-06 23:35:19 +01002113 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002114 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002115 if (bt_sk(sk)->defer_setup) {
2116 sk->sk_state = BT_CONNECT2;
2117 result = L2CAP_CR_PEND;
2118 status = L2CAP_CS_AUTHOR_PEND;
2119 parent->sk_data_ready(parent, 0);
2120 } else {
2121 sk->sk_state = BT_CONFIG;
2122 result = L2CAP_CR_SUCCESS;
2123 status = L2CAP_CS_NO_INFO;
2124 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002125 } else {
2126 sk->sk_state = BT_CONNECT2;
2127 result = L2CAP_CR_PEND;
2128 status = L2CAP_CS_AUTHEN_PEND;
2129 }
2130 } else {
2131 sk->sk_state = BT_CONNECT2;
2132 result = L2CAP_CR_PEND;
2133 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 }
2135
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002136 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137
2138response:
2139 bh_unlock_sock(parent);
2140
2141sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002142 rsp.scid = cpu_to_le16(scid);
2143 rsp.dcid = cpu_to_le16(dcid);
2144 rsp.result = cpu_to_le16(result);
2145 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002147
2148 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2149 struct l2cap_info_req info;
2150 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2151
2152 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2153 conn->info_ident = l2cap_get_ident(conn);
2154
2155 mod_timer(&conn->info_timer, jiffies +
2156 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2157
2158 l2cap_send_cmd(conn, conn->info_ident,
2159 L2CAP_INFO_REQ, sizeof(info), &info);
2160 }
2161
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002162 if (chan && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002163 result == L2CAP_CR_SUCCESS) {
2164 u8 buf[128];
2165 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2166 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002167 l2cap_build_conf_req(chan, buf), buf);
2168 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002169 }
2170
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 return 0;
2172}
2173
2174static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2175{
2176 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2177 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002178 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 struct sock *sk;
2180 u8 req[128];
2181
2182 scid = __le16_to_cpu(rsp->scid);
2183 dcid = __le16_to_cpu(rsp->dcid);
2184 result = __le16_to_cpu(rsp->result);
2185 status = __le16_to_cpu(rsp->status);
2186
2187 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2188
2189 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002190 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002191 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002192 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002194 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002195 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002196 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197 }
2198
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002199 sk = chan->sk;
2200
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201 switch (result) {
2202 case L2CAP_CR_SUCCESS:
2203 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002204 chan->ident = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002206 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2207
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002208 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2209 break;
2210
2211 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2212
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002214 l2cap_build_conf_req(chan, req), req);
2215 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 break;
2217
2218 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002219 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 break;
2221
2222 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002223 /* don't delete l2cap channel if sk is owned by user */
2224 if (sock_owned_by_user(sk)) {
2225 sk->sk_state = BT_DISCONN;
2226 l2cap_sock_clear_timer(sk);
2227 l2cap_sock_set_timer(sk, HZ / 5);
2228 break;
2229 }
2230
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002231 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232 break;
2233 }
2234
2235 bh_unlock_sock(sk);
2236 return 0;
2237}
2238
Mat Martineau8c462b62010-08-24 15:35:42 -07002239static inline void set_default_fcs(struct l2cap_pinfo *pi)
2240{
2241 /* FCS is enabled only in ERTM or streaming mode, if one or both
2242 * sides request it.
2243 */
2244 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2245 pi->fcs = L2CAP_FCS_NONE;
2246 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2247 pi->fcs = L2CAP_FCS_CRC16;
2248}
2249
Al Viro88219a02007-07-29 00:17:25 -07002250static 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 -07002251{
2252 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2253 u16 dcid, flags;
2254 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002255 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002257 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258
2259 dcid = __le16_to_cpu(req->dcid);
2260 flags = __le16_to_cpu(req->flags);
2261
2262 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2263
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002264 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002265 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 return -ENOENT;
2267
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002268 sk = chan->sk;
2269
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002270 if (sk->sk_state != BT_CONFIG) {
2271 struct l2cap_cmd_rej rej;
2272
2273 rej.reason = cpu_to_le16(0x0002);
2274 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2275 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002276 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002277 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002278
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002279 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002280 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002281 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002282 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2283 l2cap_build_conf_rsp(sk, rsp,
2284 L2CAP_CONF_REJECT, flags), rsp);
2285 goto unlock;
2286 }
2287
2288 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002289 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2290 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291
2292 if (flags & 0x0001) {
2293 /* Incomplete config. Send empty response. */
2294 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002295 l2cap_build_conf_rsp(sk, rsp,
2296 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 goto unlock;
2298 }
2299
2300 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002301 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002302 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002303 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002305 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002307 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002308 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002309
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002310 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002311 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002312
Marcel Holtmann876d9482007-10-20 13:35:42 +02002313 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2314 goto unlock;
2315
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002317 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002318
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002320
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002321 chan->next_tx_seq = 0;
2322 chan->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002323 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002324 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002325 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002326
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002328 goto unlock;
2329 }
2330
2331 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002332 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002333 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002335 l2cap_build_conf_req(chan, buf), buf);
2336 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 }
2338
2339unlock:
2340 bh_unlock_sock(sk);
2341 return 0;
2342}
2343
2344static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2345{
2346 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2347 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002348 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002350 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351
2352 scid = __le16_to_cpu(rsp->scid);
2353 flags = __le16_to_cpu(rsp->flags);
2354 result = __le16_to_cpu(rsp->result);
2355
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002356 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2357 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002359 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002360 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 return 0;
2362
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002363 sk = chan->sk;
2364
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 switch (result) {
2366 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002367 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368 break;
2369
2370 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002371 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002372 char req[64];
2373
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002374 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002375 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002376 goto done;
2377 }
2378
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002379 /* throw out any old stored conf requests */
2380 result = L2CAP_CONF_SUCCESS;
2381 len = l2cap_parse_conf_rsp(sk, rsp->data,
2382 len, req, &result);
2383 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002384 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002385 goto done;
2386 }
2387
2388 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2389 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002390 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002391 if (result != L2CAP_CONF_SUCCESS)
2392 goto done;
2393 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394 }
2395
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002396 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002397 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002399 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 goto done;
2401 }
2402
2403 if (flags & 0x01)
2404 goto done;
2405
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2407
2408 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002409 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002410
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002412 chan->next_tx_seq = 0;
2413 chan->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002414 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002415 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002416 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002417
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418 l2cap_chan_ready(sk);
2419 }
2420
2421done:
2422 bh_unlock_sock(sk);
2423 return 0;
2424}
2425
2426static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2427{
2428 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2429 struct l2cap_disconn_rsp rsp;
2430 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002431 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 struct sock *sk;
2433
2434 scid = __le16_to_cpu(req->scid);
2435 dcid = __le16_to_cpu(req->dcid);
2436
2437 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2438
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002439 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002440 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441 return 0;
2442
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002443 sk = chan->sk;
2444
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002445 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2446 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2448
2449 sk->sk_shutdown = SHUTDOWN_MASK;
2450
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002451 /* don't delete l2cap channel if sk is owned by user */
2452 if (sock_owned_by_user(sk)) {
2453 sk->sk_state = BT_DISCONN;
2454 l2cap_sock_clear_timer(sk);
2455 l2cap_sock_set_timer(sk, HZ / 5);
2456 bh_unlock_sock(sk);
2457 return 0;
2458 }
2459
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002460 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461 bh_unlock_sock(sk);
2462
2463 l2cap_sock_kill(sk);
2464 return 0;
2465}
2466
2467static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2468{
2469 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2470 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002471 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472 struct sock *sk;
2473
2474 scid = __le16_to_cpu(rsp->scid);
2475 dcid = __le16_to_cpu(rsp->dcid);
2476
2477 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2478
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002479 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002480 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481 return 0;
2482
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002483 sk = chan->sk;
2484
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002485 /* don't delete l2cap channel if sk is owned by user */
2486 if (sock_owned_by_user(sk)) {
2487 sk->sk_state = BT_DISCONN;
2488 l2cap_sock_clear_timer(sk);
2489 l2cap_sock_set_timer(sk, HZ / 5);
2490 bh_unlock_sock(sk);
2491 return 0;
2492 }
2493
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002494 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495 bh_unlock_sock(sk);
2496
2497 l2cap_sock_kill(sk);
2498 return 0;
2499}
2500
2501static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2502{
2503 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504 u16 type;
2505
2506 type = __le16_to_cpu(req->type);
2507
2508 BT_DBG("type 0x%4.4x", type);
2509
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002510 if (type == L2CAP_IT_FEAT_MASK) {
2511 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002512 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002513 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2514 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2515 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002516 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002517 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2518 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002519 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002520 l2cap_send_cmd(conn, cmd->ident,
2521 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002522 } else if (type == L2CAP_IT_FIXED_CHAN) {
2523 u8 buf[12];
2524 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2525 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2526 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2527 memcpy(buf + 4, l2cap_fixed_chan, 8);
2528 l2cap_send_cmd(conn, cmd->ident,
2529 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002530 } else {
2531 struct l2cap_info_rsp rsp;
2532 rsp.type = cpu_to_le16(type);
2533 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2534 l2cap_send_cmd(conn, cmd->ident,
2535 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2536 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537
2538 return 0;
2539}
2540
2541static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2542{
2543 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2544 u16 type, result;
2545
2546 type = __le16_to_cpu(rsp->type);
2547 result = __le16_to_cpu(rsp->result);
2548
2549 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2550
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002551 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2552 if (cmd->ident != conn->info_ident ||
2553 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2554 return 0;
2555
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002556 del_timer(&conn->info_timer);
2557
Ville Tervoadb08ed2010-08-04 09:43:33 +03002558 if (result != L2CAP_IR_SUCCESS) {
2559 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2560 conn->info_ident = 0;
2561
2562 l2cap_conn_start(conn);
2563
2564 return 0;
2565 }
2566
Marcel Holtmann984947d2009-02-06 23:35:19 +01002567 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002568 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002569
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002570 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002571 struct l2cap_info_req req;
2572 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2573
2574 conn->info_ident = l2cap_get_ident(conn);
2575
2576 l2cap_send_cmd(conn, conn->info_ident,
2577 L2CAP_INFO_REQ, sizeof(req), &req);
2578 } else {
2579 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2580 conn->info_ident = 0;
2581
2582 l2cap_conn_start(conn);
2583 }
2584 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002585 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002586 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002587
2588 l2cap_conn_start(conn);
2589 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002590
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591 return 0;
2592}
2593
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002594static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002595 u16 to_multiplier)
2596{
2597 u16 max_latency;
2598
2599 if (min > max || min < 6 || max > 3200)
2600 return -EINVAL;
2601
2602 if (to_multiplier < 10 || to_multiplier > 3200)
2603 return -EINVAL;
2604
2605 if (max >= to_multiplier * 8)
2606 return -EINVAL;
2607
2608 max_latency = (to_multiplier * 8 / max) - 1;
2609 if (latency > 499 || latency > max_latency)
2610 return -EINVAL;
2611
2612 return 0;
2613}
2614
2615static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2616 struct l2cap_cmd_hdr *cmd, u8 *data)
2617{
2618 struct hci_conn *hcon = conn->hcon;
2619 struct l2cap_conn_param_update_req *req;
2620 struct l2cap_conn_param_update_rsp rsp;
2621 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002622 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002623
2624 if (!(hcon->link_mode & HCI_LM_MASTER))
2625 return -EINVAL;
2626
2627 cmd_len = __le16_to_cpu(cmd->len);
2628 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2629 return -EPROTO;
2630
2631 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002632 min = __le16_to_cpu(req->min);
2633 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002634 latency = __le16_to_cpu(req->latency);
2635 to_multiplier = __le16_to_cpu(req->to_multiplier);
2636
2637 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2638 min, max, latency, to_multiplier);
2639
2640 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002641
2642 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2643 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002644 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2645 else
2646 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2647
2648 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2649 sizeof(rsp), &rsp);
2650
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002651 if (!err)
2652 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2653
Claudio Takahaside731152011-02-11 19:28:55 -02002654 return 0;
2655}
2656
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002657static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2658 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2659{
2660 int err = 0;
2661
2662 switch (cmd->code) {
2663 case L2CAP_COMMAND_REJ:
2664 l2cap_command_rej(conn, cmd, data);
2665 break;
2666
2667 case L2CAP_CONN_REQ:
2668 err = l2cap_connect_req(conn, cmd, data);
2669 break;
2670
2671 case L2CAP_CONN_RSP:
2672 err = l2cap_connect_rsp(conn, cmd, data);
2673 break;
2674
2675 case L2CAP_CONF_REQ:
2676 err = l2cap_config_req(conn, cmd, cmd_len, data);
2677 break;
2678
2679 case L2CAP_CONF_RSP:
2680 err = l2cap_config_rsp(conn, cmd, data);
2681 break;
2682
2683 case L2CAP_DISCONN_REQ:
2684 err = l2cap_disconnect_req(conn, cmd, data);
2685 break;
2686
2687 case L2CAP_DISCONN_RSP:
2688 err = l2cap_disconnect_rsp(conn, cmd, data);
2689 break;
2690
2691 case L2CAP_ECHO_REQ:
2692 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2693 break;
2694
2695 case L2CAP_ECHO_RSP:
2696 break;
2697
2698 case L2CAP_INFO_REQ:
2699 err = l2cap_information_req(conn, cmd, data);
2700 break;
2701
2702 case L2CAP_INFO_RSP:
2703 err = l2cap_information_rsp(conn, cmd, data);
2704 break;
2705
2706 default:
2707 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2708 err = -EINVAL;
2709 break;
2710 }
2711
2712 return err;
2713}
2714
2715static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2716 struct l2cap_cmd_hdr *cmd, u8 *data)
2717{
2718 switch (cmd->code) {
2719 case L2CAP_COMMAND_REJ:
2720 return 0;
2721
2722 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002723 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002724
2725 case L2CAP_CONN_PARAM_UPDATE_RSP:
2726 return 0;
2727
2728 default:
2729 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2730 return -EINVAL;
2731 }
2732}
2733
2734static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2735 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736{
2737 u8 *data = skb->data;
2738 int len = skb->len;
2739 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002740 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741
2742 l2cap_raw_recv(conn, skb);
2743
2744 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002745 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2747 data += L2CAP_CMD_HDR_SIZE;
2748 len -= L2CAP_CMD_HDR_SIZE;
2749
Al Viro88219a02007-07-29 00:17:25 -07002750 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751
Al Viro88219a02007-07-29 00:17:25 -07002752 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 -07002753
Al Viro88219a02007-07-29 00:17:25 -07002754 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755 BT_DBG("corrupted command");
2756 break;
2757 }
2758
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002759 if (conn->hcon->type == LE_LINK)
2760 err = l2cap_le_sig_cmd(conn, &cmd, data);
2761 else
2762 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763
2764 if (err) {
2765 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002766
2767 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768
2769 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002770 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2772 }
2773
Al Viro88219a02007-07-29 00:17:25 -07002774 data += cmd_len;
2775 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776 }
2777
2778 kfree_skb(skb);
2779}
2780
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002781static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2782{
2783 u16 our_fcs, rcv_fcs;
2784 int hdr_size = L2CAP_HDR_SIZE + 2;
2785
2786 if (pi->fcs == L2CAP_FCS_CRC16) {
2787 skb_trim(skb, skb->len - 2);
2788 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2789 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2790
2791 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002792 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002793 }
2794 return 0;
2795}
2796
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002797static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002798{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002799 u16 control = 0;
2800
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002801 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002802
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002803 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002804
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002805 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002806 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002807 l2cap_send_sframe(chan, control);
2808 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002809 }
2810
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002811 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2812 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002813
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002814 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002815
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002816 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002817 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002818 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002819 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002820 }
2821}
2822
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002823static 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 -03002824{
2825 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002826 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002827
2828 bt_cb(skb)->tx_seq = tx_seq;
2829 bt_cb(skb)->sar = sar;
2830
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002831 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002832 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002833 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002834 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002835 }
2836
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002837 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002838 if (tx_seq_offset < 0)
2839 tx_seq_offset += 64;
2840
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002841 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002842 if (bt_cb(next_skb)->tx_seq == tx_seq)
2843 return -EINVAL;
2844
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002845 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002846 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002847 if (next_tx_seq_offset < 0)
2848 next_tx_seq_offset += 64;
2849
2850 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002851 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002852 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002853 }
2854
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002855 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002856 break;
2857
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002858 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002859
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002860 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002861
2862 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002863}
2864
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002865static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002866{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002867 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002868 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002869 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002870
2871 switch (control & L2CAP_CTRL_SAR) {
2872 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002873 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002874 goto drop;
2875
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002876 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002877 if (!err)
2878 return err;
2879
2880 break;
2881
2882 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002883 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002884 goto drop;
2885
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002886 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002887
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002888 if (chan->sdu_len > pi->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002889 goto disconnect;
2890
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002891 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
2892 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002893 return -ENOMEM;
2894
2895 /* pull sdu_len bytes only after alloc, because of Local Busy
2896 * condition we have to be sure that this will be executed
2897 * only once, i.e., when alloc does not fail */
2898 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002899
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002900 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002901
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002902 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002903 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002904 break;
2905
2906 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002907 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002908 goto disconnect;
2909
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002910 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002911 goto disconnect;
2912
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002913 chan->partial_sdu_len += skb->len;
2914 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002915 goto drop;
2916
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002917 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002918
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002919 break;
2920
2921 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002922 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002923 goto disconnect;
2924
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002925 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002926 goto disconnect;
2927
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002928 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002929 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002930
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002931 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002932 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002933
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002934 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002935 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002936
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002937 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002938 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002939
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002940 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002941 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002942 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002943 return -ENOMEM;
2944 }
2945
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002946 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002947 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002948 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002949 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002950 return err;
2951 }
2952
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002953 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2954 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002955
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002956 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002957 break;
2958 }
2959
2960 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002961 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002962
2963drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002964 kfree_skb(chan->sdu);
2965 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002966
2967disconnect:
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002968 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002969 kfree_skb(skb);
2970 return 0;
2971}
2972
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002973static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002974{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002975 struct sock *sk = chan->sk;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002976 struct sk_buff *skb;
2977 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002978 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002979
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002980 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002981 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002982 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002983 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002984 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002985 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002986 }
2987
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002988 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002989 }
2990
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002991 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002992 goto done;
2993
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002994 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002995 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002996 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002997 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002998
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002999 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003000 __mod_monitor_timer();
3001
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003002 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003003
3004done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003005 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3006 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003007
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003008 BT_DBG("sk %p, Exit local busy", sk);
3009
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003010 return 0;
3011}
3012
3013static void l2cap_busy_work(struct work_struct *work)
3014{
3015 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003016 struct l2cap_chan *chan =
3017 container_of(work, struct l2cap_chan, busy_work);
3018 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003019 int n_tries = 0, timeo = HZ/5, err;
3020 struct sk_buff *skb;
3021
3022 lock_sock(sk);
3023
3024 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003025 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003026 set_current_state(TASK_INTERRUPTIBLE);
3027
3028 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3029 err = -EBUSY;
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003030 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003031 break;
3032 }
3033
3034 if (!timeo)
3035 timeo = HZ/5;
3036
3037 if (signal_pending(current)) {
3038 err = sock_intr_errno(timeo);
3039 break;
3040 }
3041
3042 release_sock(sk);
3043 timeo = schedule_timeout(timeo);
3044 lock_sock(sk);
3045
3046 err = sock_error(sk);
3047 if (err)
3048 break;
3049
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003050 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003051 break;
3052 }
3053
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003054 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003055 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003056
3057 release_sock(sk);
3058}
3059
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003060static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003061{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003062 int sctrl, err;
3063
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003064 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003065 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003066 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003067 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003068
3069
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003070 }
3071
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003072 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003073 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003074 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003075 return err;
3076 }
3077
3078 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003079 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003080
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003081 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003082 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003083 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003084
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003085 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003086 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003087 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003088
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003089 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003090
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003091 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003092
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003093 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003094
3095 return err;
3096}
3097
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003098static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003099{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003100 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003101 struct sk_buff *_skb;
3102 int err = -EINVAL;
3103
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003104 /*
3105 * TODO: We have to notify the userland if some data is lost with the
3106 * Streaming Mode.
3107 */
3108
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003109 switch (control & L2CAP_CTRL_SAR) {
3110 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003111 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003112 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003113 break;
3114 }
3115
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003116 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003117 if (!err)
3118 return 0;
3119
3120 break;
3121
3122 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003123 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003124 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003125 break;
3126 }
3127
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003128 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003129 skb_pull(skb, 2);
3130
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003131 if (chan->sdu_len > pi->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003132 err = -EMSGSIZE;
3133 break;
3134 }
3135
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003136 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3137 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003138 err = -ENOMEM;
3139 break;
3140 }
3141
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003142 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003143
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003144 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003145 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003146 err = 0;
3147 break;
3148
3149 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003150 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003151 break;
3152
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003153 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003154
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003155 chan->partial_sdu_len += skb->len;
3156 if (chan->partial_sdu_len > chan->sdu_len)
3157 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003158 else
3159 err = 0;
3160
3161 break;
3162
3163 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003164 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003165 break;
3166
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003167 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003168
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003169 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003170 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003171
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003172 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003173 goto drop;
3174
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003175 if (chan->partial_sdu_len == chan->sdu_len) {
3176 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003177 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003178 if (err < 0)
3179 kfree_skb(_skb);
3180 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003181 err = 0;
3182
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003183drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003184 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003185 break;
3186 }
3187
3188 kfree_skb(skb);
3189 return err;
3190}
3191
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003192static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003193{
3194 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003195 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003196
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003197 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003198 if (bt_cb(skb)->tx_seq != tx_seq)
3199 break;
3200
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003201 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003202 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003203 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003204 chan->buffer_seq_srej =
3205 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003206 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003207 }
3208}
3209
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003210static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003211{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003212 struct srej_list *l, *tmp;
3213 u16 control;
3214
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003215 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003216 if (l->tx_seq == tx_seq) {
3217 list_del(&l->list);
3218 kfree(l);
3219 return;
3220 }
3221 control = L2CAP_SUPER_SELECT_REJECT;
3222 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003223 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003224 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003225 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003226 }
3227}
3228
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003229static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003230{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003231 struct srej_list *new;
3232 u16 control;
3233
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003234 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003235 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003236 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003237 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003238
3239 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003240 new->tx_seq = chan->expected_tx_seq;
3241 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003242 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003243 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003244 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003245}
3246
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003247static 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 -03003248{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003249 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003250 struct l2cap_pinfo *pi = l2cap_pi(sk);
3251 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003252 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003253 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003254 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003255 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003256 int err = 0;
3257
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003258 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3259 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003260
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003261 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003262 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003263 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003264 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003265 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003266 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003267 }
3268
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003269 chan->expected_ack_seq = req_seq;
3270 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003271
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003272 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003273 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003274
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003275 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003276 if (tx_seq_offset < 0)
3277 tx_seq_offset += 64;
3278
3279 /* invalid tx_seq */
3280 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003281 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003282 goto drop;
3283 }
3284
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003285 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003286 goto drop;
3287
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003288 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003289 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003290
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003291 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003292 struct srej_list, list);
3293 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003294 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003295 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003296
3297 list_del(&first->list);
3298 kfree(first);
3299
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003300 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003301 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003302 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3303 l2cap_send_ack(chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003304 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003305 }
3306 } else {
3307 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003308
3309 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003310 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003311 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003312
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003313 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003314 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003315 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003316 return 0;
3317 }
3318 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003319 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003320 }
3321 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003322 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003323 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003324 if (expected_tx_seq_offset < 0)
3325 expected_tx_seq_offset += 64;
3326
3327 /* duplicated tx_seq */
3328 if (tx_seq_offset < expected_tx_seq_offset)
3329 goto drop;
3330
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003331 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003332
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003333 BT_DBG("sk %p, Enter SREJ", sk);
3334
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003335 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003336 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003337
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003338 __skb_queue_head_init(&chan->srej_q);
3339 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003340 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003341
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003342 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003343
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003344 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003345
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003346 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003347 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003348 return 0;
3349
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003350expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003351 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003352
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003353 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003354 bt_cb(skb)->tx_seq = tx_seq;
3355 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003356 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003357 return 0;
3358 }
3359
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003360 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003361 if (err < 0)
3362 return 0;
3363
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003364 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003365 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3366 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003367 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003368 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003369 }
3370
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003371 __mod_ack_timer();
3372
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003373 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3374 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003375 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003376
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003377 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003378
3379drop:
3380 kfree_skb(skb);
3381 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003382}
3383
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003384static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003385{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003386 struct sock *sk = chan->sk;
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003387
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003388 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3389 rx_control);
3390
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003391 chan->expected_ack_seq = __get_reqseq(rx_control);
3392 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003393
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003394 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003395 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3396 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3397 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003398 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003399 __mod_retrans_timer();
3400
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003401 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3402 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003403 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003404 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003405 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003406
3407 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003408 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003409
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003410 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3411 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003412 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003413 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003414
3415 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003416 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003417 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003418 __mod_retrans_timer();
3419
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003420 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3421 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3422 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003423 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003424 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003425 }
3426}
3427
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003428static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003429{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003430 u8 tx_seq = __get_reqseq(rx_control);
3431
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003432 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003433
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003434 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003435
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003436 chan->expected_ack_seq = tx_seq;
3437 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003438
3439 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003440 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3441 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003442 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003443 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003444 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003445 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003446
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003447 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3448 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003449 }
3450}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003451static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003452{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003453 u8 tx_seq = __get_reqseq(rx_control);
3454
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003455 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003456
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003457 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003458
3459 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003460 chan->expected_ack_seq = tx_seq;
3461 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003462
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003463 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3464 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003465
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003466 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003467
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003468 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003469 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003470 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003471 }
3472 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003473 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
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 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003477 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003478 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003479 l2cap_retransmit_one_frame(chan, tx_seq);
3480 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003481 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003482 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003483 }
3484 }
3485}
3486
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003487static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003488{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003489 u8 tx_seq = __get_reqseq(rx_control);
3490
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003491 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003492
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003493 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003494 chan->expected_ack_seq = tx_seq;
3495 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003496
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003497 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003498 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003499
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003500 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003501 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003502 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003503 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003504 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003505 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003506
3507 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003508 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003509 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003510 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003511}
3512
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003513static 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 -03003514{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003515 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003516
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003517 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003518 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003519 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003520 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003521 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003522 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003523 }
3524
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003525 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3526 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003527 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003528 break;
3529
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003530 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003531 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003532 break;
3533
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003534 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003535 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003536 break;
3537
3538 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003539 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003540 break;
3541 }
3542
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003543 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003544 return 0;
3545}
3546
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003547static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3548{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003549 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003550 struct l2cap_pinfo *pi = l2cap_pi(sk);
3551 u16 control;
3552 u8 req_seq;
3553 int len, next_tx_seq_offset, req_seq_offset;
3554
3555 control = get_unaligned_le16(skb->data);
3556 skb_pull(skb, 2);
3557 len = skb->len;
3558
3559 /*
3560 * We can just drop the corrupted I-frame here.
3561 * Receiver will miss it and start proper recovery
3562 * procedures and ask retransmission.
3563 */
3564 if (l2cap_check_fcs(pi, skb))
3565 goto drop;
3566
3567 if (__is_sar_start(control) && __is_iframe(control))
3568 len -= 2;
3569
3570 if (pi->fcs == L2CAP_FCS_CRC16)
3571 len -= 2;
3572
3573 if (len > pi->mps) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003574 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003575 goto drop;
3576 }
3577
3578 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003579 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003580 if (req_seq_offset < 0)
3581 req_seq_offset += 64;
3582
3583 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003584 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003585 if (next_tx_seq_offset < 0)
3586 next_tx_seq_offset += 64;
3587
3588 /* check for invalid req-seq */
3589 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003590 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003591 goto drop;
3592 }
3593
3594 if (__is_iframe(control)) {
3595 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003596 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003597 goto drop;
3598 }
3599
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003600 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003601 } else {
3602 if (len != 0) {
3603 BT_ERR("%d", len);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003604 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003605 goto drop;
3606 }
3607
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003608 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003609 }
3610
3611 return 0;
3612
3613drop:
3614 kfree_skb(skb);
3615 return 0;
3616}
3617
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3619{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003620 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003622 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003623 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003624 u8 tx_seq;
3625 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003627 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003628 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629 BT_DBG("unknown cid 0x%4.4x", cid);
3630 goto drop;
3631 }
3632
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003633 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003634 pi = l2cap_pi(sk);
3635
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636 BT_DBG("sk %p, len %d", sk, skb->len);
3637
3638 if (sk->sk_state != BT_CONNECTED)
3639 goto drop;
3640
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003641 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003642 case L2CAP_MODE_BASIC:
3643 /* If socket recv buffers overflows we drop data here
3644 * which is *bad* because L2CAP has to be reliable.
3645 * But we don't have any other choice. L2CAP doesn't
3646 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003648 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003649 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003651 if (!sock_queue_rcv_skb(sk, skb))
3652 goto done;
3653 break;
3654
3655 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003656 if (!sock_owned_by_user(sk)) {
3657 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003658 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003659 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003660 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003661 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003662
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003663 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003664
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003665 case L2CAP_MODE_STREAMING:
3666 control = get_unaligned_le16(skb->data);
3667 skb_pull(skb, 2);
3668 len = skb->len;
3669
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003670 if (l2cap_check_fcs(pi, skb))
3671 goto drop;
3672
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003673 if (__is_sar_start(control))
3674 len -= 2;
3675
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003676 if (pi->fcs == L2CAP_FCS_CRC16)
3677 len -= 2;
3678
Nathan Holstein51893f82010-06-09 15:46:25 -04003679 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003680 goto drop;
3681
3682 tx_seq = __get_txseq(control);
3683
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003684 if (chan->expected_tx_seq == tx_seq)
3685 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003686 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003687 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003688
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003689 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003690
3691 goto done;
3692
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003693 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003694 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003695 break;
3696 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697
3698drop:
3699 kfree_skb(skb);
3700
3701done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003702 if (sk)
3703 bh_unlock_sock(sk);
3704
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705 return 0;
3706}
3707
Al Viro8e036fc2007-07-29 00:16:36 -07003708static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709{
3710 struct sock *sk;
3711
3712 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3713 if (!sk)
3714 goto drop;
3715
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003716 bh_lock_sock(sk);
3717
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718 BT_DBG("sk %p, len %d", sk, skb->len);
3719
3720 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3721 goto drop;
3722
3723 if (l2cap_pi(sk)->imtu < skb->len)
3724 goto drop;
3725
3726 if (!sock_queue_rcv_skb(sk, skb))
3727 goto done;
3728
3729drop:
3730 kfree_skb(skb);
3731
3732done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003733 if (sk)
3734 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735 return 0;
3736}
3737
3738static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3739{
3740 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003741 u16 cid, len;
3742 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743
3744 skb_pull(skb, L2CAP_HDR_SIZE);
3745 cid = __le16_to_cpu(lh->cid);
3746 len = __le16_to_cpu(lh->len);
3747
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003748 if (len != skb->len) {
3749 kfree_skb(skb);
3750 return;
3751 }
3752
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3754
3755 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003756 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003757 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758 l2cap_sig_channel(conn, skb);
3759 break;
3760
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003761 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003762 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763 skb_pull(skb, 2);
3764 l2cap_conless_channel(conn, psm, skb);
3765 break;
3766
3767 default:
3768 l2cap_data_channel(conn, cid, skb);
3769 break;
3770 }
3771}
3772
3773/* ---- L2CAP interface with lower layer (HCI) ---- */
3774
3775static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3776{
3777 int exact = 0, lm1 = 0, lm2 = 0;
3778 register struct sock *sk;
3779 struct hlist_node *node;
3780
3781 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003782 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003783
3784 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3785
3786 /* Find listening sockets and check their link_mode */
3787 read_lock(&l2cap_sk_list.lock);
3788 sk_for_each(sk, node, &l2cap_sk_list.head) {
3789 if (sk->sk_state != BT_LISTEN)
3790 continue;
3791
3792 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003793 lm1 |= HCI_LM_ACCEPT;
3794 if (l2cap_pi(sk)->role_switch)
3795 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003797 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3798 lm2 |= HCI_LM_ACCEPT;
3799 if (l2cap_pi(sk)->role_switch)
3800 lm2 |= HCI_LM_MASTER;
3801 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802 }
3803 read_unlock(&l2cap_sk_list.lock);
3804
3805 return exact ? lm1 : lm2;
3806}
3807
3808static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3809{
Marcel Holtmann01394182006-07-03 10:02:46 +02003810 struct l2cap_conn *conn;
3811
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3813
Ville Tervoacd7d372011-02-10 22:38:49 -03003814 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003815 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816
3817 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003818 conn = l2cap_conn_add(hcon, status);
3819 if (conn)
3820 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003821 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822 l2cap_conn_del(hcon, bt_err(status));
3823
3824 return 0;
3825}
3826
Marcel Holtmann2950f212009-02-12 14:02:50 +01003827static int l2cap_disconn_ind(struct hci_conn *hcon)
3828{
3829 struct l2cap_conn *conn = hcon->l2cap_data;
3830
3831 BT_DBG("hcon %p", hcon);
3832
3833 if (hcon->type != ACL_LINK || !conn)
3834 return 0x13;
3835
3836 return conn->disc_reason;
3837}
3838
3839static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840{
3841 BT_DBG("hcon %p reason %d", hcon, reason);
3842
Ville Tervoacd7d372011-02-10 22:38:49 -03003843 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003844 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845
3846 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003847
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848 return 0;
3849}
3850
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003851static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3852{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003853 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003854 return;
3855
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003856 if (encrypt == 0x00) {
3857 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3858 l2cap_sock_clear_timer(sk);
3859 l2cap_sock_set_timer(sk, HZ * 5);
3860 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3861 __l2cap_sock_close(sk, ECONNREFUSED);
3862 } else {
3863 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3864 l2cap_sock_clear_timer(sk);
3865 }
3866}
3867
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003868static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003870 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003871 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872
Marcel Holtmann01394182006-07-03 10:02:46 +02003873 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003875
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876 BT_DBG("conn %p", conn);
3877
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003878 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003880 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003881 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003882
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883 bh_lock_sock(sk);
3884
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003885 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3886 bh_unlock_sock(sk);
3887 continue;
3888 }
3889
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003890 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003891 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003892 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003893 bh_unlock_sock(sk);
3894 continue;
3895 }
3896
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003897 if (sk->sk_state == BT_CONNECT) {
3898 if (!status) {
3899 struct l2cap_conn_req req;
3900 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3901 req.psm = l2cap_pi(sk)->psm;
3902
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003903 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003904 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003905
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003906 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003907 L2CAP_CONN_REQ, sizeof(req), &req);
3908 } else {
3909 l2cap_sock_clear_timer(sk);
3910 l2cap_sock_set_timer(sk, HZ / 10);
3911 }
3912 } else if (sk->sk_state == BT_CONNECT2) {
3913 struct l2cap_conn_rsp rsp;
3914 __u16 result;
3915
3916 if (!status) {
3917 sk->sk_state = BT_CONFIG;
3918 result = L2CAP_CR_SUCCESS;
3919 } else {
3920 sk->sk_state = BT_DISCONN;
3921 l2cap_sock_set_timer(sk, HZ / 10);
3922 result = L2CAP_CR_SEC_BLOCK;
3923 }
3924
3925 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3926 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3927 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003928 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003929 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
3930 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931 }
3932
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933 bh_unlock_sock(sk);
3934 }
3935
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003936 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003937
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938 return 0;
3939}
3940
3941static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3942{
3943 struct l2cap_conn *conn = hcon->l2cap_data;
3944
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003945 if (!conn)
3946 conn = l2cap_conn_add(hcon, 0);
3947
3948 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 goto drop;
3950
3951 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3952
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003953 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003955 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003956 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957 int len;
3958
3959 if (conn->rx_len) {
3960 BT_ERR("Unexpected start frame (len %d)", skb->len);
3961 kfree_skb(conn->rx_skb);
3962 conn->rx_skb = NULL;
3963 conn->rx_len = 0;
3964 l2cap_conn_unreliable(conn, ECOMM);
3965 }
3966
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003967 /* Start fragment always begin with Basic L2CAP header */
3968 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969 BT_ERR("Frame is too short (len %d)", skb->len);
3970 l2cap_conn_unreliable(conn, ECOMM);
3971 goto drop;
3972 }
3973
3974 hdr = (struct l2cap_hdr *) skb->data;
3975 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003976 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977
3978 if (len == skb->len) {
3979 /* Complete frame received */
3980 l2cap_recv_frame(conn, skb);
3981 return 0;
3982 }
3983
3984 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3985
3986 if (skb->len > len) {
3987 BT_ERR("Frame is too long (len %d, expected len %d)",
3988 skb->len, len);
3989 l2cap_conn_unreliable(conn, ECOMM);
3990 goto drop;
3991 }
3992
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003993 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003994
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003995 if (chan && chan->sk) {
3996 struct sock *sk = chan->sk;
3997
3998 if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
3999 BT_ERR("Frame exceeding recv MTU (len %d, "
4000 "MTU %d)", len,
4001 l2cap_pi(sk)->imtu);
4002 bh_unlock_sock(sk);
4003 l2cap_conn_unreliable(conn, ECOMM);
4004 goto drop;
4005 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004006 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004007 }
4008
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004010 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4011 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012 goto drop;
4013
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004014 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004015 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016 conn->rx_len = len - skb->len;
4017 } else {
4018 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4019
4020 if (!conn->rx_len) {
4021 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4022 l2cap_conn_unreliable(conn, ECOMM);
4023 goto drop;
4024 }
4025
4026 if (skb->len > conn->rx_len) {
4027 BT_ERR("Fragment is too long (len %d, expected %d)",
4028 skb->len, conn->rx_len);
4029 kfree_skb(conn->rx_skb);
4030 conn->rx_skb = NULL;
4031 conn->rx_len = 0;
4032 l2cap_conn_unreliable(conn, ECOMM);
4033 goto drop;
4034 }
4035
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004036 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004037 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004038 conn->rx_len -= skb->len;
4039
4040 if (!conn->rx_len) {
4041 /* Complete frame received */
4042 l2cap_recv_frame(conn, conn->rx_skb);
4043 conn->rx_skb = NULL;
4044 }
4045 }
4046
4047drop:
4048 kfree_skb(skb);
4049 return 0;
4050}
4051
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004052static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053{
4054 struct sock *sk;
4055 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056
4057 read_lock_bh(&l2cap_sk_list.lock);
4058
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004059 sk_for_each(sk, node, &l2cap_sk_list.head) {
4060 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004062 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 +01004063 batostr(&bt_sk(sk)->src),
4064 batostr(&bt_sk(sk)->dst),
4065 sk->sk_state, __le16_to_cpu(pi->psm),
4066 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004067 pi->imtu, pi->omtu, pi->sec_level,
4068 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004069 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004072
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004073 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074}
4075
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004076static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4077{
4078 return single_open(file, l2cap_debugfs_show, inode->i_private);
4079}
4080
4081static const struct file_operations l2cap_debugfs_fops = {
4082 .open = l2cap_debugfs_open,
4083 .read = seq_read,
4084 .llseek = seq_lseek,
4085 .release = single_release,
4086};
4087
4088static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090static struct hci_proto l2cap_hci_proto = {
4091 .name = "L2CAP",
4092 .id = HCI_PROTO_L2CAP,
4093 .connect_ind = l2cap_connect_ind,
4094 .connect_cfm = l2cap_connect_cfm,
4095 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004096 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004097 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098 .recv_acldata = l2cap_recv_acldata
4099};
4100
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004101int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102{
4103 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004104
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004105 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106 if (err < 0)
4107 return err;
4108
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004109 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004110 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004111 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112 goto error;
4113 }
4114
4115 err = hci_register_proto(&l2cap_hci_proto);
4116 if (err < 0) {
4117 BT_ERR("L2CAP protocol registration failed");
4118 bt_sock_unregister(BTPROTO_L2CAP);
4119 goto error;
4120 }
4121
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004122 if (bt_debugfs) {
4123 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4124 bt_debugfs, NULL, &l2cap_debugfs_fops);
4125 if (!l2cap_debugfs)
4126 BT_ERR("Failed to create L2CAP debug file");
4127 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129 return 0;
4130
4131error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004132 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004133 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134 return err;
4135}
4136
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004137void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004139 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004141 flush_workqueue(_busy_wq);
4142 destroy_workqueue(_busy_wq);
4143
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4145 BT_ERR("L2CAP protocol unregistration failed");
4146
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004147 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148}
4149
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004150module_param(disable_ertm, bool, 0644);
4151MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");