blob: 17b5b1cd96579e352b2f3bff0bb5d9b7d9406ff2 [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>
Anderson Brigliab501d6a2011-06-07 18:46:31 -030057#include <net/bluetooth/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020059int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020060
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070061static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010062static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Johannes Bergb5ad8b72011-06-01 08:54:45 +020064static LIST_HEAD(chan_list);
65static DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
Linus Torvalds1da177e2005-04-16 15:20:36 -070067static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
68 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030069static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
70 void *data);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -030071static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030072static void l2cap_send_disconn_req(struct l2cap_conn *conn,
73 struct l2cap_chan *chan, int err);
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. Padovan71ba0e52011-05-17 14:34:52 -030078
79static inline void chan_hold(struct l2cap_chan *c)
80{
81 atomic_inc(&c->refcnt);
82}
83
84static inline void chan_put(struct l2cap_chan *c)
85{
86 if (atomic_dec_and_test(&c->refcnt))
87 kfree(c);
88}
89
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030090static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020091{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030092 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030093
94 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030095 if (c->dcid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030096 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020097 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030098 return NULL;
99
Marcel Holtmann01394182006-07-03 10:02:46 +0200100}
101
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300102static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200103{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300104 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300105
106 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300107 if (c->scid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300108 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200109 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300110 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200111}
112
113/* Find channel with given SCID.
114 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300115static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200116{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300117 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300118
119 read_lock(&conn->chan_lock);
120 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300121 if (c)
122 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300123 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300124 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200125}
126
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300127static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200128{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300129 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300130
131 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300132 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300133 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200134 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300135 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200136}
137
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300138static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200139{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300140 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300141
142 read_lock(&conn->chan_lock);
143 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300144 if (c)
145 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300146 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300147 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200148}
149
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300150static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300151{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300152 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300153
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300154 list_for_each_entry(c, &chan_list, global_l) {
155 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300156 goto found;
157 }
158
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300159 c = NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300160found:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300161 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300162}
163
164int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
165{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300166 int err;
167
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300168 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300169
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300170 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300171 err = -EADDRINUSE;
172 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300173 }
174
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300175 if (psm) {
176 chan->psm = psm;
177 chan->sport = psm;
178 err = 0;
179 } else {
180 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300181
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300182 err = -EINVAL;
183 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300184 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300185 chan->psm = cpu_to_le16(p);
186 chan->sport = cpu_to_le16(p);
187 err = 0;
188 break;
189 }
190 }
191
192done:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300193 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300194 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300195}
196
197int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
198{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300199 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300200
201 chan->scid = scid;
202
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300203 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300204
205 return 0;
206}
207
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300208static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200209{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300210 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200211
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300212 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300213 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200214 return cid;
215 }
216
217 return 0;
218}
219
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300220static void l2cap_set_timer(struct l2cap_chan *chan, struct timer_list *timer, long timeout)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300221{
Mat Martineau774e5652011-06-29 14:35:20 -0700222 BT_DBG("chan %p state %d timeout %ld", chan->sk, chan->state, timeout);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300223
Mat Martineau942ecc92011-06-29 14:35:21 -0700224 if (!mod_timer(timer, jiffies + msecs_to_jiffies(timeout)))
Mat Martineau774e5652011-06-29 14:35:20 -0700225 chan_hold(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300226}
227
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300228static void l2cap_clear_timer(struct l2cap_chan *chan, struct timer_list *timer)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300229{
Mat Martineau774e5652011-06-29 14:35:20 -0700230 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300231
Mat Martineau774e5652011-06-29 14:35:20 -0700232 if (timer_pending(timer) && del_timer(timer))
233 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300234}
235
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300236static void l2cap_state_change(struct l2cap_chan *chan, int state)
237{
238 chan->state = state;
239 chan->ops->state_change(chan->data, state);
240}
241
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300242static void l2cap_chan_timeout(unsigned long arg)
243{
244 struct l2cap_chan *chan = (struct l2cap_chan *) arg;
245 struct sock *sk = chan->sk;
246 int reason;
247
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300248 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300249
250 bh_lock_sock(sk);
251
252 if (sock_owned_by_user(sk)) {
253 /* sk is owned by user. Try again later */
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -0200254 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300255 bh_unlock_sock(sk);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300256 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300257 return;
258 }
259
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300260 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300261 reason = ECONNREFUSED;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300262 else if (chan->state == BT_CONNECT &&
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300263 chan->sec_level != BT_SECURITY_SDP)
264 reason = ECONNREFUSED;
265 else
266 reason = ETIMEDOUT;
267
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300268 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300269
270 bh_unlock_sock(sk);
271
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300272 chan->ops->close(chan->data);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300273 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300274}
275
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300276struct l2cap_chan *l2cap_chan_create(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200277{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300278 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200279
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300280 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
281 if (!chan)
282 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200283
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300284 chan->sk = sk;
285
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300286 write_lock_bh(&chan_list_lock);
287 list_add(&chan->global_l, &chan_list);
288 write_unlock_bh(&chan_list_lock);
289
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300290 setup_timer(&chan->chan_timer, l2cap_chan_timeout, (unsigned long) chan);
291
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300292 chan->state = BT_OPEN;
293
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300294 atomic_set(&chan->refcnt, 1);
295
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300296 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200297}
298
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300299void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300300{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300301 write_lock_bh(&chan_list_lock);
302 list_del(&chan->global_l);
303 write_unlock_bh(&chan_list_lock);
304
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300305 chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300306}
307
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300308static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200309{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300310 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300311 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200312
Marcel Holtmann2950f212009-02-12 14:02:50 +0100313 conn->disc_reason = 0x13;
314
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300315 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200316
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300317 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
Ville Tervob62f3282011-02-10 22:38:50 -0300318 if (conn->hcon->type == LE_LINK) {
319 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300320 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300321 chan->scid = L2CAP_CID_LE_DATA;
322 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300323 } else {
324 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300325 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300326 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300327 }
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300328 } else if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200329 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300330 chan->scid = L2CAP_CID_CONN_LESS;
331 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300332 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200333 } else {
334 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300335 chan->scid = L2CAP_CID_SIGNALING;
336 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300337 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200338 }
339
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300340 chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300341
342 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200343}
344
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900345/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200346 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300347static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200348{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300349 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300350 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200351 struct sock *parent = bt_sk(sk)->parent;
352
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300353 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200354
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300355 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200356
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900357 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300358 /* Delete from channel list */
359 write_lock_bh(&conn->chan_lock);
360 list_del(&chan->list);
361 write_unlock_bh(&conn->chan_lock);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300362 chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300363
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300364 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200365 hci_conn_put(conn->hcon);
366 }
367
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300368 l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200369 sock_set_flag(sk, SOCK_ZAPPED);
370
371 if (err)
372 sk->sk_err = err;
373
374 if (parent) {
375 bt_accept_unlink(sk);
376 parent->sk_data_ready(parent, 0);
377 } else
378 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300379
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300380 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
381 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300382 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300383
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300384 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300385
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300386 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300387 struct srej_list *l, *tmp;
388
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300389 __clear_retrans_timer(chan);
390 __clear_monitor_timer(chan);
391 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300392
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300393 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300394
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300395 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300396 list_del(&l->list);
397 kfree(l);
398 }
399 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200400}
401
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300402static void l2cap_chan_cleanup_listen(struct sock *parent)
403{
404 struct sock *sk;
405
406 BT_DBG("parent %p", parent);
407
408 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300409 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300410 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300411 __clear_chan_timer(chan);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300412 lock_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300413 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300414 release_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300415 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300416 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300417}
418
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300419void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300420{
421 struct l2cap_conn *conn = chan->conn;
422 struct sock *sk = chan->sk;
423
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300424 BT_DBG("chan %p state %d socket %p", chan, chan->state, sk->sk_socket);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300425
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300426 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300427 case BT_LISTEN:
428 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300429
430 l2cap_state_change(chan, BT_CLOSED);
431 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300432 break;
433
434 case BT_CONNECTED:
435 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300436 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300437 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300438 __clear_chan_timer(chan);
439 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300440 l2cap_send_disconn_req(conn, chan, reason);
441 } else
442 l2cap_chan_del(chan, reason);
443 break;
444
445 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300446 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300447 conn->hcon->type == ACL_LINK) {
448 struct l2cap_conn_rsp rsp;
449 __u16 result;
450
451 if (bt_sk(sk)->defer_setup)
452 result = L2CAP_CR_SEC_BLOCK;
453 else
454 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300455 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300456
457 rsp.scid = cpu_to_le16(chan->dcid);
458 rsp.dcid = cpu_to_le16(chan->scid);
459 rsp.result = cpu_to_le16(result);
460 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
461 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
462 sizeof(rsp), &rsp);
463 }
464
465 l2cap_chan_del(chan, reason);
466 break;
467
468 case BT_CONNECT:
469 case BT_DISCONN:
470 l2cap_chan_del(chan, reason);
471 break;
472
473 default:
474 sock_set_flag(sk, SOCK_ZAPPED);
475 break;
476 }
477}
478
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300479static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530480{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300481 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300482 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530483 case BT_SECURITY_HIGH:
484 return HCI_AT_DEDICATED_BONDING_MITM;
485 case BT_SECURITY_MEDIUM:
486 return HCI_AT_DEDICATED_BONDING;
487 default:
488 return HCI_AT_NO_BONDING;
489 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300490 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300491 if (chan->sec_level == BT_SECURITY_LOW)
492 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530493
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300494 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530495 return HCI_AT_NO_BONDING_MITM;
496 else
497 return HCI_AT_NO_BONDING;
498 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300499 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530500 case BT_SECURITY_HIGH:
501 return HCI_AT_GENERAL_BONDING_MITM;
502 case BT_SECURITY_MEDIUM:
503 return HCI_AT_GENERAL_BONDING;
504 default:
505 return HCI_AT_NO_BONDING;
506 }
507 }
508}
509
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200510/* Service level security */
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300511static inline int l2cap_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200512{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300513 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100514 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200515
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300516 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100517
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300518 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200519}
520
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200521static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200522{
523 u8 id;
524
525 /* Get next available identificator.
526 * 1 - 128 are used by kernel.
527 * 129 - 199 are reserved.
528 * 200 - 254 are used by utilities like l2ping, etc.
529 */
530
531 spin_lock_bh(&conn->lock);
532
533 if (++conn->tx_ident > 128)
534 conn->tx_ident = 1;
535
536 id = conn->tx_ident;
537
538 spin_unlock_bh(&conn->lock);
539
540 return id;
541}
542
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300543static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200544{
545 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200546 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200547
548 BT_DBG("code 0x%2.2x", code);
549
550 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300551 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200552
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200553 if (lmp_no_flush_capable(conn->hcon->hdev))
554 flags = ACL_START_NO_FLUSH;
555 else
556 flags = ACL_START;
557
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700558 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
559
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200560 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200561}
562
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300563static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300564{
565 struct sk_buff *skb;
566 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300567 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300568 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200569 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300570
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300571 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300572 return;
573
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300574 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300575 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300576
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300577 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300578
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300579 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300580 control |= L2CAP_CTRL_FRAME_TYPE;
581
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300582 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300583 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300584
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300585 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300586 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300587
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300588 skb = bt_skb_alloc(count, GFP_ATOMIC);
589 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300590 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300591
592 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300593 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300594 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300595 put_unaligned_le16(control, skb_put(skb, 2));
596
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300597 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300598 u16 fcs = crc16(0, (u8 *)lh, count - 2);
599 put_unaligned_le16(fcs, skb_put(skb, 2));
600 }
601
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200602 if (lmp_no_flush_capable(conn->hcon->hdev))
603 flags = ACL_START_NO_FLUSH;
604 else
605 flags = ACL_START;
606
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700607 bt_cb(skb)->force_active = chan->force_active;
608
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300609 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300610}
611
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300612static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300613{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300614 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300615 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300616 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300617 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300618 control |= L2CAP_SUPER_RCV_READY;
619
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300620 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300621
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300622 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300623}
624
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300625static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300626{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300627 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300628}
629
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300630static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200631{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300632 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200633
634 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100635 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
636 return;
637
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300638 if (l2cap_check_security(chan) &&
639 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200640 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300641 req.scid = cpu_to_le16(chan->scid);
642 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200643
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300644 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300645 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200646
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300647 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
648 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200649 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200650 } else {
651 struct l2cap_info_req req;
652 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
653
654 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
655 conn->info_ident = l2cap_get_ident(conn);
656
657 mod_timer(&conn->info_timer, jiffies +
658 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
659
660 l2cap_send_cmd(conn, conn->info_ident,
661 L2CAP_INFO_REQ, sizeof(req), &req);
662 }
663}
664
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300665static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
666{
667 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300668 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300669 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
670
671 switch (mode) {
672 case L2CAP_MODE_ERTM:
673 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
674 case L2CAP_MODE_STREAMING:
675 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
676 default:
677 return 0x00;
678 }
679}
680
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300681static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300682{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300683 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300684 struct l2cap_disconn_req req;
685
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300686 if (!conn)
687 return;
688
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300689 sk = chan->sk;
690
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300691 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300692 __clear_retrans_timer(chan);
693 __clear_monitor_timer(chan);
694 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300695 }
696
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300697 req.dcid = cpu_to_le16(chan->dcid);
698 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300699 l2cap_send_cmd(conn, l2cap_get_ident(conn),
700 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300701
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300702 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300703 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300704}
705
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200707static void l2cap_conn_start(struct l2cap_conn *conn)
708{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300709 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200710
711 BT_DBG("conn %p", conn);
712
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300713 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200714
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300715 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300716 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300717
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200718 bh_lock_sock(sk);
719
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300720 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200721 bh_unlock_sock(sk);
722 continue;
723 }
724
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300725 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300726 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300727
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300728 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300729 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300730 bh_unlock_sock(sk);
731 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200732 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300733
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300734 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
735 && test_bit(CONF_STATE2_DEVICE,
736 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300737 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300738 * so release the lock */
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300739 read_unlock(&conn->chan_lock);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300740 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300741 read_lock(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300742 bh_unlock_sock(sk);
743 continue;
744 }
745
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300746 req.scid = cpu_to_le16(chan->scid);
747 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300748
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300749 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300750 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300751
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300752 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
753 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300754
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300755 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200756 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300757 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300758 rsp.scid = cpu_to_le16(chan->dcid);
759 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200760
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300761 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100762 if (bt_sk(sk)->defer_setup) {
763 struct sock *parent = bt_sk(sk)->parent;
764 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
765 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000766 if (parent)
767 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100768
769 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300770 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100771 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
772 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
773 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200774 } else {
775 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
776 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
777 }
778
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300779 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
780 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300781
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300782 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300783 rsp.result != L2CAP_CR_SUCCESS) {
784 bh_unlock_sock(sk);
785 continue;
786 }
787
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300788 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300789 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300790 l2cap_build_conf_req(chan, buf), buf);
791 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200792 }
793
794 bh_unlock_sock(sk);
795 }
796
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300797 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200798}
799
Ville Tervob62f3282011-02-10 22:38:50 -0300800/* Find socket with cid and source bdaddr.
801 * Returns closest match, locked.
802 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300803static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300804{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300805 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300806
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300807 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300808
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300809 list_for_each_entry(c, &chan_list, global_l) {
810 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300811
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300812 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300813 continue;
814
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300815 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300816 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300817 if (!bacmp(&bt_sk(sk)->src, src)) {
818 read_unlock(&chan_list_lock);
819 return c;
820 }
Ville Tervob62f3282011-02-10 22:38:50 -0300821
822 /* Closest match */
823 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300824 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300825 }
826 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300827
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300828 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300829
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300830 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300831}
832
833static void l2cap_le_conn_ready(struct l2cap_conn *conn)
834{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300835 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300836 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300837
838 BT_DBG("");
839
840 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300841 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300842 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300843 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300844 return;
845
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300846 parent = pchan->sk;
847
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300848 bh_lock_sock(parent);
849
Ville Tervob62f3282011-02-10 22:38:50 -0300850 /* Check for backlog size */
851 if (sk_acceptq_is_full(parent)) {
852 BT_DBG("backlog full %d", parent->sk_ack_backlog);
853 goto clean;
854 }
855
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300856 chan = pchan->ops->new_connection(pchan->data);
857 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300858 goto clean;
859
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300860 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300861
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300862 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300863
864 hci_conn_hold(conn->hcon);
865
Ville Tervob62f3282011-02-10 22:38:50 -0300866 bacpy(&bt_sk(sk)->src, conn->src);
867 bacpy(&bt_sk(sk)->dst, conn->dst);
868
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300869 bt_accept_enqueue(parent, sk);
870
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300871 __l2cap_chan_add(conn, chan);
872
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300873 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300874
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300875 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300876 parent->sk_data_ready(parent, 0);
877
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300878 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300879
880clean:
881 bh_unlock_sock(parent);
882}
883
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300884static void l2cap_chan_ready(struct sock *sk)
885{
886 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
887 struct sock *parent = bt_sk(sk)->parent;
888
889 BT_DBG("sk %p, parent %p", sk, parent);
890
891 chan->conf_state = 0;
892 __clear_chan_timer(chan);
893
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300894 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300895 sk->sk_state_change(sk);
896
897 if (parent)
898 parent->sk_data_ready(parent, 0);
899}
900
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200901static void l2cap_conn_ready(struct l2cap_conn *conn)
902{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300903 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200904
905 BT_DBG("conn %p", conn);
906
Ville Tervob62f3282011-02-10 22:38:50 -0300907 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
908 l2cap_le_conn_ready(conn);
909
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300910 if (conn->hcon->out && conn->hcon->type == LE_LINK)
911 smp_conn_security(conn, conn->hcon->pending_sec_level);
912
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300913 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200914
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300915 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300916 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300917
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200918 bh_lock_sock(sk);
919
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300920 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300921 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300922 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300923
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300924 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300925 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300926 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200927 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300928
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300929 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300930 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200931
932 bh_unlock_sock(sk);
933 }
934
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300935 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200936}
937
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200938/* Notify sockets that we cannot guaranty reliability anymore */
939static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
940{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300941 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200942
943 BT_DBG("conn %p", conn);
944
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300945 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200946
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300947 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300948 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300949
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300950 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200951 sk->sk_err = err;
952 }
953
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300954 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200955}
956
957static void l2cap_info_timeout(unsigned long arg)
958{
959 struct l2cap_conn *conn = (void *) arg;
960
Marcel Holtmann984947d2009-02-06 23:35:19 +0100961 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100962 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100963
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200964 l2cap_conn_start(conn);
965}
966
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300967static void l2cap_conn_del(struct hci_conn *hcon, int err)
968{
969 struct l2cap_conn *conn = hcon->l2cap_data;
970 struct l2cap_chan *chan, *l;
971 struct sock *sk;
972
973 if (!conn)
974 return;
975
976 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
977
978 kfree_skb(conn->rx_skb);
979
980 /* Kill channels */
981 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
982 sk = chan->sk;
983 bh_lock_sock(sk);
984 l2cap_chan_del(chan, err);
985 bh_unlock_sock(sk);
986 chan->ops->close(chan->data);
987 }
988
989 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
990 del_timer_sync(&conn->info_timer);
991
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300992 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) {
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300993 del_timer(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300994 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300995 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300996
997 hcon->l2cap_data = NULL;
998 kfree(conn);
999}
1000
1001static void security_timeout(unsigned long arg)
1002{
1003 struct l2cap_conn *conn = (void *) arg;
1004
1005 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1006}
1007
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1009{
Marcel Holtmann01394182006-07-03 10:02:46 +02001010 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011
Marcel Holtmann01394182006-07-03 10:02:46 +02001012 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 return conn;
1014
Marcel Holtmann01394182006-07-03 10:02:46 +02001015 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1016 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018
1019 hcon->l2cap_data = conn;
1020 conn->hcon = hcon;
1021
Marcel Holtmann01394182006-07-03 10:02:46 +02001022 BT_DBG("hcon %p conn %p", hcon, conn);
1023
Ville Tervoacd7d372011-02-10 22:38:49 -03001024 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1025 conn->mtu = hcon->hdev->le_mtu;
1026 else
1027 conn->mtu = hcon->hdev->acl_mtu;
1028
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 conn->src = &hcon->hdev->bdaddr;
1030 conn->dst = &hcon->dst;
1031
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001032 conn->feat_mask = 0;
1033
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001035 rwlock_init(&conn->chan_lock);
1036
1037 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001039 if (hcon->type == LE_LINK)
1040 setup_timer(&conn->security_timer, security_timeout,
1041 (unsigned long) conn);
1042 else
Ville Tervob62f3282011-02-10 22:38:50 -03001043 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +00001044 (unsigned long) conn);
1045
Marcel Holtmann2950f212009-02-12 14:02:50 +01001046 conn->disc_reason = 0x13;
1047
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 return conn;
1049}
1050
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001051static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001053 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001054 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001055 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056}
1057
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059
1060/* Find socket with psm and source bdaddr.
1061 * Returns closest match.
1062 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001063static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001065 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001067 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001068
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001069 list_for_each_entry(c, &chan_list, global_l) {
1070 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001071
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001072 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 continue;
1074
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001075 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001077 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001078 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001079 return c;
1080 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081
1082 /* Closest match */
1083 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001084 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 }
1086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001088 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001089
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001090 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091}
1092
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001093int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001095 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 bdaddr_t *src = &bt_sk(sk)->src;
1097 bdaddr_t *dst = &bt_sk(sk)->dst;
1098 struct l2cap_conn *conn;
1099 struct hci_conn *hcon;
1100 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001101 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001102 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001104 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001105 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001107 hdev = hci_get_route(dst, src);
1108 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 return -EHOSTUNREACH;
1110
1111 hci_dev_lock_bh(hdev);
1112
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001113 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001114
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001115 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001116 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001117 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001118 else
1119 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001120 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001121
Ville Tervo30e76272011-02-22 16:10:53 -03001122 if (IS_ERR(hcon)) {
1123 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001125 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126
1127 conn = l2cap_conn_add(hcon, 0);
1128 if (!conn) {
1129 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001130 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 goto done;
1132 }
1133
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 /* Update source addr of the socket */
1135 bacpy(src, conn->src);
1136
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001137 l2cap_chan_add(conn, chan);
1138
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001139 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001140 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141
1142 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001143 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001144 __clear_chan_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001145 if (l2cap_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001146 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001147 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001148 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 }
1150
Ville Tervo30e76272011-02-22 16:10:53 -03001151 err = 0;
1152
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153done:
1154 hci_dev_unlock_bh(hdev);
1155 hci_dev_put(hdev);
1156 return err;
1157}
1158
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001159int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001160{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001161 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001162 DECLARE_WAITQUEUE(wait, current);
1163 int err = 0;
1164 int timeo = HZ/5;
1165
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001166 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001167 set_current_state(TASK_INTERRUPTIBLE);
1168 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001169 if (!timeo)
1170 timeo = HZ/5;
1171
1172 if (signal_pending(current)) {
1173 err = sock_intr_errno(timeo);
1174 break;
1175 }
1176
1177 release_sock(sk);
1178 timeo = schedule_timeout(timeo);
1179 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001180 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001181
1182 err = sock_error(sk);
1183 if (err)
1184 break;
1185 }
1186 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001187 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001188 return err;
1189}
1190
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001191static void l2cap_monitor_timeout(unsigned long arg)
1192{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001193 struct l2cap_chan *chan = (void *) arg;
1194 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001195
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001196 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001197
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001198 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001199 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001200 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001201 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001202 return;
1203 }
1204
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001205 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001206 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001207
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001208 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001209 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001210}
1211
1212static void l2cap_retrans_timeout(unsigned long arg)
1213{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001214 struct l2cap_chan *chan = (void *) arg;
1215 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001216
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001217 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001218
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001219 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001220 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001221 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001222
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001223 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001224
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001225 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001226 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001227}
1228
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001229static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001230{
1231 struct sk_buff *skb;
1232
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001233 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001234 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001235 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001236 break;
1237
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001238 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001239 kfree_skb(skb);
1240
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001241 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001242 }
1243
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001244 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001245 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001246}
1247
Szymon Janc67c9e842011-07-28 16:24:33 +02001248static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001249{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001250 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001251 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001252
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001253 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001254
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001255 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001256 flags = ACL_START_NO_FLUSH;
1257 else
1258 flags = ACL_START;
1259
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -07001260 bt_cb(skb)->force_active = chan->force_active;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001261 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001262}
1263
Szymon Janc67c9e842011-07-28 16:24:33 +02001264static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001265{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001266 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001267 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001268
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001269 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001270 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001271 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001272 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001273
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001274 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001275 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1276 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001277 }
1278
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001279 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001280
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001281 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001282 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001283}
1284
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001285static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001286{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001287 struct sk_buff *skb, *tx_skb;
1288 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001289
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001290 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001291 if (!skb)
1292 return;
1293
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001294 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001295 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001296 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001297
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001298 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001299 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001300
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001301 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001302
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001303 if (chan->remote_max_tx &&
1304 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001305 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001306 return;
1307 }
1308
1309 tx_skb = skb_clone(skb, GFP_ATOMIC);
1310 bt_cb(skb)->retries++;
1311 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001312 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001313
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001314 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001315 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001316
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001317 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001318 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001319
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001320 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1321
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001322 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001323 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1324 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1325 }
1326
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001327 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001328}
1329
Szymon Janc67c9e842011-07-28 16:24:33 +02001330static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001331{
1332 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001333 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001334 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001335
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001336 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001337 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001338
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001339 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001340
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001341 if (chan->remote_max_tx &&
1342 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001343 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001344 break;
1345 }
1346
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001347 tx_skb = skb_clone(skb, GFP_ATOMIC);
1348
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001349 bt_cb(skb)->retries++;
1350
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001351 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001352 control &= L2CAP_CTRL_SAR;
1353
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001354 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001355 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001356
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001357 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1358 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001359 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1360
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001361
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001362 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001363 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1364 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1365 }
1366
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001367 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001368
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001369 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001370
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001371 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1372 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001373
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301374 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001375 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301376
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001377 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001378
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001379 if (skb_queue_is_last(&chan->tx_q, skb))
1380 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001381 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001382 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001383
1384 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001385 }
1386
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001387 return nsent;
1388}
1389
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001390static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001391{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001392 int ret;
1393
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001394 if (!skb_queue_empty(&chan->tx_q))
1395 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001396
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001397 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001398 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001399 return ret;
1400}
1401
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001402static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001403{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001404 u16 control = 0;
1405
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001406 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001407
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001408 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001409 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001410 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001411 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001412 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001413 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001414
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001415 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001416 return;
1417
1418 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001419 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001420}
1421
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001422static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001423{
1424 struct srej_list *tail;
1425 u16 control;
1426
1427 control = L2CAP_SUPER_SELECT_REJECT;
1428 control |= L2CAP_CTRL_FINAL;
1429
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001430 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001431 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1432
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001433 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001434}
1435
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001436static 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 -07001437{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001438 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001439 struct sk_buff **frag;
1440 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001442 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001443 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
1445 sent += count;
1446 len -= count;
1447
1448 /* Continuation fragments (no L2CAP header) */
1449 frag = &skb_shinfo(skb)->frag_list;
1450 while (len) {
1451 count = min_t(unsigned int, conn->mtu, len);
1452
1453 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1454 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001455 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001456 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1457 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458
1459 sent += count;
1460 len -= count;
1461
1462 frag = &(*frag)->next;
1463 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
1465 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001466}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
Szymon Janc67c9e842011-07-28 16:24:33 +02001468static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001469{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001470 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001471 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001472 struct sk_buff *skb;
1473 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1474 struct l2cap_hdr *lh;
1475
1476 BT_DBG("sk %p len %d", sk, (int)len);
1477
1478 count = min_t(unsigned int, (conn->mtu - hlen), len);
1479 skb = bt_skb_send_alloc(sk, count + hlen,
1480 msg->msg_flags & MSG_DONTWAIT, &err);
1481 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001482 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001483
1484 /* Create L2CAP header */
1485 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001486 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001487 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001488 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001489
1490 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1491 if (unlikely(err < 0)) {
1492 kfree_skb(skb);
1493 return ERR_PTR(err);
1494 }
1495 return skb;
1496}
1497
Szymon Janc67c9e842011-07-28 16:24:33 +02001498static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001499{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001500 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001501 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001502 struct sk_buff *skb;
1503 int err, count, hlen = L2CAP_HDR_SIZE;
1504 struct l2cap_hdr *lh;
1505
1506 BT_DBG("sk %p len %d", sk, (int)len);
1507
1508 count = min_t(unsigned int, (conn->mtu - hlen), len);
1509 skb = bt_skb_send_alloc(sk, count + hlen,
1510 msg->msg_flags & MSG_DONTWAIT, &err);
1511 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001512 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001513
1514 /* Create L2CAP header */
1515 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001516 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001517 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1518
1519 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1520 if (unlikely(err < 0)) {
1521 kfree_skb(skb);
1522 return ERR_PTR(err);
1523 }
1524 return skb;
1525}
1526
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001527static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1528 struct msghdr *msg, size_t len,
1529 u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001530{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001531 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001532 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001533 struct sk_buff *skb;
1534 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1535 struct l2cap_hdr *lh;
1536
1537 BT_DBG("sk %p len %d", sk, (int)len);
1538
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001539 if (!conn)
1540 return ERR_PTR(-ENOTCONN);
1541
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001542 if (sdulen)
1543 hlen += 2;
1544
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001545 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001546 hlen += 2;
1547
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001548 count = min_t(unsigned int, (conn->mtu - hlen), len);
1549 skb = bt_skb_send_alloc(sk, count + hlen,
1550 msg->msg_flags & MSG_DONTWAIT, &err);
1551 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001552 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001553
1554 /* Create L2CAP header */
1555 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001556 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001557 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1558 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001559 if (sdulen)
1560 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001561
1562 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1563 if (unlikely(err < 0)) {
1564 kfree_skb(skb);
1565 return ERR_PTR(err);
1566 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001567
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001568 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001569 put_unaligned_le16(0, skb_put(skb, 2));
1570
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001571 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001572 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573}
1574
Szymon Janc67c9e842011-07-28 16:24:33 +02001575static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001576{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001577 struct sk_buff *skb;
1578 struct sk_buff_head sar_queue;
1579 u16 control;
1580 size_t size = 0;
1581
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001582 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001583 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001584 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001585 if (IS_ERR(skb))
1586 return PTR_ERR(skb);
1587
1588 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001589 len -= chan->remote_mps;
1590 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001591
1592 while (len > 0) {
1593 size_t buflen;
1594
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001595 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001596 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001597 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001598 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001599 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001600 buflen = len;
1601 }
1602
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001603 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001604 if (IS_ERR(skb)) {
1605 skb_queue_purge(&sar_queue);
1606 return PTR_ERR(skb);
1607 }
1608
1609 __skb_queue_tail(&sar_queue, skb);
1610 len -= buflen;
1611 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001612 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001613 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1614 if (chan->tx_send_head == NULL)
1615 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001616
1617 return size;
1618}
1619
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001620int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1621{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001622 struct sk_buff *skb;
1623 u16 control;
1624 int err;
1625
1626 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001627 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001628 skb = l2cap_create_connless_pdu(chan, msg, len);
1629 if (IS_ERR(skb))
1630 return PTR_ERR(skb);
1631
1632 l2cap_do_send(chan, skb);
1633 return len;
1634 }
1635
1636 switch (chan->mode) {
1637 case L2CAP_MODE_BASIC:
1638 /* Check outgoing MTU */
1639 if (len > chan->omtu)
1640 return -EMSGSIZE;
1641
1642 /* Create a basic PDU */
1643 skb = l2cap_create_basic_pdu(chan, msg, len);
1644 if (IS_ERR(skb))
1645 return PTR_ERR(skb);
1646
1647 l2cap_do_send(chan, skb);
1648 err = len;
1649 break;
1650
1651 case L2CAP_MODE_ERTM:
1652 case L2CAP_MODE_STREAMING:
1653 /* Entire SDU fits into one PDU */
1654 if (len <= chan->remote_mps) {
1655 control = L2CAP_SDU_UNSEGMENTED;
1656 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1657 0);
1658 if (IS_ERR(skb))
1659 return PTR_ERR(skb);
1660
1661 __skb_queue_tail(&chan->tx_q, skb);
1662
1663 if (chan->tx_send_head == NULL)
1664 chan->tx_send_head = skb;
1665
1666 } else {
1667 /* Segment SDU into multiples PDUs */
1668 err = l2cap_sar_segment_sdu(chan, msg, len);
1669 if (err < 0)
1670 return err;
1671 }
1672
1673 if (chan->mode == L2CAP_MODE_STREAMING) {
1674 l2cap_streaming_send(chan);
1675 err = len;
1676 break;
1677 }
1678
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001679 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1680 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001681 err = len;
1682 break;
1683 }
1684
1685 err = l2cap_ertm_send(chan);
1686 if (err >= 0)
1687 err = len;
1688
1689 break;
1690
1691 default:
1692 BT_DBG("bad state %1.1x", chan->mode);
1693 err = -EBADFD;
1694 }
1695
1696 return err;
1697}
1698
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699/* Copy frame to all raw sockets on that connection */
1700static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1701{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001703 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704
1705 BT_DBG("conn %p", conn);
1706
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001707 read_lock(&conn->chan_lock);
1708 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001709 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001710 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 continue;
1712
1713 /* Don't send frame to the socket it came from */
1714 if (skb->sk == sk)
1715 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001716 nskb = skb_clone(skb, GFP_ATOMIC);
1717 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 continue;
1719
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001720 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 kfree_skb(nskb);
1722 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001723 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724}
1725
1726/* ---- L2CAP signalling commands ---- */
1727static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1728 u8 code, u8 ident, u16 dlen, void *data)
1729{
1730 struct sk_buff *skb, **frag;
1731 struct l2cap_cmd_hdr *cmd;
1732 struct l2cap_hdr *lh;
1733 int len, count;
1734
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001735 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1736 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737
1738 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1739 count = min_t(unsigned int, conn->mtu, len);
1740
1741 skb = bt_skb_alloc(count, GFP_ATOMIC);
1742 if (!skb)
1743 return NULL;
1744
1745 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001746 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001747
1748 if (conn->hcon->type == LE_LINK)
1749 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1750 else
1751 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752
1753 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1754 cmd->code = code;
1755 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001756 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757
1758 if (dlen) {
1759 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1760 memcpy(skb_put(skb, count), data, count);
1761 data += count;
1762 }
1763
1764 len -= skb->len;
1765
1766 /* Continuation fragments (no L2CAP header) */
1767 frag = &skb_shinfo(skb)->frag_list;
1768 while (len) {
1769 count = min_t(unsigned int, conn->mtu, len);
1770
1771 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1772 if (!*frag)
1773 goto fail;
1774
1775 memcpy(skb_put(*frag, count), data, count);
1776
1777 len -= count;
1778 data += count;
1779
1780 frag = &(*frag)->next;
1781 }
1782
1783 return skb;
1784
1785fail:
1786 kfree_skb(skb);
1787 return NULL;
1788}
1789
1790static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1791{
1792 struct l2cap_conf_opt *opt = *ptr;
1793 int len;
1794
1795 len = L2CAP_CONF_OPT_SIZE + opt->len;
1796 *ptr += len;
1797
1798 *type = opt->type;
1799 *olen = opt->len;
1800
1801 switch (opt->len) {
1802 case 1:
1803 *val = *((u8 *) opt->val);
1804 break;
1805
1806 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001807 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 break;
1809
1810 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001811 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 break;
1813
1814 default:
1815 *val = (unsigned long) opt->val;
1816 break;
1817 }
1818
1819 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1820 return len;
1821}
1822
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1824{
1825 struct l2cap_conf_opt *opt = *ptr;
1826
1827 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1828
1829 opt->type = type;
1830 opt->len = len;
1831
1832 switch (len) {
1833 case 1:
1834 *((u8 *) opt->val) = val;
1835 break;
1836
1837 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001838 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839 break;
1840
1841 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001842 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 break;
1844
1845 default:
1846 memcpy(opt->val, (void *) val, len);
1847 break;
1848 }
1849
1850 *ptr += L2CAP_CONF_OPT_SIZE + len;
1851}
1852
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001853static void l2cap_ack_timeout(unsigned long arg)
1854{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001855 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001856
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001857 bh_lock_sock(chan->sk);
1858 l2cap_send_ack(chan);
1859 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001860}
1861
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001862static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001863{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001864 struct sock *sk = chan->sk;
1865
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001866 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001867 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001868 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001869 chan->num_acked = 0;
1870 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001871
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001872 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1873 (unsigned long) chan);
1874 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1875 (unsigned long) chan);
1876 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001877
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001878 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001879
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001880 INIT_LIST_HEAD(&chan->srej_l);
1881
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001882
1883 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001884}
1885
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001886static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1887{
1888 switch (mode) {
1889 case L2CAP_MODE_STREAMING:
1890 case L2CAP_MODE_ERTM:
1891 if (l2cap_mode_supported(mode, remote_feat_mask))
1892 return mode;
1893 /* fall through */
1894 default:
1895 return L2CAP_MODE_BASIC;
1896 }
1897}
1898
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03001899static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001902 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 void *ptr = req->data;
1904
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001905 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001907 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001908 goto done;
1909
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001910 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001911 case L2CAP_MODE_STREAMING:
1912 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001913 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001914 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001915
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001916 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001917 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001918 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001919 break;
1920 }
1921
1922done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001923 if (chan->imtu != L2CAP_DEFAULT_MTU)
1924 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001925
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001926 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001927 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001928 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1929 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001930 break;
1931
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001932 rfc.mode = L2CAP_MODE_BASIC;
1933 rfc.txwin_size = 0;
1934 rfc.max_transmit = 0;
1935 rfc.retrans_timeout = 0;
1936 rfc.monitor_timeout = 0;
1937 rfc.max_pdu_size = 0;
1938
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001939 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1940 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001941 break;
1942
1943 case L2CAP_MODE_ERTM:
1944 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001945 rfc.txwin_size = chan->tx_win;
1946 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001947 rfc.retrans_timeout = 0;
1948 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001949 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001950 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1951 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001952
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001953 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1954 (unsigned long) &rfc);
1955
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001956 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001957 break;
1958
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001959 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001960 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001961 chan->fcs = L2CAP_FCS_NONE;
1962 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001963 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001964 break;
1965
1966 case L2CAP_MODE_STREAMING:
1967 rfc.mode = L2CAP_MODE_STREAMING;
1968 rfc.txwin_size = 0;
1969 rfc.max_transmit = 0;
1970 rfc.retrans_timeout = 0;
1971 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001972 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001973 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1974 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001975
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001976 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1977 (unsigned long) &rfc);
1978
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001979 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001980 break;
1981
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001982 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001983 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001984 chan->fcs = L2CAP_FCS_NONE;
1985 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001986 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001987 break;
1988 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001990 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001991 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992
1993 return ptr - data;
1994}
1995
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001996static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001998 struct l2cap_conf_rsp *rsp = data;
1999 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002000 void *req = chan->conf_req;
2001 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002002 int type, hint, olen;
2003 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002004 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002005 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002006 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002008 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002009
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002010 while (len >= L2CAP_CONF_OPT_SIZE) {
2011 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002013 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002014 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002015
2016 switch (type) {
2017 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002018 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002019 break;
2020
2021 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002022 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002023 break;
2024
2025 case L2CAP_CONF_QOS:
2026 break;
2027
Marcel Holtmann6464f352007-10-20 13:39:51 +02002028 case L2CAP_CONF_RFC:
2029 if (olen == sizeof(rfc))
2030 memcpy(&rfc, (void *) val, olen);
2031 break;
2032
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002033 case L2CAP_CONF_FCS:
2034 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002035 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002036
2037 break;
2038
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002039 default:
2040 if (hint)
2041 break;
2042
2043 result = L2CAP_CONF_UNKNOWN;
2044 *((u8 *) ptr++) = type;
2045 break;
2046 }
2047 }
2048
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002049 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002050 goto done;
2051
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002052 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002053 case L2CAP_MODE_STREAMING:
2054 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002055 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002056 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002057 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002058 break;
2059 }
2060
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002061 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002062 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002063
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002064 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002065 }
2066
2067done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002068 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002069 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002070 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002071
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002072 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002073 return -ECONNREFUSED;
2074
2075 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2076 sizeof(rfc), (unsigned long) &rfc);
2077 }
2078
2079
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002080 if (result == L2CAP_CONF_SUCCESS) {
2081 /* Configure output options and let the other side know
2082 * which ones we don't like. */
2083
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002084 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2085 result = L2CAP_CONF_UNACCEPT;
2086 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002087 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002088 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002089 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002090 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002091
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002092 switch (rfc.mode) {
2093 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002094 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002095 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002096 break;
2097
2098 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002099 chan->remote_tx_win = rfc.txwin_size;
2100 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002101
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002102 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2103 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002104
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002105 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002106
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002107 rfc.retrans_timeout =
2108 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2109 rfc.monitor_timeout =
2110 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002111
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002112 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002113
2114 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2115 sizeof(rfc), (unsigned long) &rfc);
2116
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002117 break;
2118
2119 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002120 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2121 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002122
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002123 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002124
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002125 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002126
2127 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2128 sizeof(rfc), (unsigned long) &rfc);
2129
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002130 break;
2131
2132 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002133 result = L2CAP_CONF_UNACCEPT;
2134
2135 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002136 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002137 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002138
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002139 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002140 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002141 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002142 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002143 rsp->result = cpu_to_le16(result);
2144 rsp->flags = cpu_to_le16(0x0000);
2145
2146 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147}
2148
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002149static 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 -03002150{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002151 struct l2cap_conf_req *req = data;
2152 void *ptr = req->data;
2153 int type, olen;
2154 unsigned long val;
Mat Martineau36e999a2011-12-08 17:23:21 -08002155 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002156
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002157 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002158
2159 while (len >= L2CAP_CONF_OPT_SIZE) {
2160 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2161
2162 switch (type) {
2163 case L2CAP_CONF_MTU:
2164 if (val < L2CAP_DEFAULT_MIN_MTU) {
2165 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002166 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002167 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002168 chan->imtu = val;
2169 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002170 break;
2171
2172 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002173 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002174 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002175 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002176 break;
2177
2178 case L2CAP_CONF_RFC:
2179 if (olen == sizeof(rfc))
2180 memcpy(&rfc, (void *)val, olen);
2181
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002182 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002183 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002184 return -ECONNREFUSED;
2185
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002186 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002187
2188 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2189 sizeof(rfc), (unsigned long) &rfc);
2190 break;
2191 }
2192 }
2193
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002194 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002195 return -ECONNREFUSED;
2196
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002197 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002198
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002199 if (*result == L2CAP_CONF_SUCCESS) {
2200 switch (rfc.mode) {
2201 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002202 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2203 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2204 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002205 break;
2206 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002207 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002208 }
2209 }
2210
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002211 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002212 req->flags = cpu_to_le16(0x0000);
2213
2214 return ptr - data;
2215}
2216
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002217static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218{
2219 struct l2cap_conf_rsp *rsp = data;
2220 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002222 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002224 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002225 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002226 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227
2228 return ptr - data;
2229}
2230
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002231void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002232{
2233 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002234 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002235 u8 buf[128];
2236
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002237 rsp.scid = cpu_to_le16(chan->dcid);
2238 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002239 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2240 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2241 l2cap_send_cmd(conn, chan->ident,
2242 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2243
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002244 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002245 return;
2246
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002247 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2248 l2cap_build_conf_req(chan, buf), buf);
2249 chan->num_conf_req++;
2250}
2251
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002252static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002253{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002254 int type, olen;
2255 unsigned long val;
2256 struct l2cap_conf_rfc rfc;
2257
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002258 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002259
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002260 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002261 return;
2262
2263 while (len >= L2CAP_CONF_OPT_SIZE) {
2264 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2265
2266 switch (type) {
2267 case L2CAP_CONF_RFC:
2268 if (olen == sizeof(rfc))
2269 memcpy(&rfc, (void *)val, olen);
2270 goto done;
2271 }
2272 }
2273
Mat Martineau36e999a2011-12-08 17:23:21 -08002274 /* Use sane default values in case a misbehaving remote device
2275 * did not send an RFC option.
2276 */
2277 rfc.mode = chan->mode;
2278 rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
2279 rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
2280 rfc.max_pdu_size = cpu_to_le16(chan->imtu);
2281
2282 BT_ERR("Expected RFC option was not found, using defaults");
2283
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002284done:
2285 switch (rfc.mode) {
2286 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002287 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2288 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2289 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002290 break;
2291 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002292 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002293 }
2294}
2295
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002296static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2297{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002298 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002299
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002300 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002301 return 0;
2302
2303 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2304 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002305 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002306
2307 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002308 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002309
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002310 l2cap_conn_start(conn);
2311 }
2312
2313 return 0;
2314}
2315
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2317{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2319 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002320 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002321 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002322 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323
2324 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002325 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326
2327 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2328
2329 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002330 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2331 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 result = L2CAP_CR_BAD_PSM;
2333 goto sendresp;
2334 }
2335
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002336 parent = pchan->sk;
2337
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002338 bh_lock_sock(parent);
2339
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002340 /* Check if the ACL is secure enough (if not SDP) */
2341 if (psm != cpu_to_le16(0x0001) &&
2342 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002343 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002344 result = L2CAP_CR_SEC_BLOCK;
2345 goto response;
2346 }
2347
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 result = L2CAP_CR_NO_MEM;
2349
2350 /* Check for backlog size */
2351 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002352 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353 goto response;
2354 }
2355
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002356 chan = pchan->ops->new_connection(pchan->data);
2357 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 goto response;
2359
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002360 sk = chan->sk;
2361
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002362 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363
2364 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002365 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2366 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002368 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 goto response;
2370 }
2371
2372 hci_conn_hold(conn->hcon);
2373
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374 bacpy(&bt_sk(sk)->src, conn->src);
2375 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002376 chan->psm = psm;
2377 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002379 bt_accept_enqueue(parent, sk);
2380
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002381 __l2cap_chan_add(conn, chan);
2382
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002383 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002385 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002387 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388
Marcel Holtmann984947d2009-02-06 23:35:19 +01002389 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002390 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002391 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002392 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002393 result = L2CAP_CR_PEND;
2394 status = L2CAP_CS_AUTHOR_PEND;
2395 parent->sk_data_ready(parent, 0);
2396 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002397 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002398 result = L2CAP_CR_SUCCESS;
2399 status = L2CAP_CS_NO_INFO;
2400 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002401 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002402 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002403 result = L2CAP_CR_PEND;
2404 status = L2CAP_CS_AUTHEN_PEND;
2405 }
2406 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002407 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002408 result = L2CAP_CR_PEND;
2409 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 }
2411
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002412 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413
2414response:
2415 bh_unlock_sock(parent);
2416
2417sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002418 rsp.scid = cpu_to_le16(scid);
2419 rsp.dcid = cpu_to_le16(dcid);
2420 rsp.result = cpu_to_le16(result);
2421 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002423
2424 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2425 struct l2cap_info_req info;
2426 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2427
2428 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2429 conn->info_ident = l2cap_get_ident(conn);
2430
2431 mod_timer(&conn->info_timer, jiffies +
2432 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2433
2434 l2cap_send_cmd(conn, conn->info_ident,
2435 L2CAP_INFO_REQ, sizeof(info), &info);
2436 }
2437
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002438 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002439 result == L2CAP_CR_SUCCESS) {
2440 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002441 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002442 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002443 l2cap_build_conf_req(chan, buf), buf);
2444 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002445 }
2446
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 return 0;
2448}
2449
2450static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2451{
2452 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2453 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002454 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 struct sock *sk;
2456 u8 req[128];
2457
2458 scid = __le16_to_cpu(rsp->scid);
2459 dcid = __le16_to_cpu(rsp->dcid);
2460 result = __le16_to_cpu(rsp->result);
2461 status = __le16_to_cpu(rsp->status);
2462
2463 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2464
2465 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002466 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002467 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002468 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002470 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002471 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002472 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473 }
2474
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002475 sk = chan->sk;
2476
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 switch (result) {
2478 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002479 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002480 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002481 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002482 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002483
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002484 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002485 break;
2486
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002488 l2cap_build_conf_req(chan, req), req);
2489 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 break;
2491
2492 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002493 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494 break;
2495
2496 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002497 /* don't delete l2cap channel if sk is owned by user */
2498 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002499 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002500 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02002501 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002502 break;
2503 }
2504
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002505 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506 break;
2507 }
2508
2509 bh_unlock_sock(sk);
2510 return 0;
2511}
2512
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002513static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002514{
2515 /* FCS is enabled only in ERTM or streaming mode, if one or both
2516 * sides request it.
2517 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002518 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002519 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002520 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002521 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002522}
2523
Al Viro88219a02007-07-29 00:17:25 -07002524static 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 -07002525{
2526 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2527 u16 dcid, flags;
2528 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002529 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002531 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532
2533 dcid = __le16_to_cpu(req->dcid);
2534 flags = __le16_to_cpu(req->flags);
2535
2536 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2537
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002538 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002539 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 return -ENOENT;
2541
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002542 sk = chan->sk;
2543
David S. Miller033b1142011-07-21 13:38:42 -07002544 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002545 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002546
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002547 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2548 rej.scid = cpu_to_le16(chan->scid);
2549 rej.dcid = cpu_to_le16(chan->dcid);
2550
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002551 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2552 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002553 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002554 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002555
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002556 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002557 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002558 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002559 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002560 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002561 L2CAP_CONF_REJECT, flags), rsp);
2562 goto unlock;
2563 }
2564
2565 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002566 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2567 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568
2569 if (flags & 0x0001) {
2570 /* Incomplete config. Send empty response. */
2571 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002572 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002573 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574 goto unlock;
2575 }
2576
2577 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002578 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002579 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002580 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002582 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002584 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002585 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002586
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002587 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002588 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002589
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002590 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002591 goto unlock;
2592
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002593 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002594 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002595
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002596 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002597
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002598 chan->next_tx_seq = 0;
2599 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002600 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002601 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002602 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002603
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002605 goto unlock;
2606 }
2607
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002608 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002609 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002611 l2cap_build_conf_req(chan, buf), buf);
2612 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 }
2614
2615unlock:
2616 bh_unlock_sock(sk);
2617 return 0;
2618}
2619
2620static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2621{
2622 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2623 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002624 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002626 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627
2628 scid = __le16_to_cpu(rsp->scid);
2629 flags = __le16_to_cpu(rsp->flags);
2630 result = __le16_to_cpu(rsp->result);
2631
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002632 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2633 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002635 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002636 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 return 0;
2638
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002639 sk = chan->sk;
2640
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641 switch (result) {
2642 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002643 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644 break;
2645
2646 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002647 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002648 char req[64];
2649
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002650 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002651 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002652 goto done;
2653 }
2654
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002655 /* throw out any old stored conf requests */
2656 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002657 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2658 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002659 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002660 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002661 goto done;
2662 }
2663
2664 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2665 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002666 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002667 if (result != L2CAP_CONF_SUCCESS)
2668 goto done;
2669 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670 }
2671
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002672 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002673 sk->sk_err = ECONNRESET;
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02002674 __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002675 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676 goto done;
2677 }
2678
2679 if (flags & 0x01)
2680 goto done;
2681
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002682 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002684 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002685 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002686
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002687 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002688 chan->next_tx_seq = 0;
2689 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002690 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002691 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002692 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002693
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694 l2cap_chan_ready(sk);
2695 }
2696
2697done:
2698 bh_unlock_sock(sk);
2699 return 0;
2700}
2701
2702static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2703{
2704 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2705 struct l2cap_disconn_rsp rsp;
2706 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002707 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708 struct sock *sk;
2709
2710 scid = __le16_to_cpu(req->scid);
2711 dcid = __le16_to_cpu(req->dcid);
2712
2713 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2714
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002715 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002716 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717 return 0;
2718
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002719 sk = chan->sk;
2720
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002721 rsp.dcid = cpu_to_le16(chan->scid);
2722 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2724
2725 sk->sk_shutdown = SHUTDOWN_MASK;
2726
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002727 /* don't delete l2cap channel if sk is owned by user */
2728 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002729 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002730 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02002731 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002732 bh_unlock_sock(sk);
2733 return 0;
2734 }
2735
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002736 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 bh_unlock_sock(sk);
2738
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002739 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 return 0;
2741}
2742
2743static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2744{
2745 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2746 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002747 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 struct sock *sk;
2749
2750 scid = __le16_to_cpu(rsp->scid);
2751 dcid = __le16_to_cpu(rsp->dcid);
2752
2753 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2754
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002755 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002756 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757 return 0;
2758
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002759 sk = chan->sk;
2760
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002761 /* don't delete l2cap channel if sk is owned by user */
2762 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002763 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002764 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02002765 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002766 bh_unlock_sock(sk);
2767 return 0;
2768 }
2769
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002770 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 bh_unlock_sock(sk);
2772
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002773 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774 return 0;
2775}
2776
2777static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2778{
2779 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780 u16 type;
2781
2782 type = __le16_to_cpu(req->type);
2783
2784 BT_DBG("type 0x%4.4x", type);
2785
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002786 if (type == L2CAP_IT_FEAT_MASK) {
2787 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002788 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002789 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2790 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2791 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002792 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002793 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2794 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002795 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002796 l2cap_send_cmd(conn, cmd->ident,
2797 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002798 } else if (type == L2CAP_IT_FIXED_CHAN) {
2799 u8 buf[12];
2800 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2801 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2802 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2803 memcpy(buf + 4, l2cap_fixed_chan, 8);
2804 l2cap_send_cmd(conn, cmd->ident,
2805 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002806 } else {
2807 struct l2cap_info_rsp rsp;
2808 rsp.type = cpu_to_le16(type);
2809 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2810 l2cap_send_cmd(conn, cmd->ident,
2811 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2812 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813
2814 return 0;
2815}
2816
2817static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2818{
2819 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2820 u16 type, result;
2821
2822 type = __le16_to_cpu(rsp->type);
2823 result = __le16_to_cpu(rsp->result);
2824
2825 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2826
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002827 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2828 if (cmd->ident != conn->info_ident ||
2829 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2830 return 0;
2831
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002832 del_timer(&conn->info_timer);
2833
Ville Tervoadb08ed2010-08-04 09:43:33 +03002834 if (result != L2CAP_IR_SUCCESS) {
2835 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2836 conn->info_ident = 0;
2837
2838 l2cap_conn_start(conn);
2839
2840 return 0;
2841 }
2842
Marcel Holtmann984947d2009-02-06 23:35:19 +01002843 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002844 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002845
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002846 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002847 struct l2cap_info_req req;
2848 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2849
2850 conn->info_ident = l2cap_get_ident(conn);
2851
2852 l2cap_send_cmd(conn, conn->info_ident,
2853 L2CAP_INFO_REQ, sizeof(req), &req);
2854 } else {
2855 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2856 conn->info_ident = 0;
2857
2858 l2cap_conn_start(conn);
2859 }
2860 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002861 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002862 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002863
2864 l2cap_conn_start(conn);
2865 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002866
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867 return 0;
2868}
2869
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002870static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002871 u16 to_multiplier)
2872{
2873 u16 max_latency;
2874
2875 if (min > max || min < 6 || max > 3200)
2876 return -EINVAL;
2877
2878 if (to_multiplier < 10 || to_multiplier > 3200)
2879 return -EINVAL;
2880
2881 if (max >= to_multiplier * 8)
2882 return -EINVAL;
2883
2884 max_latency = (to_multiplier * 8 / max) - 1;
2885 if (latency > 499 || latency > max_latency)
2886 return -EINVAL;
2887
2888 return 0;
2889}
2890
2891static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2892 struct l2cap_cmd_hdr *cmd, u8 *data)
2893{
2894 struct hci_conn *hcon = conn->hcon;
2895 struct l2cap_conn_param_update_req *req;
2896 struct l2cap_conn_param_update_rsp rsp;
2897 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002898 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002899
2900 if (!(hcon->link_mode & HCI_LM_MASTER))
2901 return -EINVAL;
2902
2903 cmd_len = __le16_to_cpu(cmd->len);
2904 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2905 return -EPROTO;
2906
2907 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002908 min = __le16_to_cpu(req->min);
2909 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002910 latency = __le16_to_cpu(req->latency);
2911 to_multiplier = __le16_to_cpu(req->to_multiplier);
2912
2913 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2914 min, max, latency, to_multiplier);
2915
2916 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002917
2918 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2919 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002920 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2921 else
2922 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2923
2924 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2925 sizeof(rsp), &rsp);
2926
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002927 if (!err)
2928 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2929
Claudio Takahaside731152011-02-11 19:28:55 -02002930 return 0;
2931}
2932
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002933static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2934 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2935{
2936 int err = 0;
2937
2938 switch (cmd->code) {
2939 case L2CAP_COMMAND_REJ:
2940 l2cap_command_rej(conn, cmd, data);
2941 break;
2942
2943 case L2CAP_CONN_REQ:
2944 err = l2cap_connect_req(conn, cmd, data);
2945 break;
2946
2947 case L2CAP_CONN_RSP:
2948 err = l2cap_connect_rsp(conn, cmd, data);
2949 break;
2950
2951 case L2CAP_CONF_REQ:
2952 err = l2cap_config_req(conn, cmd, cmd_len, data);
2953 break;
2954
2955 case L2CAP_CONF_RSP:
2956 err = l2cap_config_rsp(conn, cmd, data);
2957 break;
2958
2959 case L2CAP_DISCONN_REQ:
2960 err = l2cap_disconnect_req(conn, cmd, data);
2961 break;
2962
2963 case L2CAP_DISCONN_RSP:
2964 err = l2cap_disconnect_rsp(conn, cmd, data);
2965 break;
2966
2967 case L2CAP_ECHO_REQ:
2968 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2969 break;
2970
2971 case L2CAP_ECHO_RSP:
2972 break;
2973
2974 case L2CAP_INFO_REQ:
2975 err = l2cap_information_req(conn, cmd, data);
2976 break;
2977
2978 case L2CAP_INFO_RSP:
2979 err = l2cap_information_rsp(conn, cmd, data);
2980 break;
2981
2982 default:
2983 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2984 err = -EINVAL;
2985 break;
2986 }
2987
2988 return err;
2989}
2990
2991static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2992 struct l2cap_cmd_hdr *cmd, u8 *data)
2993{
2994 switch (cmd->code) {
2995 case L2CAP_COMMAND_REJ:
2996 return 0;
2997
2998 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002999 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003000
3001 case L2CAP_CONN_PARAM_UPDATE_RSP:
3002 return 0;
3003
3004 default:
3005 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3006 return -EINVAL;
3007 }
3008}
3009
3010static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3011 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012{
3013 u8 *data = skb->data;
3014 int len = skb->len;
3015 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003016 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017
3018 l2cap_raw_recv(conn, skb);
3019
3020 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003021 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3023 data += L2CAP_CMD_HDR_SIZE;
3024 len -= L2CAP_CMD_HDR_SIZE;
3025
Al Viro88219a02007-07-29 00:17:25 -07003026 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027
Al Viro88219a02007-07-29 00:17:25 -07003028 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 -07003029
Al Viro88219a02007-07-29 00:17:25 -07003030 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031 BT_DBG("corrupted command");
3032 break;
3033 }
3034
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003035 if (conn->hcon->type == LE_LINK)
3036 err = l2cap_le_sig_cmd(conn, &cmd, data);
3037 else
3038 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039
3040 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003041 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003042
3043 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044
3045 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003046 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3048 }
3049
Al Viro88219a02007-07-29 00:17:25 -07003050 data += cmd_len;
3051 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052 }
3053
3054 kfree_skb(skb);
3055}
3056
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003057static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003058{
3059 u16 our_fcs, rcv_fcs;
3060 int hdr_size = L2CAP_HDR_SIZE + 2;
3061
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003062 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003063 skb_trim(skb, skb->len - 2);
3064 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3065 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3066
3067 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003068 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003069 }
3070 return 0;
3071}
3072
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003073static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003074{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003075 u16 control = 0;
3076
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003077 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003078
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003079 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003080
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003081 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003082 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003083 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003084 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003085 }
3086
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003087 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003088 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003089
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003090 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003091
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003092 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003093 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003094 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003095 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003096 }
3097}
3098
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003099static 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 -03003100{
3101 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003102 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003103
3104 bt_cb(skb)->tx_seq = tx_seq;
3105 bt_cb(skb)->sar = sar;
3106
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003107 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003108 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003109 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003110 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003111 }
3112
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003113 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003114 if (tx_seq_offset < 0)
3115 tx_seq_offset += 64;
3116
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003117 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003118 if (bt_cb(next_skb)->tx_seq == tx_seq)
3119 return -EINVAL;
3120
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003121 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003122 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003123 if (next_tx_seq_offset < 0)
3124 next_tx_seq_offset += 64;
3125
3126 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003127 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003128 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003129 }
3130
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003131 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003132 break;
3133
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003134 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003135
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003136 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003137
3138 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003139}
3140
Mat Martineau84084a32011-07-22 14:54:00 -07003141static void append_skb_frag(struct sk_buff *skb,
3142 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003143{
Mat Martineau84084a32011-07-22 14:54:00 -07003144 /* skb->len reflects data in skb as well as all fragments
3145 * skb->data_len reflects only data in fragments
3146 */
3147 if (!skb_has_frag_list(skb))
3148 skb_shinfo(skb)->frag_list = new_frag;
3149
3150 new_frag->next = NULL;
3151
3152 (*last_frag)->next = new_frag;
3153 *last_frag = new_frag;
3154
3155 skb->len += new_frag->len;
3156 skb->data_len += new_frag->len;
3157 skb->truesize += new_frag->truesize;
3158}
3159
3160static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
3161{
3162 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003163
3164 switch (control & L2CAP_CTRL_SAR) {
3165 case L2CAP_SDU_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003166 if (chan->sdu)
3167 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003168
Mat Martineau84084a32011-07-22 14:54:00 -07003169 err = chan->ops->recv(chan->data, skb);
3170 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003171
3172 case L2CAP_SDU_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003173 if (chan->sdu)
3174 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003175
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003176 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003177 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003178
Mat Martineau84084a32011-07-22 14:54:00 -07003179 if (chan->sdu_len > chan->imtu) {
3180 err = -EMSGSIZE;
3181 break;
3182 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003183
Mat Martineau84084a32011-07-22 14:54:00 -07003184 if (skb->len >= chan->sdu_len)
3185 break;
3186
3187 chan->sdu = skb;
3188 chan->sdu_last_frag = skb;
3189
3190 skb = NULL;
3191 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003192 break;
3193
3194 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003195 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003196 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003197
Mat Martineau84084a32011-07-22 14:54:00 -07003198 append_skb_frag(chan->sdu, skb,
3199 &chan->sdu_last_frag);
3200 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003201
Mat Martineau84084a32011-07-22 14:54:00 -07003202 if (chan->sdu->len >= chan->sdu_len)
3203 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003204
Mat Martineau84084a32011-07-22 14:54:00 -07003205 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003206 break;
3207
3208 case L2CAP_SDU_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003209 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003210 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003211
Mat Martineau84084a32011-07-22 14:54:00 -07003212 append_skb_frag(chan->sdu, skb,
3213 &chan->sdu_last_frag);
3214 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003215
Mat Martineau84084a32011-07-22 14:54:00 -07003216 if (chan->sdu->len != chan->sdu_len)
3217 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003218
Mat Martineau84084a32011-07-22 14:54:00 -07003219 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003220
Mat Martineau84084a32011-07-22 14:54:00 -07003221 if (!err) {
3222 /* Reassembly complete */
3223 chan->sdu = NULL;
3224 chan->sdu_last_frag = NULL;
3225 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003226 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003227 break;
3228 }
3229
Mat Martineau84084a32011-07-22 14:54:00 -07003230 if (err) {
3231 kfree_skb(skb);
3232 kfree_skb(chan->sdu);
3233 chan->sdu = NULL;
3234 chan->sdu_last_frag = NULL;
3235 chan->sdu_len = 0;
3236 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003237
Mat Martineau84084a32011-07-22 14:54:00 -07003238 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003239}
3240
Mat Martineau26f880d2011-07-07 09:39:01 -07003241static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003242{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003243 u16 control;
3244
Mat Martineau26f880d2011-07-07 09:39:01 -07003245 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003246
Mat Martineau26f880d2011-07-07 09:39:01 -07003247 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3248
3249 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3250 control |= L2CAP_SUPER_RCV_NOT_READY;
3251 l2cap_send_sframe(chan, control);
3252
3253 set_bit(CONN_RNR_SENT, &chan->conn_state);
3254
3255 __clear_ack_timer(chan);
3256}
3257
3258static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3259{
3260 u16 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003261
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003262 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003263 goto done;
3264
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003265 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003266 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003267 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003268 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003269
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003270 __clear_retrans_timer(chan);
3271 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003272
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003273 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003274
3275done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003276 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3277 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003278
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003279 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003280}
3281
Mat Martineaue3281402011-07-07 09:39:02 -07003282void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003283{
Mat Martineaue3281402011-07-07 09:39:02 -07003284 if (chan->mode == L2CAP_MODE_ERTM) {
3285 if (busy)
3286 l2cap_ertm_enter_local_busy(chan);
3287 else
3288 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003289 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003290}
3291
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003292static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003293{
3294 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003295 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003296
Mat Martineaue3281402011-07-07 09:39:02 -07003297 while ((skb = skb_peek(&chan->srej_q)) &&
3298 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3299 int err;
3300
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003301 if (bt_cb(skb)->tx_seq != tx_seq)
3302 break;
3303
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003304 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003305 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Mat Martineau84084a32011-07-22 14:54:00 -07003306 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003307
3308 if (err < 0) {
3309 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3310 break;
3311 }
3312
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003313 chan->buffer_seq_srej =
3314 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003315 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003316 }
3317}
3318
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003319static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003320{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003321 struct srej_list *l, *tmp;
3322 u16 control;
3323
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003324 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003325 if (l->tx_seq == tx_seq) {
3326 list_del(&l->list);
3327 kfree(l);
3328 return;
3329 }
3330 control = L2CAP_SUPER_SELECT_REJECT;
3331 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003332 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003333 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003334 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003335 }
3336}
3337
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003338static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003339{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003340 struct srej_list *new;
3341 u16 control;
3342
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003343 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003344 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003345 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003346 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003347
3348 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003349 new->tx_seq = chan->expected_tx_seq;
3350 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003351 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003352 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003353 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003354}
3355
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003356static 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 -03003357{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003358 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003359 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003360 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003361 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003362 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003363 int err = 0;
3364
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003365 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3366 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003367
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003368 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003369 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003370 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003371 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003372 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003373 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003374 }
3375
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003376 chan->expected_ack_seq = req_seq;
3377 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003378
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003379 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003380 if (tx_seq_offset < 0)
3381 tx_seq_offset += 64;
3382
3383 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003384 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003385 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003386 goto drop;
3387 }
3388
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003389 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003390 goto drop;
3391
Mat Martineau02f1b642011-06-29 14:35:19 -07003392 if (tx_seq == chan->expected_tx_seq)
3393 goto expected;
3394
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003395 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003396 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003397
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003398 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003399 struct srej_list, list);
3400 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003401 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003402 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003403
3404 list_del(&first->list);
3405 kfree(first);
3406
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003407 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003408 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003409 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003410 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003411 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003412 }
3413 } else {
3414 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003415
3416 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003417 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003418 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003419
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003420 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003421 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003422 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003423 return 0;
3424 }
3425 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003426 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003427 }
3428 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003429 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003430 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003431 if (expected_tx_seq_offset < 0)
3432 expected_tx_seq_offset += 64;
3433
3434 /* duplicated tx_seq */
3435 if (tx_seq_offset < expected_tx_seq_offset)
3436 goto drop;
3437
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003438 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003439
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003440 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003441
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003442 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003443 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003444
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003445 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003446 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003447
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003448 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003449
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003450 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003451
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003452 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003453 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003454 return 0;
3455
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003456expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003457 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003458
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003459 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003460 bt_cb(skb)->tx_seq = tx_seq;
3461 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003462 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003463 return 0;
3464 }
3465
Mat Martineau84084a32011-07-22 14:54:00 -07003466 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Mat Martineaufadd1922011-07-07 09:39:03 -07003467 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Mat Martineaue3281402011-07-07 09:39:02 -07003468 if (err < 0) {
3469 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3470 return err;
3471 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003472
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003473 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003474 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003475 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003476 }
3477
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003478 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003479
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003480 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3481 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003482 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003483
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003484 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003485
3486drop:
3487 kfree_skb(skb);
3488 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003489}
3490
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003491static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003492{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003493 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003494 rx_control);
3495
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003496 chan->expected_ack_seq = __get_reqseq(rx_control);
3497 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003498
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003499 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003500 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3501 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3502 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003503 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003504 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003505
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003506 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003507 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003508 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003509 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003510 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003511
3512 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003513 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003514
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003515 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003516 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003517
3518 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003519 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003520 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003521 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003522
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003523 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3524 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003525 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003526 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003527 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003528 }
3529}
3530
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003531static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003532{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003533 u8 tx_seq = __get_reqseq(rx_control);
3534
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003535 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003536
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003537 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003538
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003539 chan->expected_ack_seq = tx_seq;
3540 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003541
3542 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003543 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003544 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003545 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003546 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003547
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003548 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3549 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003550 }
3551}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003552static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003553{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003554 u8 tx_seq = __get_reqseq(rx_control);
3555
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003556 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003557
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003558 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003559
3560 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003561 chan->expected_ack_seq = tx_seq;
3562 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003563
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003564 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003565 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003566
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003567 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003568
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003569 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003570 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003571 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003572 }
3573 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003574 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003575 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003576 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003577 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003578 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003579 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003580 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003581 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003582 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003583 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003584 }
3585 }
3586}
3587
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003588static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003589{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003590 u8 tx_seq = __get_reqseq(rx_control);
3591
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003592 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003593
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003594 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003595 chan->expected_ack_seq = tx_seq;
3596 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003597
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003598 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003599 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003600
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003601 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003602 __clear_retrans_timer(chan);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003603 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003604 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003605 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003606 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003607
3608 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003609 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003610 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003611 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003612}
3613
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003614static 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 -03003615{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003616 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003617
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003618 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003619 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003620 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003621 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003622 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003623 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003624 }
3625
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003626 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3627 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003628 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003629 break;
3630
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003631 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003632 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003633 break;
3634
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003635 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003636 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003637 break;
3638
3639 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003640 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003641 break;
3642 }
3643
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003644 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003645 return 0;
3646}
3647
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003648static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3649{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003650 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003651 u16 control;
3652 u8 req_seq;
3653 int len, next_tx_seq_offset, req_seq_offset;
3654
3655 control = get_unaligned_le16(skb->data);
3656 skb_pull(skb, 2);
3657 len = skb->len;
3658
3659 /*
3660 * We can just drop the corrupted I-frame here.
3661 * Receiver will miss it and start proper recovery
3662 * procedures and ask retransmission.
3663 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003664 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003665 goto drop;
3666
3667 if (__is_sar_start(control) && __is_iframe(control))
3668 len -= 2;
3669
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003670 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003671 len -= 2;
3672
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003673 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003674 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003675 goto drop;
3676 }
3677
3678 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003679 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003680 if (req_seq_offset < 0)
3681 req_seq_offset += 64;
3682
3683 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003684 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003685 if (next_tx_seq_offset < 0)
3686 next_tx_seq_offset += 64;
3687
3688 /* check for invalid req-seq */
3689 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003690 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003691 goto drop;
3692 }
3693
3694 if (__is_iframe(control)) {
3695 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003696 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003697 goto drop;
3698 }
3699
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003700 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003701 } else {
3702 if (len != 0) {
3703 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003704 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003705 goto drop;
3706 }
3707
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003708 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003709 }
3710
3711 return 0;
3712
3713drop:
3714 kfree_skb(skb);
3715 return 0;
3716}
3717
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3719{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003720 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003721 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003722 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003723 u8 tx_seq;
3724 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003726 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003727 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003728 BT_DBG("unknown cid 0x%4.4x", cid);
3729 goto drop;
3730 }
3731
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003732 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003733
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003734 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003736 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003737 goto drop;
3738
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003739 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003740 case L2CAP_MODE_BASIC:
3741 /* If socket recv buffers overflows we drop data here
3742 * which is *bad* because L2CAP has to be reliable.
3743 * But we don't have any other choice. L2CAP doesn't
3744 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003745
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003746 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003747 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003749 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003750 goto done;
3751 break;
3752
3753 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003754 if (!sock_owned_by_user(sk)) {
3755 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003756 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003757 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003758 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003759 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003760
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003761 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003762
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003763 case L2CAP_MODE_STREAMING:
3764 control = get_unaligned_le16(skb->data);
3765 skb_pull(skb, 2);
3766 len = skb->len;
3767
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003768 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003769 goto drop;
3770
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003771 if (__is_sar_start(control))
3772 len -= 2;
3773
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003774 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003775 len -= 2;
3776
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003777 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003778 goto drop;
3779
3780 tx_seq = __get_txseq(control);
3781
Mat Martineau84084a32011-07-22 14:54:00 -07003782 if (chan->expected_tx_seq != tx_seq) {
3783 /* Frame(s) missing - must discard partial SDU */
3784 kfree_skb(chan->sdu);
3785 chan->sdu = NULL;
3786 chan->sdu_last_frag = NULL;
3787 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003788
Mat Martineau84084a32011-07-22 14:54:00 -07003789 /* TODO: Notify userland of missing data */
3790 }
3791
3792 chan->expected_tx_seq = (tx_seq + 1) % 64;
3793
3794 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
3795 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003796
3797 goto done;
3798
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003799 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003800 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003801 break;
3802 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003803
3804drop:
3805 kfree_skb(skb);
3806
3807done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003808 if (sk)
3809 bh_unlock_sock(sk);
3810
Linus Torvalds1da177e2005-04-16 15:20:36 -07003811 return 0;
3812}
3813
Al Viro8e036fc2007-07-29 00:16:36 -07003814static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003816 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003817 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003818
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003819 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3820 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821 goto drop;
3822
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003823 sk = chan->sk;
3824
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003825 bh_lock_sock(sk);
3826
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827 BT_DBG("sk %p, len %d", sk, skb->len);
3828
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003829 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830 goto drop;
3831
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003832 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833 goto drop;
3834
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003835 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836 goto done;
3837
3838drop:
3839 kfree_skb(skb);
3840
3841done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003842 if (sk)
3843 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844 return 0;
3845}
3846
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003847static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3848{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003849 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003850 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003851
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003852 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3853 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003854 goto drop;
3855
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003856 sk = chan->sk;
3857
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003858 bh_lock_sock(sk);
3859
3860 BT_DBG("sk %p, len %d", sk, skb->len);
3861
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003862 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003863 goto drop;
3864
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003865 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003866 goto drop;
3867
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003868 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003869 goto done;
3870
3871drop:
3872 kfree_skb(skb);
3873
3874done:
3875 if (sk)
3876 bh_unlock_sock(sk);
3877 return 0;
3878}
3879
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3881{
3882 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003883 u16 cid, len;
3884 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885
3886 skb_pull(skb, L2CAP_HDR_SIZE);
3887 cid = __le16_to_cpu(lh->cid);
3888 len = __le16_to_cpu(lh->len);
3889
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003890 if (len != skb->len) {
3891 kfree_skb(skb);
3892 return;
3893 }
3894
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3896
3897 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003898 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003899 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003900 l2cap_sig_channel(conn, skb);
3901 break;
3902
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003903 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003904 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905 skb_pull(skb, 2);
3906 l2cap_conless_channel(conn, psm, skb);
3907 break;
3908
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003909 case L2CAP_CID_LE_DATA:
3910 l2cap_att_channel(conn, cid, skb);
3911 break;
3912
Anderson Brigliab501d6a2011-06-07 18:46:31 -03003913 case L2CAP_CID_SMP:
3914 if (smp_sig_channel(conn, skb))
3915 l2cap_conn_del(conn->hcon, EACCES);
3916 break;
3917
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918 default:
3919 l2cap_data_channel(conn, cid, skb);
3920 break;
3921 }
3922}
3923
3924/* ---- L2CAP interface with lower layer (HCI) ---- */
3925
3926static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3927{
3928 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003929 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930
3931 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003932 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933
3934 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3935
3936 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003937 read_lock(&chan_list_lock);
3938 list_for_each_entry(c, &chan_list, global_l) {
3939 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003940
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003941 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942 continue;
3943
3944 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003945 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003946 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003947 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003949 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3950 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003951 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003952 lm2 |= HCI_LM_MASTER;
3953 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003955 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956
3957 return exact ? lm1 : lm2;
3958}
3959
3960static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3961{
Marcel Holtmann01394182006-07-03 10:02:46 +02003962 struct l2cap_conn *conn;
3963
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3965
Ville Tervoacd7d372011-02-10 22:38:49 -03003966 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003967 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968
3969 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970 conn = l2cap_conn_add(hcon, status);
3971 if (conn)
3972 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003973 } else
Joe Perchese1750722011-06-29 18:18:29 -07003974 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003975
3976 return 0;
3977}
3978
Marcel Holtmann2950f212009-02-12 14:02:50 +01003979static int l2cap_disconn_ind(struct hci_conn *hcon)
3980{
3981 struct l2cap_conn *conn = hcon->l2cap_data;
3982
3983 BT_DBG("hcon %p", hcon);
3984
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03003985 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01003986 return 0x13;
3987
3988 return conn->disc_reason;
3989}
3990
3991static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992{
3993 BT_DBG("hcon %p reason %d", hcon, reason);
3994
Ville Tervoacd7d372011-02-10 22:38:49 -03003995 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003996 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003997
Joe Perchese1750722011-06-29 18:18:29 -07003998 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003999
Linus Torvalds1da177e2005-04-16 15:20:36 -07004000 return 0;
4001}
4002
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004003static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004004{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004005 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004006 return;
4007
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004008 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004009 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004010 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02004011 __set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004012 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004013 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004014 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004015 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004016 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004017 }
4018}
4019
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004020static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004022 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004023 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024
Marcel Holtmann01394182006-07-03 10:02:46 +02004025 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004027
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028 BT_DBG("conn %p", conn);
4029
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004030 if (hcon->type == LE_LINK) {
4031 smp_distribute_keys(conn, 0);
4032 del_timer(&conn->security_timer);
4033 }
4034
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004035 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004037 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004038 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004039
Linus Torvalds1da177e2005-04-16 15:20:36 -07004040 bh_lock_sock(sk);
4041
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004042 BT_DBG("chan->scid %d", chan->scid);
4043
4044 if (chan->scid == L2CAP_CID_LE_DATA) {
4045 if (!status && encrypt) {
4046 chan->sec_level = hcon->sec_level;
4047 l2cap_chan_ready(sk);
4048 }
4049
4050 bh_unlock_sock(sk);
4051 continue;
4052 }
4053
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004054 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004055 bh_unlock_sock(sk);
4056 continue;
4057 }
4058
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004059 if (!status && (chan->state == BT_CONNECTED ||
4060 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004061 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004062 bh_unlock_sock(sk);
4063 continue;
4064 }
4065
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004066 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004067 if (!status) {
4068 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004069 req.scid = cpu_to_le16(chan->scid);
4070 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004071
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004072 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004073 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004074
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004075 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004076 L2CAP_CONN_REQ, sizeof(req), &req);
4077 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004078 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02004079 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004080 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004081 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004082 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004083 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004084
4085 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004086 if (bt_sk(sk)->defer_setup) {
4087 struct sock *parent = bt_sk(sk)->parent;
4088 res = L2CAP_CR_PEND;
4089 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004090 if (parent)
4091 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004092 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004093 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004094 res = L2CAP_CR_SUCCESS;
4095 stat = L2CAP_CS_NO_INFO;
4096 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004097 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004098 l2cap_state_change(chan, BT_DISCONN);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02004099 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004100 res = L2CAP_CR_SEC_BLOCK;
4101 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004102 }
4103
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004104 rsp.scid = cpu_to_le16(chan->dcid);
4105 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004106 rsp.result = cpu_to_le16(res);
4107 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004108 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4109 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110 }
4111
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112 bh_unlock_sock(sk);
4113 }
4114
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004115 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004116
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117 return 0;
4118}
4119
4120static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4121{
4122 struct l2cap_conn *conn = hcon->l2cap_data;
4123
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004124 if (!conn)
4125 conn = l2cap_conn_add(hcon, 0);
4126
4127 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128 goto drop;
4129
4130 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4131
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004132 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004134 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004135 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004136 int len;
4137
4138 if (conn->rx_len) {
4139 BT_ERR("Unexpected start frame (len %d)", skb->len);
4140 kfree_skb(conn->rx_skb);
4141 conn->rx_skb = NULL;
4142 conn->rx_len = 0;
4143 l2cap_conn_unreliable(conn, ECOMM);
4144 }
4145
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004146 /* Start fragment always begin with Basic L2CAP header */
4147 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148 BT_ERR("Frame is too short (len %d)", skb->len);
4149 l2cap_conn_unreliable(conn, ECOMM);
4150 goto drop;
4151 }
4152
4153 hdr = (struct l2cap_hdr *) skb->data;
4154 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004155 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156
4157 if (len == skb->len) {
4158 /* Complete frame received */
4159 l2cap_recv_frame(conn, skb);
4160 return 0;
4161 }
4162
4163 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4164
4165 if (skb->len > len) {
4166 BT_ERR("Frame is too long (len %d, expected len %d)",
4167 skb->len, len);
4168 l2cap_conn_unreliable(conn, ECOMM);
4169 goto drop;
4170 }
4171
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004172 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004173
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004174 if (chan && chan->sk) {
4175 struct sock *sk = chan->sk;
4176
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004177 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004178 BT_ERR("Frame exceeding recv MTU (len %d, "
4179 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004180 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004181 bh_unlock_sock(sk);
4182 l2cap_conn_unreliable(conn, ECOMM);
4183 goto drop;
4184 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004185 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004186 }
4187
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004189 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4190 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191 goto drop;
4192
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004193 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004194 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195 conn->rx_len = len - skb->len;
4196 } else {
4197 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4198
4199 if (!conn->rx_len) {
4200 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4201 l2cap_conn_unreliable(conn, ECOMM);
4202 goto drop;
4203 }
4204
4205 if (skb->len > conn->rx_len) {
4206 BT_ERR("Fragment is too long (len %d, expected %d)",
4207 skb->len, conn->rx_len);
4208 kfree_skb(conn->rx_skb);
4209 conn->rx_skb = NULL;
4210 conn->rx_len = 0;
4211 l2cap_conn_unreliable(conn, ECOMM);
4212 goto drop;
4213 }
4214
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004215 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004216 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217 conn->rx_len -= skb->len;
4218
4219 if (!conn->rx_len) {
4220 /* Complete frame received */
4221 l2cap_recv_frame(conn, conn->rx_skb);
4222 conn->rx_skb = NULL;
4223 }
4224 }
4225
4226drop:
4227 kfree_skb(skb);
4228 return 0;
4229}
4230
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004231static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004233 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004234
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004235 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004237 list_for_each_entry(c, &chan_list, global_l) {
4238 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004239
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004240 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 +01004241 batostr(&bt_sk(sk)->src),
4242 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004243 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004244 c->scid, c->dcid, c->imtu, c->omtu,
4245 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004246}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004248 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004249
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004250 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004251}
4252
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004253static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4254{
4255 return single_open(file, l2cap_debugfs_show, inode->i_private);
4256}
4257
4258static const struct file_operations l2cap_debugfs_fops = {
4259 .open = l2cap_debugfs_open,
4260 .read = seq_read,
4261 .llseek = seq_lseek,
4262 .release = single_release,
4263};
4264
4265static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267static struct hci_proto l2cap_hci_proto = {
4268 .name = "L2CAP",
4269 .id = HCI_PROTO_L2CAP,
4270 .connect_ind = l2cap_connect_ind,
4271 .connect_cfm = l2cap_connect_cfm,
4272 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004273 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004274 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004275 .recv_acldata = l2cap_recv_acldata
4276};
4277
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004278int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279{
4280 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004281
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004282 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283 if (err < 0)
4284 return err;
4285
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286 err = hci_register_proto(&l2cap_hci_proto);
4287 if (err < 0) {
4288 BT_ERR("L2CAP protocol registration failed");
4289 bt_sock_unregister(BTPROTO_L2CAP);
4290 goto error;
4291 }
4292
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004293 if (bt_debugfs) {
4294 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4295 bt_debugfs, NULL, &l2cap_debugfs_fops);
4296 if (!l2cap_debugfs)
4297 BT_ERR("Failed to create L2CAP debug file");
4298 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300 return 0;
4301
4302error:
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004303 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004304 return err;
4305}
4306
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004307void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004309 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4312 BT_ERR("L2CAP protocol unregistration failed");
4313
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004314 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004315}
4316
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004317module_param(disable_ertm, bool, 0644);
4318MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");