blob: 29742d875e60a1963462c05196b26131b1912933 [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. Padovan5d41ce12011-04-08 15:40:02 -0300152struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200153{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300154 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200155
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300156 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
157 if (!chan)
158 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200159
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300160 chan->sk = sk;
161
162 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200163}
164
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300165static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200166{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300167 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200168
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300169 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
170 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200171
Marcel Holtmann2950f212009-02-12 14:02:50 +0100172 conn->disc_reason = 0x13;
173
Marcel Holtmann01394182006-07-03 10:02:46 +0200174 l2cap_pi(sk)->conn = conn;
175
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300176 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Ville Tervob62f3282011-02-10 22:38:50 -0300177 if (conn->hcon->type == LE_LINK) {
178 /* LE connection */
179 l2cap_pi(sk)->omtu = L2CAP_LE_DEFAULT_MTU;
180 l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA;
181 l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA;
182 } else {
183 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300184 l2cap_pi(sk)->scid = l2cap_alloc_cid(conn);
Ville Tervob62f3282011-02-10 22:38:50 -0300185 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
186 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200187 } else if (sk->sk_type == SOCK_DGRAM) {
188 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300189 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
190 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200191 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
192 } else {
193 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300194 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
195 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200196 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
197 }
198
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300199 sock_hold(sk);
200
201 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200202}
203
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900204/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200205 * Must be called on the locked socket. */
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300206void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200207{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300208 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200209 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
210 struct sock *parent = bt_sk(sk)->parent;
211
212 l2cap_sock_clear_timer(sk);
213
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300214 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200215
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900216 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300217 /* Delete from channel list */
218 write_lock_bh(&conn->chan_lock);
219 list_del(&chan->list);
220 write_unlock_bh(&conn->chan_lock);
221 __sock_put(sk);
222
Marcel Holtmann01394182006-07-03 10:02:46 +0200223 l2cap_pi(sk)->conn = NULL;
224 hci_conn_put(conn->hcon);
225 }
226
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200227 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200228 sock_set_flag(sk, SOCK_ZAPPED);
229
230 if (err)
231 sk->sk_err = err;
232
233 if (parent) {
234 bt_accept_unlink(sk);
235 parent->sk_data_ready(parent, 0);
236 } else
237 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300238
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300239 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE &&
240 chan->conf_state & L2CAP_CONF_INPUT_DONE))
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300241 goto free;
242
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300243 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300244
245 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
246 struct srej_list *l, *tmp;
247
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300248 del_timer(&chan->retrans_timer);
249 del_timer(&chan->monitor_timer);
250 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300251
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300252 skb_queue_purge(&chan->srej_q);
253 skb_queue_purge(&chan->busy_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300254
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300255 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300256 list_del(&l->list);
257 kfree(l);
258 }
259 }
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300260
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300261free:
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300262 kfree(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200263}
264
Johan Hedberg8556edd32011-01-19 12:06:50 +0530265static inline u8 l2cap_get_auth_type(struct sock *sk)
266{
267 if (sk->sk_type == SOCK_RAW) {
268 switch (l2cap_pi(sk)->sec_level) {
269 case BT_SECURITY_HIGH:
270 return HCI_AT_DEDICATED_BONDING_MITM;
271 case BT_SECURITY_MEDIUM:
272 return HCI_AT_DEDICATED_BONDING;
273 default:
274 return HCI_AT_NO_BONDING;
275 }
276 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
277 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
278 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
279
280 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
281 return HCI_AT_NO_BONDING_MITM;
282 else
283 return HCI_AT_NO_BONDING;
284 } else {
285 switch (l2cap_pi(sk)->sec_level) {
286 case BT_SECURITY_HIGH:
287 return HCI_AT_GENERAL_BONDING_MITM;
288 case BT_SECURITY_MEDIUM:
289 return HCI_AT_GENERAL_BONDING;
290 default:
291 return HCI_AT_NO_BONDING;
292 }
293 }
294}
295
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200296/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100297static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200298{
299 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100300 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200301
Johan Hedberg8556edd32011-01-19 12:06:50 +0530302 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100303
304 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
305 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200306}
307
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200308u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200309{
310 u8 id;
311
312 /* Get next available identificator.
313 * 1 - 128 are used by kernel.
314 * 129 - 199 are reserved.
315 * 200 - 254 are used by utilities like l2ping, etc.
316 */
317
318 spin_lock_bh(&conn->lock);
319
320 if (++conn->tx_ident > 128)
321 conn->tx_ident = 1;
322
323 id = conn->tx_ident;
324
325 spin_unlock_bh(&conn->lock);
326
327 return id;
328}
329
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200330void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200331{
332 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200333 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200334
335 BT_DBG("code 0x%2.2x", code);
336
337 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300338 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200339
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200340 if (lmp_no_flush_capable(conn->hcon->hdev))
341 flags = ACL_START_NO_FLUSH;
342 else
343 flags = ACL_START;
344
345 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200346}
347
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300348static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300349{
350 struct sk_buff *skb;
351 struct l2cap_hdr *lh;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300352 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300353 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300354 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300355 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200356 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300357
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300358 if (sk->sk_state != BT_CONNECTED)
359 return;
360
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300361 if (pi->fcs == L2CAP_FCS_CRC16)
362 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300363
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300364 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300365
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300366 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300367 control |= L2CAP_CTRL_FRAME_TYPE;
368
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300369 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300370 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300371 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300372 }
373
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300374 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300375 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300376 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300377 }
378
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300379 skb = bt_skb_alloc(count, GFP_ATOMIC);
380 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300381 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300382
383 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300384 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300385 lh->cid = cpu_to_le16(pi->dcid);
386 put_unaligned_le16(control, skb_put(skb, 2));
387
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300388 if (pi->fcs == L2CAP_FCS_CRC16) {
389 u16 fcs = crc16(0, (u8 *)lh, count - 2);
390 put_unaligned_le16(fcs, skb_put(skb, 2));
391 }
392
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200393 if (lmp_no_flush_capable(conn->hcon->hdev))
394 flags = ACL_START_NO_FLUSH;
395 else
396 flags = ACL_START;
397
398 hci_send_acl(pi->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300399}
400
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300401static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300402{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300403 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300404 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300405 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300406 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300407 control |= L2CAP_SUPER_RCV_READY;
408
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300409 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300410
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300411 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300412}
413
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300414static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300415{
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300416 return !(chan->conf_state & L2CAP_CONF_CONNECT_PEND);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300417}
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
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300428 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(chan)) {
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);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300434 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200435
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300436 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
437 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200438 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200439 } else {
440 struct l2cap_info_req req;
441 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
442
443 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
444 conn->info_ident = l2cap_get_ident(conn);
445
446 mod_timer(&conn->info_timer, jiffies +
447 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
448
449 l2cap_send_cmd(conn, conn->info_ident,
450 L2CAP_INFO_REQ, sizeof(req), &req);
451 }
452}
453
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300454static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
455{
456 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300457 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300458 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
459
460 switch (mode) {
461 case L2CAP_MODE_ERTM:
462 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
463 case L2CAP_MODE_STREAMING:
464 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
465 default:
466 return 0x00;
467 }
468}
469
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300470void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300471{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300472 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300473 struct l2cap_disconn_req req;
474
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300475 if (!conn)
476 return;
477
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300478 sk = chan->sk;
479
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300480 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300481 del_timer(&chan->retrans_timer);
482 del_timer(&chan->monitor_timer);
483 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300484 }
485
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300486 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
487 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
488 l2cap_send_cmd(conn, l2cap_get_ident(conn),
489 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300490
491 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300492 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300493}
494
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200496static void l2cap_conn_start(struct l2cap_conn *conn)
497{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300498 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200499
500 BT_DBG("conn %p", conn);
501
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300502 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200503
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300504 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300505 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300506
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200507 bh_lock_sock(sk);
508
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300509 if (sk->sk_type != SOCK_SEQPACKET &&
510 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200511 bh_unlock_sock(sk);
512 continue;
513 }
514
515 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300516 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300517
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300518 if (!l2cap_check_security(sk) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300519 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300520 bh_unlock_sock(sk);
521 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200522 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300523
524 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
525 conn->feat_mask)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300526 && chan->conf_state &
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300527 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300528 /* __l2cap_sock_close() calls list_del(chan)
529 * so release the lock */
530 read_unlock_bh(&conn->chan_lock);
531 __l2cap_sock_close(sk, ECONNRESET);
532 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300533 bh_unlock_sock(sk);
534 continue;
535 }
536
537 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
538 req.psm = l2cap_pi(sk)->psm;
539
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300540 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300541 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300542
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300543 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
544 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300545
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200546 } else if (sk->sk_state == BT_CONNECT2) {
547 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300548 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200549 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
550 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
551
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100552 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100553 if (bt_sk(sk)->defer_setup) {
554 struct sock *parent = bt_sk(sk)->parent;
555 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
556 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
557 parent->sk_data_ready(parent, 0);
558
559 } else {
560 sk->sk_state = BT_CONFIG;
561 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
562 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
563 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200564 } else {
565 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
566 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
567 }
568
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300569 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
570 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300571
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300572 if (chan->conf_state & L2CAP_CONF_REQ_SENT ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300573 rsp.result != L2CAP_CR_SUCCESS) {
574 bh_unlock_sock(sk);
575 continue;
576 }
577
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300578 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300579 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300580 l2cap_build_conf_req(chan, buf), buf);
581 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200582 }
583
584 bh_unlock_sock(sk);
585 }
586
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300587 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200588}
589
Ville Tervob62f3282011-02-10 22:38:50 -0300590/* Find socket with cid and source bdaddr.
591 * Returns closest match, locked.
592 */
593static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
594{
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300595 struct sock *sk = NULL, *sk1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300596 struct hlist_node *node;
597
598 read_lock(&l2cap_sk_list.lock);
599
600 sk_for_each(sk, node, &l2cap_sk_list.head) {
601 if (state && sk->sk_state != state)
602 continue;
603
604 if (l2cap_pi(sk)->scid == cid) {
605 /* Exact match. */
606 if (!bacmp(&bt_sk(sk)->src, src))
607 break;
608
609 /* Closest match */
610 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
611 sk1 = sk;
612 }
613 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300614
Ville Tervob62f3282011-02-10 22:38:50 -0300615 read_unlock(&l2cap_sk_list.lock);
616
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300617 return node ? sk : sk1;
Ville Tervob62f3282011-02-10 22:38:50 -0300618}
619
620static void l2cap_le_conn_ready(struct l2cap_conn *conn)
621{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300622 struct sock *parent, *sk;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300623 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300624
625 BT_DBG("");
626
627 /* Check if we have socket listening on cid */
628 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
629 conn->src);
630 if (!parent)
631 return;
632
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300633 bh_lock_sock(parent);
634
Ville Tervob62f3282011-02-10 22:38:50 -0300635 /* Check for backlog size */
636 if (sk_acceptq_is_full(parent)) {
637 BT_DBG("backlog full %d", parent->sk_ack_backlog);
638 goto clean;
639 }
640
641 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
642 if (!sk)
643 goto clean;
644
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300645 chan = l2cap_chan_alloc(sk);
646 if (!chan) {
647 l2cap_sock_kill(sk);
648 goto clean;
649 }
650
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300651 l2cap_pi(sk)->chan = chan;
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
Ville Tervob62f3282011-02-10 22:38:50 -0300666 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
667
668 sk->sk_state = BT_CONNECTED;
669 parent->sk_data_ready(parent, 0);
670
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300671 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300672
673clean:
674 bh_unlock_sock(parent);
675}
676
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200677static void l2cap_conn_ready(struct l2cap_conn *conn)
678{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300679 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200680
681 BT_DBG("conn %p", conn);
682
Ville Tervob62f3282011-02-10 22:38:50 -0300683 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
684 l2cap_le_conn_ready(conn);
685
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300686 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200687
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300688 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300689 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300690
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200691 bh_lock_sock(sk);
692
Ville Tervoacd7d372011-02-10 22:38:49 -0300693 if (conn->hcon->type == LE_LINK) {
694 l2cap_sock_clear_timer(sk);
695 sk->sk_state = BT_CONNECTED;
696 sk->sk_state_change(sk);
697 }
698
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300699 if (sk->sk_type != SOCK_SEQPACKET &&
700 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200701 l2cap_sock_clear_timer(sk);
702 sk->sk_state = BT_CONNECTED;
703 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200704 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300705 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200706
707 bh_unlock_sock(sk);
708 }
709
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300710 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200711}
712
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200713/* Notify sockets that we cannot guaranty reliability anymore */
714static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
715{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300716 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200717
718 BT_DBG("conn %p", conn);
719
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300720 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200721
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300722 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300723 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300724
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100725 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200726 sk->sk_err = err;
727 }
728
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300729 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200730}
731
732static void l2cap_info_timeout(unsigned long arg)
733{
734 struct l2cap_conn *conn = (void *) arg;
735
Marcel Holtmann984947d2009-02-06 23:35:19 +0100736 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100737 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100738
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200739 l2cap_conn_start(conn);
740}
741
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
743{
Marcel Holtmann01394182006-07-03 10:02:46 +0200744 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745
Marcel Holtmann01394182006-07-03 10:02:46 +0200746 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 return conn;
748
Marcel Holtmann01394182006-07-03 10:02:46 +0200749 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
750 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752
753 hcon->l2cap_data = conn;
754 conn->hcon = hcon;
755
Marcel Holtmann01394182006-07-03 10:02:46 +0200756 BT_DBG("hcon %p conn %p", hcon, conn);
757
Ville Tervoacd7d372011-02-10 22:38:49 -0300758 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
759 conn->mtu = hcon->hdev->le_mtu;
760 else
761 conn->mtu = hcon->hdev->acl_mtu;
762
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 conn->src = &hcon->hdev->bdaddr;
764 conn->dst = &hcon->dst;
765
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200766 conn->feat_mask = 0;
767
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300769 rwlock_init(&conn->chan_lock);
770
771 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772
Ville Tervob62f3282011-02-10 22:38:50 -0300773 if (hcon->type != LE_LINK)
774 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000775 (unsigned long) conn);
776
Marcel Holtmann2950f212009-02-12 14:02:50 +0100777 conn->disc_reason = 0x13;
778
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 return conn;
780}
781
Marcel Holtmann01394182006-07-03 10:02:46 +0200782static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783{
Marcel Holtmann01394182006-07-03 10:02:46 +0200784 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300785 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 struct sock *sk;
787
Marcel Holtmann01394182006-07-03 10:02:46 +0200788 if (!conn)
789 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
791 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
792
Wei Yongjun7585b972009-02-25 18:29:52 +0800793 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794
795 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300796 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300797 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300799 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 bh_unlock_sock(sk);
801 l2cap_sock_kill(sk);
802 }
803
Dave Young8e8440f2008-03-03 12:18:55 -0800804 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
805 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800806
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 hcon->l2cap_data = NULL;
808 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809}
810
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300811static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300813 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300814 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300815 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816}
817
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819
820/* Find socket with psm and source bdaddr.
821 * Returns closest match.
822 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000823static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824{
825 struct sock *sk = NULL, *sk1 = NULL;
826 struct hlist_node *node;
827
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000828 read_lock(&l2cap_sk_list.lock);
829
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 sk_for_each(sk, node, &l2cap_sk_list.head) {
831 if (state && sk->sk_state != state)
832 continue;
833
834 if (l2cap_pi(sk)->psm == psm) {
835 /* Exact match. */
836 if (!bacmp(&bt_sk(sk)->src, src))
837 break;
838
839 /* Closest match */
840 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
841 sk1 = sk;
842 }
843 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000846
847 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848}
849
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -0300850int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300852 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 bdaddr_t *src = &bt_sk(sk)->src;
854 bdaddr_t *dst = &bt_sk(sk)->dst;
855 struct l2cap_conn *conn;
856 struct hci_conn *hcon;
857 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200858 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200859 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100861 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
862 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300864 hdev = hci_get_route(dst, src);
865 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 return -EHOSTUNREACH;
867
868 hci_dev_lock_bh(hdev);
869
Johan Hedberg8556edd32011-01-19 12:06:50 +0530870 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200871
Ville Tervoacd7d372011-02-10 22:38:49 -0300872 if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
873 hcon = hci_connect(hdev, LE_LINK, dst,
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100874 l2cap_pi(sk)->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300875 else
876 hcon = hci_connect(hdev, ACL_LINK, dst,
877 l2cap_pi(sk)->sec_level, auth_type);
878
Ville Tervo30e76272011-02-22 16:10:53 -0300879 if (IS_ERR(hcon)) {
880 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300882 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883
884 conn = l2cap_conn_add(hcon, 0);
885 if (!conn) {
886 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300887 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 goto done;
889 }
890
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 /* Update source addr of the socket */
892 bacpy(src, conn->src);
893
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300894 l2cap_chan_add(conn, chan);
895
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 sk->sk_state = BT_CONNECT;
897 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
898
899 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300900 if (sk->sk_type != SOCK_SEQPACKET &&
901 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530903 if (l2cap_check_security(sk))
904 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200905 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300906 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 }
908
Ville Tervo30e76272011-02-22 16:10:53 -0300909 err = 0;
910
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911done:
912 hci_dev_unlock_bh(hdev);
913 hci_dev_put(hdev);
914 return err;
915}
916
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200917int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300918{
919 DECLARE_WAITQUEUE(wait, current);
920 int err = 0;
921 int timeo = HZ/5;
922
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200923 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300924 while ((l2cap_pi(sk)->chan->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300925 set_current_state(TASK_INTERRUPTIBLE);
926
927 if (!timeo)
928 timeo = HZ/5;
929
930 if (signal_pending(current)) {
931 err = sock_intr_errno(timeo);
932 break;
933 }
934
935 release_sock(sk);
936 timeo = schedule_timeout(timeo);
937 lock_sock(sk);
938
939 err = sock_error(sk);
940 if (err)
941 break;
942 }
943 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200944 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300945 return err;
946}
947
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300948static void l2cap_monitor_timeout(unsigned long arg)
949{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300950 struct l2cap_chan *chan = (void *) arg;
951 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300952
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300953 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300954
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300955 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -0300956 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300957 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200958 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300959 return;
960 }
961
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300962 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300963 __mod_monitor_timer();
964
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300965 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300966 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300967}
968
969static void l2cap_retrans_timeout(unsigned long arg)
970{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300971 struct l2cap_chan *chan = (void *) arg;
972 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300973
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300974 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300975
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300976 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300977 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300978 __mod_monitor_timer();
979
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300980 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300981
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300982 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300983 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300984}
985
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300986static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300987{
988 struct sk_buff *skb;
989
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300990 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300991 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300992 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300993 break;
994
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300995 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300996 kfree_skb(skb);
997
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300998 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300999 }
1000
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001001 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001002 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001003}
1004
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001005void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001006{
1007 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001008 struct hci_conn *hcon = pi->conn->hcon;
1009 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001010
1011 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1012
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001013 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
1014 flags = ACL_START_NO_FLUSH;
1015 else
1016 flags = ACL_START;
1017
1018 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001019}
1020
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001021void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001022{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001023 struct sock *sk = chan->sk;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001024 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001025 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001026 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001027
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001028 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001029 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001030 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001031 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001032
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001033 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001034 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1035 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001036 }
1037
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001038 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001039
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001040 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001041 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001042}
1043
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001044static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001045{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001046 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001047 struct l2cap_pinfo *pi = l2cap_pi(sk);
1048 struct sk_buff *skb, *tx_skb;
1049 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001050
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001051 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001052 if (!skb)
1053 return;
1054
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001055 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001056 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001057 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001058
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001059 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001060 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001061
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001062 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001063
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001064 if (chan->remote_max_tx &&
1065 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001066 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001067 return;
1068 }
1069
1070 tx_skb = skb_clone(skb, GFP_ATOMIC);
1071 bt_cb(skb)->retries++;
1072 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001073 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001074
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001075 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001076 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001077 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001078 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001079
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001080 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001081 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001082
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001083 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1084
1085 if (pi->fcs == L2CAP_FCS_CRC16) {
1086 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1087 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1088 }
1089
1090 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001091}
1092
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001093int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001094{
1095 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001096 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001097 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001098 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001099 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001100
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001101 if (sk->sk_state != BT_CONNECTED)
1102 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001103
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001104 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001105
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001106 if (chan->remote_max_tx &&
1107 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001108 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001109 break;
1110 }
1111
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001112 tx_skb = skb_clone(skb, GFP_ATOMIC);
1113
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001114 bt_cb(skb)->retries++;
1115
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001116 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001117 control &= L2CAP_CTRL_SAR;
1118
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001119 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001120 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001121 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001122 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001123 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1124 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001125 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1126
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001127
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001128 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001129 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1130 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1131 }
1132
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001133 l2cap_do_send(sk, tx_skb);
1134
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001135 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001136
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001137 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1138 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001139
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301140 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001141 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301142
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001143 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001144
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001145 if (skb_queue_is_last(&chan->tx_q, skb))
1146 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001147 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001148 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001149
1150 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001151 }
1152
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001153 return nsent;
1154}
1155
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001156static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001157{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001158 int ret;
1159
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001160 if (!skb_queue_empty(&chan->tx_q))
1161 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001162
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001163 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001164 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001165 return ret;
1166}
1167
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001168static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001169{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001170 u16 control = 0;
1171
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001172 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001173
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001174 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001175 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001176 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1177 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001178 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001179 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001180
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001181 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001182 return;
1183
1184 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001185 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001186}
1187
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001188static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001189{
1190 struct srej_list *tail;
1191 u16 control;
1192
1193 control = L2CAP_SUPER_SELECT_REJECT;
1194 control |= L2CAP_CTRL_FINAL;
1195
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001196 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001197 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1198
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001199 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001200}
1201
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001202static 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 -07001203{
1204 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001205 struct sk_buff **frag;
1206 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001208 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001209 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
1211 sent += count;
1212 len -= count;
1213
1214 /* Continuation fragments (no L2CAP header) */
1215 frag = &skb_shinfo(skb)->frag_list;
1216 while (len) {
1217 count = min_t(unsigned int, conn->mtu, len);
1218
1219 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1220 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001221 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001222 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1223 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224
1225 sent += count;
1226 len -= count;
1227
1228 frag = &(*frag)->next;
1229 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
1231 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001232}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001234struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001235{
1236 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1237 struct sk_buff *skb;
1238 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1239 struct l2cap_hdr *lh;
1240
1241 BT_DBG("sk %p len %d", sk, (int)len);
1242
1243 count = min_t(unsigned int, (conn->mtu - hlen), len);
1244 skb = bt_skb_send_alloc(sk, count + hlen,
1245 msg->msg_flags & MSG_DONTWAIT, &err);
1246 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001247 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001248
1249 /* Create L2CAP header */
1250 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1251 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1252 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1253 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1254
1255 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1256 if (unlikely(err < 0)) {
1257 kfree_skb(skb);
1258 return ERR_PTR(err);
1259 }
1260 return skb;
1261}
1262
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001263struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001264{
1265 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1266 struct sk_buff *skb;
1267 int err, count, hlen = L2CAP_HDR_SIZE;
1268 struct l2cap_hdr *lh;
1269
1270 BT_DBG("sk %p len %d", sk, (int)len);
1271
1272 count = min_t(unsigned int, (conn->mtu - hlen), len);
1273 skb = bt_skb_send_alloc(sk, count + hlen,
1274 msg->msg_flags & MSG_DONTWAIT, &err);
1275 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001276 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001277
1278 /* Create L2CAP header */
1279 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1280 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1281 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1282
1283 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1284 if (unlikely(err < 0)) {
1285 kfree_skb(skb);
1286 return ERR_PTR(err);
1287 }
1288 return skb;
1289}
1290
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001291struct 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 -03001292{
1293 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1294 struct sk_buff *skb;
1295 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1296 struct l2cap_hdr *lh;
1297
1298 BT_DBG("sk %p len %d", sk, (int)len);
1299
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001300 if (!conn)
1301 return ERR_PTR(-ENOTCONN);
1302
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001303 if (sdulen)
1304 hlen += 2;
1305
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001306 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1307 hlen += 2;
1308
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001309 count = min_t(unsigned int, (conn->mtu - hlen), len);
1310 skb = bt_skb_send_alloc(sk, count + hlen,
1311 msg->msg_flags & MSG_DONTWAIT, &err);
1312 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001313 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001314
1315 /* Create L2CAP header */
1316 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1317 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1318 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1319 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001320 if (sdulen)
1321 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001322
1323 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1324 if (unlikely(err < 0)) {
1325 kfree_skb(skb);
1326 return ERR_PTR(err);
1327 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001328
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001329 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1330 put_unaligned_le16(0, skb_put(skb, 2));
1331
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001332 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001333 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334}
1335
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001336int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001337{
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001338 struct sock *sk = chan->sk;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001339 struct sk_buff *skb;
1340 struct sk_buff_head sar_queue;
1341 u16 control;
1342 size_t size = 0;
1343
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001344 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001345 control = L2CAP_SDU_START;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001346 skb = l2cap_create_iframe_pdu(sk, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001347 if (IS_ERR(skb))
1348 return PTR_ERR(skb);
1349
1350 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001351 len -= chan->remote_mps;
1352 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001353
1354 while (len > 0) {
1355 size_t buflen;
1356
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001357 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001358 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001359 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001360 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001361 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001362 buflen = len;
1363 }
1364
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001365 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001366 if (IS_ERR(skb)) {
1367 skb_queue_purge(&sar_queue);
1368 return PTR_ERR(skb);
1369 }
1370
1371 __skb_queue_tail(&sar_queue, skb);
1372 len -= buflen;
1373 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001374 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001375 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1376 if (chan->tx_send_head == NULL)
1377 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001378
1379 return size;
1380}
1381
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382static void l2cap_chan_ready(struct sock *sk)
1383{
1384 struct sock *parent = bt_sk(sk)->parent;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001385 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
1387 BT_DBG("sk %p, parent %p", sk, parent);
1388
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001389 chan->conf_state = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 l2cap_sock_clear_timer(sk);
1391
1392 if (!parent) {
1393 /* Outgoing channel.
1394 * Wake up socket sleeping on connect.
1395 */
1396 sk->sk_state = BT_CONNECTED;
1397 sk->sk_state_change(sk);
1398 } else {
1399 /* Incoming channel.
1400 * Wake up socket sleeping on accept.
1401 */
1402 parent->sk_data_ready(parent, 0);
1403 }
1404}
1405
1406/* Copy frame to all raw sockets on that connection */
1407static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1408{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001410 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411
1412 BT_DBG("conn %p", conn);
1413
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001414 read_lock(&conn->chan_lock);
1415 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001416 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 if (sk->sk_type != SOCK_RAW)
1418 continue;
1419
1420 /* Don't send frame to the socket it came from */
1421 if (skb->sk == sk)
1422 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001423 nskb = skb_clone(skb, GFP_ATOMIC);
1424 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 continue;
1426
1427 if (sock_queue_rcv_skb(sk, nskb))
1428 kfree_skb(nskb);
1429 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001430 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431}
1432
1433/* ---- L2CAP signalling commands ---- */
1434static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1435 u8 code, u8 ident, u16 dlen, void *data)
1436{
1437 struct sk_buff *skb, **frag;
1438 struct l2cap_cmd_hdr *cmd;
1439 struct l2cap_hdr *lh;
1440 int len, count;
1441
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001442 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1443 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
1445 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1446 count = min_t(unsigned int, conn->mtu, len);
1447
1448 skb = bt_skb_alloc(count, GFP_ATOMIC);
1449 if (!skb)
1450 return NULL;
1451
1452 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001453 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001454
1455 if (conn->hcon->type == LE_LINK)
1456 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1457 else
1458 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459
1460 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1461 cmd->code = code;
1462 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001463 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
1465 if (dlen) {
1466 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1467 memcpy(skb_put(skb, count), data, count);
1468 data += count;
1469 }
1470
1471 len -= skb->len;
1472
1473 /* Continuation fragments (no L2CAP header) */
1474 frag = &skb_shinfo(skb)->frag_list;
1475 while (len) {
1476 count = min_t(unsigned int, conn->mtu, len);
1477
1478 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1479 if (!*frag)
1480 goto fail;
1481
1482 memcpy(skb_put(*frag, count), data, count);
1483
1484 len -= count;
1485 data += count;
1486
1487 frag = &(*frag)->next;
1488 }
1489
1490 return skb;
1491
1492fail:
1493 kfree_skb(skb);
1494 return NULL;
1495}
1496
1497static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1498{
1499 struct l2cap_conf_opt *opt = *ptr;
1500 int len;
1501
1502 len = L2CAP_CONF_OPT_SIZE + opt->len;
1503 *ptr += len;
1504
1505 *type = opt->type;
1506 *olen = opt->len;
1507
1508 switch (opt->len) {
1509 case 1:
1510 *val = *((u8 *) opt->val);
1511 break;
1512
1513 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001514 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 break;
1516
1517 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001518 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 break;
1520
1521 default:
1522 *val = (unsigned long) opt->val;
1523 break;
1524 }
1525
1526 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1527 return len;
1528}
1529
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1531{
1532 struct l2cap_conf_opt *opt = *ptr;
1533
1534 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1535
1536 opt->type = type;
1537 opt->len = len;
1538
1539 switch (len) {
1540 case 1:
1541 *((u8 *) opt->val) = val;
1542 break;
1543
1544 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001545 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 break;
1547
1548 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001549 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 break;
1551
1552 default:
1553 memcpy(opt->val, (void *) val, len);
1554 break;
1555 }
1556
1557 *ptr += L2CAP_CONF_OPT_SIZE + len;
1558}
1559
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001560static void l2cap_ack_timeout(unsigned long arg)
1561{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001562 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001563
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001564 bh_lock_sock(chan->sk);
1565 l2cap_send_ack(chan);
1566 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001567}
1568
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001569static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001570{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001571 struct sock *sk = chan->sk;
1572
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001573 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001574 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001575 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001576 chan->num_acked = 0;
1577 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001578
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001579 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1580 (unsigned long) chan);
1581 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1582 (unsigned long) chan);
1583 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001584
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001585 skb_queue_head_init(&chan->srej_q);
1586 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001587
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001588 INIT_LIST_HEAD(&chan->srej_l);
1589
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001590 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001591
1592 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001593}
1594
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001595static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1596{
1597 switch (mode) {
1598 case L2CAP_MODE_STREAMING:
1599 case L2CAP_MODE_ERTM:
1600 if (l2cap_mode_supported(mode, remote_feat_mask))
1601 return mode;
1602 /* fall through */
1603 default:
1604 return L2CAP_MODE_BASIC;
1605 }
1606}
1607
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001608static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001610 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001612 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 void *ptr = req->data;
1614
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001615 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001617 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001618 goto done;
1619
1620 switch (pi->mode) {
1621 case L2CAP_MODE_STREAMING:
1622 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001623 if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001624 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001625
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001626 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001627 default:
1628 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1629 break;
1630 }
1631
1632done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001633 if (pi->imtu != L2CAP_DEFAULT_MTU)
1634 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1635
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001636 switch (pi->mode) {
1637 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001638 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1639 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1640 break;
1641
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001642 rfc.mode = L2CAP_MODE_BASIC;
1643 rfc.txwin_size = 0;
1644 rfc.max_transmit = 0;
1645 rfc.retrans_timeout = 0;
1646 rfc.monitor_timeout = 0;
1647 rfc.max_pdu_size = 0;
1648
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001649 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1650 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001651 break;
1652
1653 case L2CAP_MODE_ERTM:
1654 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001655 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001656 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001657 rfc.retrans_timeout = 0;
1658 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001659 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001660 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001661 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001662
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001663 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1664 (unsigned long) &rfc);
1665
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001666 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1667 break;
1668
1669 if (pi->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001670 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001671 pi->fcs = L2CAP_FCS_NONE;
1672 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1673 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001674 break;
1675
1676 case L2CAP_MODE_STREAMING:
1677 rfc.mode = L2CAP_MODE_STREAMING;
1678 rfc.txwin_size = 0;
1679 rfc.max_transmit = 0;
1680 rfc.retrans_timeout = 0;
1681 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001682 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001683 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001684 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001685
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001686 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1687 (unsigned long) &rfc);
1688
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001689 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1690 break;
1691
1692 if (pi->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001693 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001694 pi->fcs = L2CAP_FCS_NONE;
1695 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1696 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001697 break;
1698 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001700 req->dcid = cpu_to_le16(pi->dcid);
1701 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702
1703 return ptr - data;
1704}
1705
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001706static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001708 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001709 struct l2cap_conf_rsp *rsp = data;
1710 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001711 void *req = chan->conf_req;
1712 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001713 int type, hint, olen;
1714 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001715 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001716 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001717 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001719 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001720
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001721 while (len >= L2CAP_CONF_OPT_SIZE) {
1722 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001724 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001725 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001726
1727 switch (type) {
1728 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001729 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001730 break;
1731
1732 case L2CAP_CONF_FLUSH_TO:
1733 pi->flush_to = val;
1734 break;
1735
1736 case L2CAP_CONF_QOS:
1737 break;
1738
Marcel Holtmann6464f352007-10-20 13:39:51 +02001739 case L2CAP_CONF_RFC:
1740 if (olen == sizeof(rfc))
1741 memcpy(&rfc, (void *) val, olen);
1742 break;
1743
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001744 case L2CAP_CONF_FCS:
1745 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001746 chan->conf_state |= L2CAP_CONF_NO_FCS_RECV;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001747
1748 break;
1749
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001750 default:
1751 if (hint)
1752 break;
1753
1754 result = L2CAP_CONF_UNKNOWN;
1755 *((u8 *) ptr++) = type;
1756 break;
1757 }
1758 }
1759
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001760 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001761 goto done;
1762
1763 switch (pi->mode) {
1764 case L2CAP_MODE_STREAMING:
1765 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001766 if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001767 pi->mode = l2cap_select_mode(rfc.mode,
1768 pi->conn->feat_mask);
1769 break;
1770 }
1771
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001772 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001773 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001774
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001775 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001776 }
1777
1778done:
1779 if (pi->mode != rfc.mode) {
1780 result = L2CAP_CONF_UNACCEPT;
1781 rfc.mode = pi->mode;
1782
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001783 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001784 return -ECONNREFUSED;
1785
1786 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1787 sizeof(rfc), (unsigned long) &rfc);
1788 }
1789
1790
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001791 if (result == L2CAP_CONF_SUCCESS) {
1792 /* Configure output options and let the other side know
1793 * which ones we don't like. */
1794
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001795 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1796 result = L2CAP_CONF_UNACCEPT;
1797 else {
1798 pi->omtu = mtu;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001799 chan->conf_state |= L2CAP_CONF_MTU_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001800 }
1801 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001802
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001803 switch (rfc.mode) {
1804 case L2CAP_MODE_BASIC:
1805 pi->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001806 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001807 break;
1808
1809 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001810 chan->remote_tx_win = rfc.txwin_size;
1811 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001812
1813 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1814 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001815
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001816 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001817
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001818 rfc.retrans_timeout =
1819 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1820 rfc.monitor_timeout =
1821 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001822
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001823 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001824
1825 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1826 sizeof(rfc), (unsigned long) &rfc);
1827
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001828 break;
1829
1830 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001831 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1832 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001833
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001834 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001835
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001836 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001837
1838 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1839 sizeof(rfc), (unsigned long) &rfc);
1840
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001841 break;
1842
1843 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001844 result = L2CAP_CONF_UNACCEPT;
1845
1846 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001847 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001848 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001849
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001850 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001851 chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001852 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001853 rsp->scid = cpu_to_le16(pi->dcid);
1854 rsp->result = cpu_to_le16(result);
1855 rsp->flags = cpu_to_le16(0x0000);
1856
1857 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858}
1859
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001860static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001861{
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001862 struct sock *sk = chan->sk;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001863 struct l2cap_pinfo *pi = l2cap_pi(sk);
1864 struct l2cap_conf_req *req = data;
1865 void *ptr = req->data;
1866 int type, olen;
1867 unsigned long val;
1868 struct l2cap_conf_rfc rfc;
1869
1870 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1871
1872 while (len >= L2CAP_CONF_OPT_SIZE) {
1873 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1874
1875 switch (type) {
1876 case L2CAP_CONF_MTU:
1877 if (val < L2CAP_DEFAULT_MIN_MTU) {
1878 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001879 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001880 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001881 pi->imtu = val;
1882 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001883 break;
1884
1885 case L2CAP_CONF_FLUSH_TO:
1886 pi->flush_to = val;
1887 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1888 2, pi->flush_to);
1889 break;
1890
1891 case L2CAP_CONF_RFC:
1892 if (olen == sizeof(rfc))
1893 memcpy(&rfc, (void *)val, olen);
1894
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001895 if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001896 rfc.mode != pi->mode)
1897 return -ECONNREFUSED;
1898
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001899 pi->fcs = 0;
1900
1901 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1902 sizeof(rfc), (unsigned long) &rfc);
1903 break;
1904 }
1905 }
1906
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001907 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1908 return -ECONNREFUSED;
1909
1910 pi->mode = rfc.mode;
1911
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001912 if (*result == L2CAP_CONF_SUCCESS) {
1913 switch (rfc.mode) {
1914 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001915 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1916 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001917 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001918 break;
1919 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001920 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001921 }
1922 }
1923
1924 req->dcid = cpu_to_le16(pi->dcid);
1925 req->flags = cpu_to_le16(0x0000);
1926
1927 return ptr - data;
1928}
1929
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001930static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931{
1932 struct l2cap_conf_rsp *rsp = data;
1933 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001935 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001937 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001938 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001939 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940
1941 return ptr - data;
1942}
1943
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001944void __l2cap_connect_rsp_defer(struct sock *sk)
1945{
1946 struct l2cap_conn_rsp rsp;
1947 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1948 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
1949 u8 buf[128];
1950
1951 sk->sk_state = BT_CONFIG;
1952
1953 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1954 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1955 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1956 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1957 l2cap_send_cmd(conn, chan->ident,
1958 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1959
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001960 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001961 return;
1962
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001963 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001964 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1965 l2cap_build_conf_req(chan, buf), buf);
1966 chan->num_conf_req++;
1967}
1968
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001969static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1970{
1971 struct l2cap_pinfo *pi = l2cap_pi(sk);
1972 int type, olen;
1973 unsigned long val;
1974 struct l2cap_conf_rfc rfc;
1975
1976 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1977
1978 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1979 return;
1980
1981 while (len >= L2CAP_CONF_OPT_SIZE) {
1982 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1983
1984 switch (type) {
1985 case L2CAP_CONF_RFC:
1986 if (olen == sizeof(rfc))
1987 memcpy(&rfc, (void *)val, olen);
1988 goto done;
1989 }
1990 }
1991
1992done:
1993 switch (rfc.mode) {
1994 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001995 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1996 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001997 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1998 break;
1999 case L2CAP_MODE_STREAMING:
2000 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2001 }
2002}
2003
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002004static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2005{
2006 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2007
2008 if (rej->reason != 0x0000)
2009 return 0;
2010
2011 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2012 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002013 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002014
2015 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002016 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002017
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002018 l2cap_conn_start(conn);
2019 }
2020
2021 return 0;
2022}
2023
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2025{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2027 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002028 struct l2cap_chan *chan = NULL;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002029 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002030 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031
2032 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002033 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034
2035 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2036
2037 /* Check if we have socket listening on psm */
2038 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2039 if (!parent) {
2040 result = L2CAP_CR_BAD_PSM;
2041 goto sendresp;
2042 }
2043
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002044 bh_lock_sock(parent);
2045
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002046 /* Check if the ACL is secure enough (if not SDP) */
2047 if (psm != cpu_to_le16(0x0001) &&
2048 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002049 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002050 result = L2CAP_CR_SEC_BLOCK;
2051 goto response;
2052 }
2053
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054 result = L2CAP_CR_NO_MEM;
2055
2056 /* Check for backlog size */
2057 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002058 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 goto response;
2060 }
2061
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002062 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 if (!sk)
2064 goto response;
2065
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002066 chan = l2cap_chan_alloc(sk);
2067 if (!chan) {
2068 l2cap_sock_kill(sk);
2069 goto response;
2070 }
2071
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03002072 l2cap_pi(sk)->chan = chan;
2073
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002074 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075
2076 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002077 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2078 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 sock_set_flag(sk, SOCK_ZAPPED);
2080 l2cap_sock_kill(sk);
2081 goto response;
2082 }
2083
2084 hci_conn_hold(conn->hcon);
2085
2086 l2cap_sock_init(sk, parent);
2087 bacpy(&bt_sk(sk)->src, conn->src);
2088 bacpy(&bt_sk(sk)->dst, conn->dst);
2089 l2cap_pi(sk)->psm = psm;
2090 l2cap_pi(sk)->dcid = scid;
2091
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002092 bt_accept_enqueue(parent, sk);
2093
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002094 __l2cap_chan_add(conn, chan);
2095
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096 dcid = l2cap_pi(sk)->scid;
2097
2098 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2099
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002100 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101
Marcel Holtmann984947d2009-02-06 23:35:19 +01002102 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002103 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002104 if (bt_sk(sk)->defer_setup) {
2105 sk->sk_state = BT_CONNECT2;
2106 result = L2CAP_CR_PEND;
2107 status = L2CAP_CS_AUTHOR_PEND;
2108 parent->sk_data_ready(parent, 0);
2109 } else {
2110 sk->sk_state = BT_CONFIG;
2111 result = L2CAP_CR_SUCCESS;
2112 status = L2CAP_CS_NO_INFO;
2113 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002114 } else {
2115 sk->sk_state = BT_CONNECT2;
2116 result = L2CAP_CR_PEND;
2117 status = L2CAP_CS_AUTHEN_PEND;
2118 }
2119 } else {
2120 sk->sk_state = BT_CONNECT2;
2121 result = L2CAP_CR_PEND;
2122 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 }
2124
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002125 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126
2127response:
2128 bh_unlock_sock(parent);
2129
2130sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002131 rsp.scid = cpu_to_le16(scid);
2132 rsp.dcid = cpu_to_le16(dcid);
2133 rsp.result = cpu_to_le16(result);
2134 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002136
2137 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2138 struct l2cap_info_req info;
2139 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2140
2141 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2142 conn->info_ident = l2cap_get_ident(conn);
2143
2144 mod_timer(&conn->info_timer, jiffies +
2145 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2146
2147 l2cap_send_cmd(conn, conn->info_ident,
2148 L2CAP_INFO_REQ, sizeof(info), &info);
2149 }
2150
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002151 if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002152 result == L2CAP_CR_SUCCESS) {
2153 u8 buf[128];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002154 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002155 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002156 l2cap_build_conf_req(chan, buf), buf);
2157 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002158 }
2159
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 return 0;
2161}
2162
2163static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2164{
2165 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2166 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002167 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 struct sock *sk;
2169 u8 req[128];
2170
2171 scid = __le16_to_cpu(rsp->scid);
2172 dcid = __le16_to_cpu(rsp->dcid);
2173 result = __le16_to_cpu(rsp->result);
2174 status = __le16_to_cpu(rsp->status);
2175
2176 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2177
2178 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002179 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002180 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002181 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002183 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002184 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002185 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186 }
2187
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002188 sk = chan->sk;
2189
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 switch (result) {
2191 case L2CAP_CR_SUCCESS:
2192 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002193 chan->ident = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 l2cap_pi(sk)->dcid = dcid;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002195 chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002196
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002197 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002198 break;
2199
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002200 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002201
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002203 l2cap_build_conf_req(chan, req), req);
2204 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205 break;
2206
2207 case L2CAP_CR_PEND:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002208 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 break;
2210
2211 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002212 /* don't delete l2cap channel if sk is owned by user */
2213 if (sock_owned_by_user(sk)) {
2214 sk->sk_state = BT_DISCONN;
2215 l2cap_sock_clear_timer(sk);
2216 l2cap_sock_set_timer(sk, HZ / 5);
2217 break;
2218 }
2219
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002220 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221 break;
2222 }
2223
2224 bh_unlock_sock(sk);
2225 return 0;
2226}
2227
Mat Martineau8c462b62010-08-24 15:35:42 -07002228static inline void set_default_fcs(struct l2cap_pinfo *pi)
2229{
2230 /* FCS is enabled only in ERTM or streaming mode, if one or both
2231 * sides request it.
2232 */
2233 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2234 pi->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002235 else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
Mat Martineau8c462b62010-08-24 15:35:42 -07002236 pi->fcs = L2CAP_FCS_CRC16;
2237}
2238
Al Viro88219a02007-07-29 00:17:25 -07002239static 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 -07002240{
2241 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2242 u16 dcid, flags;
2243 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002244 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002246 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247
2248 dcid = __le16_to_cpu(req->dcid);
2249 flags = __le16_to_cpu(req->flags);
2250
2251 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2252
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002253 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002254 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255 return -ENOENT;
2256
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002257 sk = chan->sk;
2258
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002259 if (sk->sk_state != BT_CONFIG) {
2260 struct l2cap_cmd_rej rej;
2261
2262 rej.reason = cpu_to_le16(0x0002);
2263 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2264 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002265 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002266 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002267
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002268 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002269 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002270 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002271 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2272 l2cap_build_conf_rsp(sk, rsp,
2273 L2CAP_CONF_REJECT, flags), rsp);
2274 goto unlock;
2275 }
2276
2277 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002278 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2279 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280
2281 if (flags & 0x0001) {
2282 /* Incomplete config. Send empty response. */
2283 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002284 l2cap_build_conf_rsp(sk, rsp,
2285 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286 goto unlock;
2287 }
2288
2289 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002290 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002291 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002292 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002294 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002296 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002297 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002298
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002299 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002300 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002301
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002302 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002303 goto unlock;
2304
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002305 if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002306 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002307
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002309
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002310 chan->next_tx_seq = 0;
2311 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002312 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002313 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002314 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002315
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002317 goto unlock;
2318 }
2319
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002320 if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002321 u8 buf[64];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002322 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002324 l2cap_build_conf_req(chan, buf), buf);
2325 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326 }
2327
2328unlock:
2329 bh_unlock_sock(sk);
2330 return 0;
2331}
2332
2333static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2334{
2335 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2336 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002337 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002339 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340
2341 scid = __le16_to_cpu(rsp->scid);
2342 flags = __le16_to_cpu(rsp->flags);
2343 result = __le16_to_cpu(rsp->result);
2344
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002345 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2346 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002348 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002349 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 return 0;
2351
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002352 sk = chan->sk;
2353
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 switch (result) {
2355 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002356 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 break;
2358
2359 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002360 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002361 char req[64];
2362
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002363 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002364 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002365 goto done;
2366 }
2367
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002368 /* throw out any old stored conf requests */
2369 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002370 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2371 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002372 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002373 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002374 goto done;
2375 }
2376
2377 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2378 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002379 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002380 if (result != L2CAP_CONF_SUCCESS)
2381 goto done;
2382 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 }
2384
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002385 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002386 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002388 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389 goto done;
2390 }
2391
2392 if (flags & 0x01)
2393 goto done;
2394
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002395 chan->conf_state |= L2CAP_CONF_INPUT_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002397 if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002398 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002399
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002401 chan->next_tx_seq = 0;
2402 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002403 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002404 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002405 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002406
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407 l2cap_chan_ready(sk);
2408 }
2409
2410done:
2411 bh_unlock_sock(sk);
2412 return 0;
2413}
2414
2415static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2416{
2417 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2418 struct l2cap_disconn_rsp rsp;
2419 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002420 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 struct sock *sk;
2422
2423 scid = __le16_to_cpu(req->scid);
2424 dcid = __le16_to_cpu(req->dcid);
2425
2426 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2427
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002428 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002429 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 return 0;
2431
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002432 sk = chan->sk;
2433
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002434 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2435 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2437
2438 sk->sk_shutdown = SHUTDOWN_MASK;
2439
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002440 /* don't delete l2cap channel if sk is owned by user */
2441 if (sock_owned_by_user(sk)) {
2442 sk->sk_state = BT_DISCONN;
2443 l2cap_sock_clear_timer(sk);
2444 l2cap_sock_set_timer(sk, HZ / 5);
2445 bh_unlock_sock(sk);
2446 return 0;
2447 }
2448
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002449 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450 bh_unlock_sock(sk);
2451
2452 l2cap_sock_kill(sk);
2453 return 0;
2454}
2455
2456static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2457{
2458 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2459 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002460 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461 struct sock *sk;
2462
2463 scid = __le16_to_cpu(rsp->scid);
2464 dcid = __le16_to_cpu(rsp->dcid);
2465
2466 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2467
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002468 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002469 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 return 0;
2471
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002472 sk = chan->sk;
2473
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002474 /* don't delete l2cap channel if sk is owned by user */
2475 if (sock_owned_by_user(sk)) {
2476 sk->sk_state = BT_DISCONN;
2477 l2cap_sock_clear_timer(sk);
2478 l2cap_sock_set_timer(sk, HZ / 5);
2479 bh_unlock_sock(sk);
2480 return 0;
2481 }
2482
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002483 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484 bh_unlock_sock(sk);
2485
2486 l2cap_sock_kill(sk);
2487 return 0;
2488}
2489
2490static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2491{
2492 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493 u16 type;
2494
2495 type = __le16_to_cpu(req->type);
2496
2497 BT_DBG("type 0x%4.4x", type);
2498
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002499 if (type == L2CAP_IT_FEAT_MASK) {
2500 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002501 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002502 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2503 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2504 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002505 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002506 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2507 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002508 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002509 l2cap_send_cmd(conn, cmd->ident,
2510 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002511 } else if (type == L2CAP_IT_FIXED_CHAN) {
2512 u8 buf[12];
2513 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2514 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2515 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2516 memcpy(buf + 4, l2cap_fixed_chan, 8);
2517 l2cap_send_cmd(conn, cmd->ident,
2518 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002519 } else {
2520 struct l2cap_info_rsp rsp;
2521 rsp.type = cpu_to_le16(type);
2522 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2523 l2cap_send_cmd(conn, cmd->ident,
2524 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2525 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526
2527 return 0;
2528}
2529
2530static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2531{
2532 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2533 u16 type, result;
2534
2535 type = __le16_to_cpu(rsp->type);
2536 result = __le16_to_cpu(rsp->result);
2537
2538 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2539
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002540 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2541 if (cmd->ident != conn->info_ident ||
2542 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2543 return 0;
2544
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002545 del_timer(&conn->info_timer);
2546
Ville Tervoadb08ed2010-08-04 09:43:33 +03002547 if (result != L2CAP_IR_SUCCESS) {
2548 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2549 conn->info_ident = 0;
2550
2551 l2cap_conn_start(conn);
2552
2553 return 0;
2554 }
2555
Marcel Holtmann984947d2009-02-06 23:35:19 +01002556 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002557 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002558
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002559 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002560 struct l2cap_info_req req;
2561 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2562
2563 conn->info_ident = l2cap_get_ident(conn);
2564
2565 l2cap_send_cmd(conn, conn->info_ident,
2566 L2CAP_INFO_REQ, sizeof(req), &req);
2567 } else {
2568 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2569 conn->info_ident = 0;
2570
2571 l2cap_conn_start(conn);
2572 }
2573 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002574 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002575 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002576
2577 l2cap_conn_start(conn);
2578 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002579
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 return 0;
2581}
2582
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002583static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002584 u16 to_multiplier)
2585{
2586 u16 max_latency;
2587
2588 if (min > max || min < 6 || max > 3200)
2589 return -EINVAL;
2590
2591 if (to_multiplier < 10 || to_multiplier > 3200)
2592 return -EINVAL;
2593
2594 if (max >= to_multiplier * 8)
2595 return -EINVAL;
2596
2597 max_latency = (to_multiplier * 8 / max) - 1;
2598 if (latency > 499 || latency > max_latency)
2599 return -EINVAL;
2600
2601 return 0;
2602}
2603
2604static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2605 struct l2cap_cmd_hdr *cmd, u8 *data)
2606{
2607 struct hci_conn *hcon = conn->hcon;
2608 struct l2cap_conn_param_update_req *req;
2609 struct l2cap_conn_param_update_rsp rsp;
2610 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002611 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002612
2613 if (!(hcon->link_mode & HCI_LM_MASTER))
2614 return -EINVAL;
2615
2616 cmd_len = __le16_to_cpu(cmd->len);
2617 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2618 return -EPROTO;
2619
2620 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002621 min = __le16_to_cpu(req->min);
2622 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002623 latency = __le16_to_cpu(req->latency);
2624 to_multiplier = __le16_to_cpu(req->to_multiplier);
2625
2626 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2627 min, max, latency, to_multiplier);
2628
2629 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002630
2631 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2632 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002633 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2634 else
2635 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2636
2637 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2638 sizeof(rsp), &rsp);
2639
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002640 if (!err)
2641 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2642
Claudio Takahaside731152011-02-11 19:28:55 -02002643 return 0;
2644}
2645
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002646static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2647 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2648{
2649 int err = 0;
2650
2651 switch (cmd->code) {
2652 case L2CAP_COMMAND_REJ:
2653 l2cap_command_rej(conn, cmd, data);
2654 break;
2655
2656 case L2CAP_CONN_REQ:
2657 err = l2cap_connect_req(conn, cmd, data);
2658 break;
2659
2660 case L2CAP_CONN_RSP:
2661 err = l2cap_connect_rsp(conn, cmd, data);
2662 break;
2663
2664 case L2CAP_CONF_REQ:
2665 err = l2cap_config_req(conn, cmd, cmd_len, data);
2666 break;
2667
2668 case L2CAP_CONF_RSP:
2669 err = l2cap_config_rsp(conn, cmd, data);
2670 break;
2671
2672 case L2CAP_DISCONN_REQ:
2673 err = l2cap_disconnect_req(conn, cmd, data);
2674 break;
2675
2676 case L2CAP_DISCONN_RSP:
2677 err = l2cap_disconnect_rsp(conn, cmd, data);
2678 break;
2679
2680 case L2CAP_ECHO_REQ:
2681 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2682 break;
2683
2684 case L2CAP_ECHO_RSP:
2685 break;
2686
2687 case L2CAP_INFO_REQ:
2688 err = l2cap_information_req(conn, cmd, data);
2689 break;
2690
2691 case L2CAP_INFO_RSP:
2692 err = l2cap_information_rsp(conn, cmd, data);
2693 break;
2694
2695 default:
2696 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2697 err = -EINVAL;
2698 break;
2699 }
2700
2701 return err;
2702}
2703
2704static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2705 struct l2cap_cmd_hdr *cmd, u8 *data)
2706{
2707 switch (cmd->code) {
2708 case L2CAP_COMMAND_REJ:
2709 return 0;
2710
2711 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002712 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002713
2714 case L2CAP_CONN_PARAM_UPDATE_RSP:
2715 return 0;
2716
2717 default:
2718 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2719 return -EINVAL;
2720 }
2721}
2722
2723static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2724 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725{
2726 u8 *data = skb->data;
2727 int len = skb->len;
2728 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002729 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730
2731 l2cap_raw_recv(conn, skb);
2732
2733 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002734 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2736 data += L2CAP_CMD_HDR_SIZE;
2737 len -= L2CAP_CMD_HDR_SIZE;
2738
Al Viro88219a02007-07-29 00:17:25 -07002739 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740
Al Viro88219a02007-07-29 00:17:25 -07002741 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 -07002742
Al Viro88219a02007-07-29 00:17:25 -07002743 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744 BT_DBG("corrupted command");
2745 break;
2746 }
2747
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002748 if (conn->hcon->type == LE_LINK)
2749 err = l2cap_le_sig_cmd(conn, &cmd, data);
2750 else
2751 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752
2753 if (err) {
2754 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002755
2756 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757
2758 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002759 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2761 }
2762
Al Viro88219a02007-07-29 00:17:25 -07002763 data += cmd_len;
2764 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 }
2766
2767 kfree_skb(skb);
2768}
2769
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002770static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2771{
2772 u16 our_fcs, rcv_fcs;
2773 int hdr_size = L2CAP_HDR_SIZE + 2;
2774
2775 if (pi->fcs == L2CAP_FCS_CRC16) {
2776 skb_trim(skb, skb->len - 2);
2777 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2778 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2779
2780 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002781 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002782 }
2783 return 0;
2784}
2785
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002786static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002787{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002788 u16 control = 0;
2789
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002790 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002791
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002792 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002793
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002794 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002795 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002796 l2cap_send_sframe(chan, control);
2797 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002798 }
2799
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002800 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2801 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002802
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002803 l2cap_ertm_send(chan);
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. Padovan6a026612011-04-01 00:38:50 -03002806 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002807 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002808 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002809 }
2810}
2811
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002812static 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 -03002813{
2814 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002815 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002816
2817 bt_cb(skb)->tx_seq = tx_seq;
2818 bt_cb(skb)->sar = sar;
2819
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002820 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002821 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002822 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002823 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002824 }
2825
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002826 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002827 if (tx_seq_offset < 0)
2828 tx_seq_offset += 64;
2829
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002830 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002831 if (bt_cb(next_skb)->tx_seq == tx_seq)
2832 return -EINVAL;
2833
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002834 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002835 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002836 if (next_tx_seq_offset < 0)
2837 next_tx_seq_offset += 64;
2838
2839 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002840 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002841 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002842 }
2843
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002844 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002845 break;
2846
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002847 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002848
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002849 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002850
2851 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002852}
2853
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002854static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002855{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002856 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002857 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002858 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002859
2860 switch (control & L2CAP_CTRL_SAR) {
2861 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002862 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002863 goto drop;
2864
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002865 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002866 if (!err)
2867 return err;
2868
2869 break;
2870
2871 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002872 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002873 goto drop;
2874
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002875 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002876
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002877 if (chan->sdu_len > pi->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002878 goto disconnect;
2879
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002880 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
2881 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002882 return -ENOMEM;
2883
2884 /* pull sdu_len bytes only after alloc, because of Local Busy
2885 * condition we have to be sure that this will be executed
2886 * only once, i.e., when alloc does not fail */
2887 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002888
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002889 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002890
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002891 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002892 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002893 break;
2894
2895 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002896 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002897 goto disconnect;
2898
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002899 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002900 goto disconnect;
2901
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002902 chan->partial_sdu_len += skb->len;
2903 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002904 goto drop;
2905
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002906 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002907
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002908 break;
2909
2910 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002911 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002912 goto disconnect;
2913
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002914 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002915 goto disconnect;
2916
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002917 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002918 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002919
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002920 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002921 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002922
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002923 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002924 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002925
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002926 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002927 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002928
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002929 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002930 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002931 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002932 return -ENOMEM;
2933 }
2934
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002935 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002936 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002937 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002938 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002939 return err;
2940 }
2941
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002942 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2943 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002944
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002945 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002946 break;
2947 }
2948
2949 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002950 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002951
2952drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002953 kfree_skb(chan->sdu);
2954 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002955
2956disconnect:
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002957 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002958 kfree_skb(skb);
2959 return 0;
2960}
2961
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002962static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002963{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002964 struct sk_buff *skb;
2965 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002966 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002967
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002968 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002969 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002970 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002971 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002972 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002973 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002974 }
2975
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002976 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002977 }
2978
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002979 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002980 goto done;
2981
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002982 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002983 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002984 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002985 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002986
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002987 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002988 __mod_monitor_timer();
2989
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002990 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002991
2992done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002993 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2994 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002995
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002996 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002997
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002998 return 0;
2999}
3000
3001static void l2cap_busy_work(struct work_struct *work)
3002{
3003 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003004 struct l2cap_chan *chan =
3005 container_of(work, struct l2cap_chan, busy_work);
3006 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003007 int n_tries = 0, timeo = HZ/5, err;
3008 struct sk_buff *skb;
3009
3010 lock_sock(sk);
3011
3012 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003013 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003014 set_current_state(TASK_INTERRUPTIBLE);
3015
3016 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3017 err = -EBUSY;
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003018 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003019 break;
3020 }
3021
3022 if (!timeo)
3023 timeo = HZ/5;
3024
3025 if (signal_pending(current)) {
3026 err = sock_intr_errno(timeo);
3027 break;
3028 }
3029
3030 release_sock(sk);
3031 timeo = schedule_timeout(timeo);
3032 lock_sock(sk);
3033
3034 err = sock_error(sk);
3035 if (err)
3036 break;
3037
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003038 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003039 break;
3040 }
3041
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003042 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003043 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003044
3045 release_sock(sk);
3046}
3047
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003048static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003049{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003050 int sctrl, err;
3051
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003052 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003053 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003054 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003055 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003056
3057
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003058 }
3059
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003060 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003061 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003062 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003063 return err;
3064 }
3065
3066 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003067 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003068
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003069 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003070 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003071 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003072
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003073 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003074 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003075 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003076
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003077 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003078
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003079 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003080
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003081 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003082
3083 return err;
3084}
3085
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003086static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003087{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003088 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003089 struct sk_buff *_skb;
3090 int err = -EINVAL;
3091
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003092 /*
3093 * TODO: We have to notify the userland if some data is lost with the
3094 * Streaming Mode.
3095 */
3096
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003097 switch (control & L2CAP_CTRL_SAR) {
3098 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003099 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003100 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003101 break;
3102 }
3103
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003104 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003105 if (!err)
3106 return 0;
3107
3108 break;
3109
3110 case L2CAP_SDU_START:
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. Padovan6f61fd472011-03-25 20:09:37 -03003116 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003117 skb_pull(skb, 2);
3118
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003119 if (chan->sdu_len > pi->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003120 err = -EMSGSIZE;
3121 break;
3122 }
3123
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003124 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3125 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003126 err = -ENOMEM;
3127 break;
3128 }
3129
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003130 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003131
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003132 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003133 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003134 err = 0;
3135 break;
3136
3137 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003138 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003139 break;
3140
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003141 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003142
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003143 chan->partial_sdu_len += skb->len;
3144 if (chan->partial_sdu_len > chan->sdu_len)
3145 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003146 else
3147 err = 0;
3148
3149 break;
3150
3151 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003152 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003153 break;
3154
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003155 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003156
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003157 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003158 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003159
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003160 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003161 goto drop;
3162
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003163 if (chan->partial_sdu_len == chan->sdu_len) {
3164 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003165 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003166 if (err < 0)
3167 kfree_skb(_skb);
3168 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003169 err = 0;
3170
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003171drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003172 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003173 break;
3174 }
3175
3176 kfree_skb(skb);
3177 return err;
3178}
3179
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003180static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003181{
3182 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003183 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003184
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003185 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003186 if (bt_cb(skb)->tx_seq != tx_seq)
3187 break;
3188
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003189 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003190 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003191 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003192 chan->buffer_seq_srej =
3193 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003194 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003195 }
3196}
3197
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003198static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003199{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003200 struct srej_list *l, *tmp;
3201 u16 control;
3202
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003203 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003204 if (l->tx_seq == tx_seq) {
3205 list_del(&l->list);
3206 kfree(l);
3207 return;
3208 }
3209 control = L2CAP_SUPER_SELECT_REJECT;
3210 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003211 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003212 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003213 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003214 }
3215}
3216
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003217static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003218{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003219 struct srej_list *new;
3220 u16 control;
3221
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003222 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003223 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003224 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003225 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003226
3227 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003228 new->tx_seq = chan->expected_tx_seq;
3229 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003230 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003231 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003232 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003233}
3234
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003235static 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 -03003236{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003237 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003238 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003239 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003240 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003241 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003242 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003243 int err = 0;
3244
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003245 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3246 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003247
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003248 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003249 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003250 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003251 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003252 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003253 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003254 }
3255
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003256 chan->expected_ack_seq = req_seq;
3257 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003258
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003259 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003260 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003261
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003262 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003263 if (tx_seq_offset < 0)
3264 tx_seq_offset += 64;
3265
3266 /* invalid tx_seq */
3267 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003268 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003269 goto drop;
3270 }
3271
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003272 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003273 goto drop;
3274
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003275 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003276 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003277
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003278 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003279 struct srej_list, list);
3280 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003281 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003282 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003283
3284 list_del(&first->list);
3285 kfree(first);
3286
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003287 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003288 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003289 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3290 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003291 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003292 }
3293 } else {
3294 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003295
3296 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003297 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003298 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003299
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003300 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003301 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003302 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003303 return 0;
3304 }
3305 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003306 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003307 }
3308 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003309 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003310 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003311 if (expected_tx_seq_offset < 0)
3312 expected_tx_seq_offset += 64;
3313
3314 /* duplicated tx_seq */
3315 if (tx_seq_offset < expected_tx_seq_offset)
3316 goto drop;
3317
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003318 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003319
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003320 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003321
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003322 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003323 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003324
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003325 __skb_queue_head_init(&chan->srej_q);
3326 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003327 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003328
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003329 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003330
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003331 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003332
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003333 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003334 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003335 return 0;
3336
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003337expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003338 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003339
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003340 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003341 bt_cb(skb)->tx_seq = tx_seq;
3342 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003343 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003344 return 0;
3345 }
3346
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003347 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003348 if (err < 0)
3349 return 0;
3350
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003351 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003352 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3353 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003354 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003355 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003356 }
3357
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003358 __mod_ack_timer();
3359
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003360 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3361 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003362 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003363
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003364 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003365
3366drop:
3367 kfree_skb(skb);
3368 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003369}
3370
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003371static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003372{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003373 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003374 rx_control);
3375
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003376 chan->expected_ack_seq = __get_reqseq(rx_control);
3377 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003378
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003379 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003380 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3381 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3382 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003383 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003384 __mod_retrans_timer();
3385
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003386 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3387 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003388 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003389 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003390 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003391
3392 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003393 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003394
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003395 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3396 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003397 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003398 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003399
3400 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003401 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003402 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003403 __mod_retrans_timer();
3404
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003405 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3406 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3407 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003408 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003409 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003410 }
3411}
3412
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003413static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003414{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003415 u8 tx_seq = __get_reqseq(rx_control);
3416
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003417 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003418
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003419 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003420
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003421 chan->expected_ack_seq = tx_seq;
3422 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003423
3424 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003425 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3426 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003427 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003428 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003429 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003430 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003431
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003432 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3433 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003434 }
3435}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003436static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003437{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003438 u8 tx_seq = __get_reqseq(rx_control);
3439
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003440 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003441
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003442 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003443
3444 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003445 chan->expected_ack_seq = tx_seq;
3446 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003447
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003448 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3449 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003450
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003451 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003452
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003453 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003454 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003455 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003456 }
3457 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003458 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003459 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003460 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003461 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003462 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003463 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003464 l2cap_retransmit_one_frame(chan, tx_seq);
3465 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003466 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003467 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003468 }
3469 }
3470}
3471
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003472static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003473{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003474 u8 tx_seq = __get_reqseq(rx_control);
3475
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003476 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003477
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003478 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003479 chan->expected_ack_seq = tx_seq;
3480 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003481
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003482 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003483 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003484
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003485 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003486 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003487 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003488 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003489 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003490 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003491
3492 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003493 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003494 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003495 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003496}
3497
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003498static 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 -03003499{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003500 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003501
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003502 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003503 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003504 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003505 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003506 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003507 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003508 }
3509
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003510 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3511 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003512 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003513 break;
3514
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003515 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003516 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003517 break;
3518
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003519 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003520 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003521 break;
3522
3523 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003524 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003525 break;
3526 }
3527
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003528 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003529 return 0;
3530}
3531
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003532static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3533{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003534 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003535 struct l2cap_pinfo *pi = l2cap_pi(sk);
3536 u16 control;
3537 u8 req_seq;
3538 int len, next_tx_seq_offset, req_seq_offset;
3539
3540 control = get_unaligned_le16(skb->data);
3541 skb_pull(skb, 2);
3542 len = skb->len;
3543
3544 /*
3545 * We can just drop the corrupted I-frame here.
3546 * Receiver will miss it and start proper recovery
3547 * procedures and ask retransmission.
3548 */
3549 if (l2cap_check_fcs(pi, skb))
3550 goto drop;
3551
3552 if (__is_sar_start(control) && __is_iframe(control))
3553 len -= 2;
3554
3555 if (pi->fcs == L2CAP_FCS_CRC16)
3556 len -= 2;
3557
3558 if (len > pi->mps) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003559 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003560 goto drop;
3561 }
3562
3563 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003564 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003565 if (req_seq_offset < 0)
3566 req_seq_offset += 64;
3567
3568 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003569 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003570 if (next_tx_seq_offset < 0)
3571 next_tx_seq_offset += 64;
3572
3573 /* check for invalid req-seq */
3574 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003575 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003576 goto drop;
3577 }
3578
3579 if (__is_iframe(control)) {
3580 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003581 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003582 goto drop;
3583 }
3584
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003585 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003586 } else {
3587 if (len != 0) {
3588 BT_ERR("%d", len);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003589 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003590 goto drop;
3591 }
3592
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003593 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003594 }
3595
3596 return 0;
3597
3598drop:
3599 kfree_skb(skb);
3600 return 0;
3601}
3602
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3604{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003605 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003607 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003608 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003609 u8 tx_seq;
3610 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003612 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003613 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614 BT_DBG("unknown cid 0x%4.4x", cid);
3615 goto drop;
3616 }
3617
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003618 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003619 pi = l2cap_pi(sk);
3620
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003621 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622
3623 if (sk->sk_state != BT_CONNECTED)
3624 goto drop;
3625
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003626 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003627 case L2CAP_MODE_BASIC:
3628 /* If socket recv buffers overflows we drop data here
3629 * which is *bad* because L2CAP has to be reliable.
3630 * But we don't have any other choice. L2CAP doesn't
3631 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003633 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003634 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003636 if (!sock_queue_rcv_skb(sk, skb))
3637 goto done;
3638 break;
3639
3640 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003641 if (!sock_owned_by_user(sk)) {
3642 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003643 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003644 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003645 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003646 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003647
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003648 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003649
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003650 case L2CAP_MODE_STREAMING:
3651 control = get_unaligned_le16(skb->data);
3652 skb_pull(skb, 2);
3653 len = skb->len;
3654
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003655 if (l2cap_check_fcs(pi, skb))
3656 goto drop;
3657
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003658 if (__is_sar_start(control))
3659 len -= 2;
3660
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003661 if (pi->fcs == L2CAP_FCS_CRC16)
3662 len -= 2;
3663
Nathan Holstein51893f82010-06-09 15:46:25 -04003664 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003665 goto drop;
3666
3667 tx_seq = __get_txseq(control);
3668
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003669 if (chan->expected_tx_seq == tx_seq)
3670 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003671 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003672 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003673
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003674 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003675
3676 goto done;
3677
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003678 default:
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003679 BT_DBG("chan %p: bad mode 0x%2.2x", chan, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003680 break;
3681 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682
3683drop:
3684 kfree_skb(skb);
3685
3686done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003687 if (sk)
3688 bh_unlock_sock(sk);
3689
Linus Torvalds1da177e2005-04-16 15:20:36 -07003690 return 0;
3691}
3692
Al Viro8e036fc2007-07-29 00:16:36 -07003693static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694{
3695 struct sock *sk;
3696
3697 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3698 if (!sk)
3699 goto drop;
3700
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003701 bh_lock_sock(sk);
3702
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703 BT_DBG("sk %p, len %d", sk, skb->len);
3704
3705 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3706 goto drop;
3707
3708 if (l2cap_pi(sk)->imtu < skb->len)
3709 goto drop;
3710
3711 if (!sock_queue_rcv_skb(sk, skb))
3712 goto done;
3713
3714drop:
3715 kfree_skb(skb);
3716
3717done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003718 if (sk)
3719 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720 return 0;
3721}
3722
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003723static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3724{
3725 struct sock *sk;
3726
3727 sk = l2cap_get_sock_by_scid(0, cid, conn->src);
3728 if (!sk)
3729 goto drop;
3730
3731 bh_lock_sock(sk);
3732
3733 BT_DBG("sk %p, len %d", sk, skb->len);
3734
3735 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3736 goto drop;
3737
3738 if (l2cap_pi(sk)->imtu < skb->len)
3739 goto drop;
3740
3741 if (!sock_queue_rcv_skb(sk, skb))
3742 goto done;
3743
3744drop:
3745 kfree_skb(skb);
3746
3747done:
3748 if (sk)
3749 bh_unlock_sock(sk);
3750 return 0;
3751}
3752
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3754{
3755 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003756 u16 cid, len;
3757 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758
3759 skb_pull(skb, L2CAP_HDR_SIZE);
3760 cid = __le16_to_cpu(lh->cid);
3761 len = __le16_to_cpu(lh->len);
3762
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003763 if (len != skb->len) {
3764 kfree_skb(skb);
3765 return;
3766 }
3767
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3769
3770 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003771 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003772 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773 l2cap_sig_channel(conn, skb);
3774 break;
3775
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003776 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003777 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778 skb_pull(skb, 2);
3779 l2cap_conless_channel(conn, psm, skb);
3780 break;
3781
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003782 case L2CAP_CID_LE_DATA:
3783 l2cap_att_channel(conn, cid, skb);
3784 break;
3785
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786 default:
3787 l2cap_data_channel(conn, cid, skb);
3788 break;
3789 }
3790}
3791
3792/* ---- L2CAP interface with lower layer (HCI) ---- */
3793
3794static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3795{
3796 int exact = 0, lm1 = 0, lm2 = 0;
3797 register struct sock *sk;
3798 struct hlist_node *node;
3799
3800 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003801 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802
3803 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3804
3805 /* Find listening sockets and check their link_mode */
3806 read_lock(&l2cap_sk_list.lock);
3807 sk_for_each(sk, node, &l2cap_sk_list.head) {
3808 if (sk->sk_state != BT_LISTEN)
3809 continue;
3810
3811 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003812 lm1 |= HCI_LM_ACCEPT;
3813 if (l2cap_pi(sk)->role_switch)
3814 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003816 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3817 lm2 |= HCI_LM_ACCEPT;
3818 if (l2cap_pi(sk)->role_switch)
3819 lm2 |= HCI_LM_MASTER;
3820 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821 }
3822 read_unlock(&l2cap_sk_list.lock);
3823
3824 return exact ? lm1 : lm2;
3825}
3826
3827static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3828{
Marcel Holtmann01394182006-07-03 10:02:46 +02003829 struct l2cap_conn *conn;
3830
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3832
Ville Tervoacd7d372011-02-10 22:38:49 -03003833 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003834 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835
3836 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837 conn = l2cap_conn_add(hcon, status);
3838 if (conn)
3839 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003840 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 l2cap_conn_del(hcon, bt_err(status));
3842
3843 return 0;
3844}
3845
Marcel Holtmann2950f212009-02-12 14:02:50 +01003846static int l2cap_disconn_ind(struct hci_conn *hcon)
3847{
3848 struct l2cap_conn *conn = hcon->l2cap_data;
3849
3850 BT_DBG("hcon %p", hcon);
3851
3852 if (hcon->type != ACL_LINK || !conn)
3853 return 0x13;
3854
3855 return conn->disc_reason;
3856}
3857
3858static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859{
3860 BT_DBG("hcon %p reason %d", hcon, reason);
3861
Ville Tervoacd7d372011-02-10 22:38:49 -03003862 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003863 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864
3865 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003866
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867 return 0;
3868}
3869
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003870static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3871{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003872 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003873 return;
3874
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003875 if (encrypt == 0x00) {
3876 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3877 l2cap_sock_clear_timer(sk);
3878 l2cap_sock_set_timer(sk, HZ * 5);
3879 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3880 __l2cap_sock_close(sk, ECONNREFUSED);
3881 } else {
3882 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3883 l2cap_sock_clear_timer(sk);
3884 }
3885}
3886
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003887static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003889 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003890 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891
Marcel Holtmann01394182006-07-03 10:02:46 +02003892 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003894
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895 BT_DBG("conn %p", conn);
3896
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003897 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003899 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003900 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003901
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902 bh_lock_sock(sk);
3903
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003904 if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003905 bh_unlock_sock(sk);
3906 continue;
3907 }
3908
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003909 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003910 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003911 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003912 bh_unlock_sock(sk);
3913 continue;
3914 }
3915
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003916 if (sk->sk_state == BT_CONNECT) {
3917 if (!status) {
3918 struct l2cap_conn_req req;
3919 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3920 req.psm = l2cap_pi(sk)->psm;
3921
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003922 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003923 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003924
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003925 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003926 L2CAP_CONN_REQ, sizeof(req), &req);
3927 } else {
3928 l2cap_sock_clear_timer(sk);
3929 l2cap_sock_set_timer(sk, HZ / 10);
3930 }
3931 } else if (sk->sk_state == BT_CONNECT2) {
3932 struct l2cap_conn_rsp rsp;
3933 __u16 result;
3934
3935 if (!status) {
3936 sk->sk_state = BT_CONFIG;
3937 result = L2CAP_CR_SUCCESS;
3938 } else {
3939 sk->sk_state = BT_DISCONN;
3940 l2cap_sock_set_timer(sk, HZ / 10);
3941 result = L2CAP_CR_SEC_BLOCK;
3942 }
3943
3944 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3945 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3946 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003947 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003948 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
3949 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950 }
3951
Linus Torvalds1da177e2005-04-16 15:20:36 -07003952 bh_unlock_sock(sk);
3953 }
3954
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003955 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003956
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957 return 0;
3958}
3959
3960static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3961{
3962 struct l2cap_conn *conn = hcon->l2cap_data;
3963
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003964 if (!conn)
3965 conn = l2cap_conn_add(hcon, 0);
3966
3967 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968 goto drop;
3969
3970 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3971
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003972 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003974 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003975 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003976 int len;
3977
3978 if (conn->rx_len) {
3979 BT_ERR("Unexpected start frame (len %d)", skb->len);
3980 kfree_skb(conn->rx_skb);
3981 conn->rx_skb = NULL;
3982 conn->rx_len = 0;
3983 l2cap_conn_unreliable(conn, ECOMM);
3984 }
3985
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003986 /* Start fragment always begin with Basic L2CAP header */
3987 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988 BT_ERR("Frame is too short (len %d)", skb->len);
3989 l2cap_conn_unreliable(conn, ECOMM);
3990 goto drop;
3991 }
3992
3993 hdr = (struct l2cap_hdr *) skb->data;
3994 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003995 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996
3997 if (len == skb->len) {
3998 /* Complete frame received */
3999 l2cap_recv_frame(conn, skb);
4000 return 0;
4001 }
4002
4003 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4004
4005 if (skb->len > len) {
4006 BT_ERR("Frame is too long (len %d, expected len %d)",
4007 skb->len, len);
4008 l2cap_conn_unreliable(conn, ECOMM);
4009 goto drop;
4010 }
4011
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004012 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004013
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004014 if (chan && chan->sk) {
4015 struct sock *sk = chan->sk;
4016
4017 if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
4018 BT_ERR("Frame exceeding recv MTU (len %d, "
4019 "MTU %d)", len,
4020 l2cap_pi(sk)->imtu);
4021 bh_unlock_sock(sk);
4022 l2cap_conn_unreliable(conn, ECOMM);
4023 goto drop;
4024 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004025 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004026 }
4027
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004029 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4030 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031 goto drop;
4032
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004033 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004034 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035 conn->rx_len = len - skb->len;
4036 } else {
4037 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4038
4039 if (!conn->rx_len) {
4040 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4041 l2cap_conn_unreliable(conn, ECOMM);
4042 goto drop;
4043 }
4044
4045 if (skb->len > conn->rx_len) {
4046 BT_ERR("Fragment is too long (len %d, expected %d)",
4047 skb->len, conn->rx_len);
4048 kfree_skb(conn->rx_skb);
4049 conn->rx_skb = NULL;
4050 conn->rx_len = 0;
4051 l2cap_conn_unreliable(conn, ECOMM);
4052 goto drop;
4053 }
4054
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004055 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004056 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057 conn->rx_len -= skb->len;
4058
4059 if (!conn->rx_len) {
4060 /* Complete frame received */
4061 l2cap_recv_frame(conn, conn->rx_skb);
4062 conn->rx_skb = NULL;
4063 }
4064 }
4065
4066drop:
4067 kfree_skb(skb);
4068 return 0;
4069}
4070
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004071static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072{
4073 struct sock *sk;
4074 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075
4076 read_lock_bh(&l2cap_sk_list.lock);
4077
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004078 sk_for_each(sk, node, &l2cap_sk_list.head) {
4079 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004081 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 +01004082 batostr(&bt_sk(sk)->src),
4083 batostr(&bt_sk(sk)->dst),
4084 sk->sk_state, __le16_to_cpu(pi->psm),
4085 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004086 pi->imtu, pi->omtu, pi->sec_level,
4087 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004088 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004091
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004092 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093}
4094
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004095static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4096{
4097 return single_open(file, l2cap_debugfs_show, inode->i_private);
4098}
4099
4100static const struct file_operations l2cap_debugfs_fops = {
4101 .open = l2cap_debugfs_open,
4102 .read = seq_read,
4103 .llseek = seq_lseek,
4104 .release = single_release,
4105};
4106
4107static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004108
Linus Torvalds1da177e2005-04-16 15:20:36 -07004109static struct hci_proto l2cap_hci_proto = {
4110 .name = "L2CAP",
4111 .id = HCI_PROTO_L2CAP,
4112 .connect_ind = l2cap_connect_ind,
4113 .connect_cfm = l2cap_connect_cfm,
4114 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004115 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004116 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117 .recv_acldata = l2cap_recv_acldata
4118};
4119
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004120int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121{
4122 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004123
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004124 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125 if (err < 0)
4126 return err;
4127
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004128 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004129 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004130 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131 goto error;
4132 }
4133
4134 err = hci_register_proto(&l2cap_hci_proto);
4135 if (err < 0) {
4136 BT_ERR("L2CAP protocol registration failed");
4137 bt_sock_unregister(BTPROTO_L2CAP);
4138 goto error;
4139 }
4140
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004141 if (bt_debugfs) {
4142 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4143 bt_debugfs, NULL, &l2cap_debugfs_fops);
4144 if (!l2cap_debugfs)
4145 BT_ERR("Failed to create L2CAP debug file");
4146 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148 return 0;
4149
4150error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004151 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004152 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153 return err;
4154}
4155
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004156void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004158 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004160 flush_workqueue(_busy_wq);
4161 destroy_workqueue(_busy_wq);
4162
Linus Torvalds1da177e2005-04-16 15:20:36 -07004163 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4164 BT_ERR("L2CAP protocol unregistration failed");
4165
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004166 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004167}
4168
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004169module_param(disable_ertm, bool, 0644);
4170MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");