blob: 3204ba8a701ca0d7c99eebfc629d22e51a007021 [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 */
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300254 __set_chan_timer(chan, HZ / 5);
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
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300910 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200911
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300912 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300913 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300914
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200915 bh_lock_sock(sk);
916
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300917 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300918 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300919 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300920
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300921 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300922 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300923 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200924 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300925
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300926 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300927 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200928
929 bh_unlock_sock(sk);
930 }
931
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300932 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200933}
934
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200935/* Notify sockets that we cannot guaranty reliability anymore */
936static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
937{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300938 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200939
940 BT_DBG("conn %p", conn);
941
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300942 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200943
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300944 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300945 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300946
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300947 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200948 sk->sk_err = err;
949 }
950
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300951 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200952}
953
954static void l2cap_info_timeout(unsigned long arg)
955{
956 struct l2cap_conn *conn = (void *) arg;
957
Marcel Holtmann984947d2009-02-06 23:35:19 +0100958 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100959 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100960
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200961 l2cap_conn_start(conn);
962}
963
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300964static void l2cap_conn_del(struct hci_conn *hcon, int err)
965{
966 struct l2cap_conn *conn = hcon->l2cap_data;
967 struct l2cap_chan *chan, *l;
968 struct sock *sk;
969
970 if (!conn)
971 return;
972
973 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
974
975 kfree_skb(conn->rx_skb);
976
977 /* Kill channels */
978 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
979 sk = chan->sk;
980 bh_lock_sock(sk);
981 l2cap_chan_del(chan, err);
982 bh_unlock_sock(sk);
983 chan->ops->close(chan->data);
984 }
985
986 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
987 del_timer_sync(&conn->info_timer);
988
989 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
990 del_timer(&conn->security_timer);
991
992 hcon->l2cap_data = NULL;
993 kfree(conn);
994}
995
996static void security_timeout(unsigned long arg)
997{
998 struct l2cap_conn *conn = (void *) arg;
999
1000 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1001}
1002
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1004{
Marcel Holtmann01394182006-07-03 10:02:46 +02001005 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006
Marcel Holtmann01394182006-07-03 10:02:46 +02001007 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 return conn;
1009
Marcel Holtmann01394182006-07-03 10:02:46 +02001010 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1011 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013
1014 hcon->l2cap_data = conn;
1015 conn->hcon = hcon;
1016
Marcel Holtmann01394182006-07-03 10:02:46 +02001017 BT_DBG("hcon %p conn %p", hcon, conn);
1018
Ville Tervoacd7d372011-02-10 22:38:49 -03001019 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1020 conn->mtu = hcon->hdev->le_mtu;
1021 else
1022 conn->mtu = hcon->hdev->acl_mtu;
1023
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 conn->src = &hcon->hdev->bdaddr;
1025 conn->dst = &hcon->dst;
1026
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001027 conn->feat_mask = 0;
1028
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001030 rwlock_init(&conn->chan_lock);
1031
1032 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001034 if (hcon->type == LE_LINK)
1035 setup_timer(&conn->security_timer, security_timeout,
1036 (unsigned long) conn);
1037 else
Ville Tervob62f3282011-02-10 22:38:50 -03001038 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +00001039 (unsigned long) conn);
1040
Marcel Holtmann2950f212009-02-12 14:02:50 +01001041 conn->disc_reason = 0x13;
1042
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 return conn;
1044}
1045
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001046static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001048 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001049 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001050 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051}
1052
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054
1055/* Find socket with psm and source bdaddr.
1056 * Returns closest match.
1057 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001058static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001060 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001062 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001063
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001064 list_for_each_entry(c, &chan_list, global_l) {
1065 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001066
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001067 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 continue;
1069
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001070 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001072 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001073 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001074 return c;
1075 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076
1077 /* Closest match */
1078 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001079 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 }
1081 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001083 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001084
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001085 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086}
1087
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001088int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001090 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 bdaddr_t *src = &bt_sk(sk)->src;
1092 bdaddr_t *dst = &bt_sk(sk)->dst;
1093 struct l2cap_conn *conn;
1094 struct hci_conn *hcon;
1095 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001096 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001097 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001099 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001100 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001102 hdev = hci_get_route(dst, src);
1103 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 return -EHOSTUNREACH;
1105
1106 hci_dev_lock_bh(hdev);
1107
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001108 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001109
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001110 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001111 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001112 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001113 else
1114 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001115 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001116
Ville Tervo30e76272011-02-22 16:10:53 -03001117 if (IS_ERR(hcon)) {
1118 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001120 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121
1122 conn = l2cap_conn_add(hcon, 0);
1123 if (!conn) {
1124 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001125 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 goto done;
1127 }
1128
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 /* Update source addr of the socket */
1130 bacpy(src, conn->src);
1131
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001132 l2cap_chan_add(conn, chan);
1133
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001134 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001135 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136
1137 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001138 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001139 __clear_chan_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001140 if (l2cap_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001141 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001142 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001143 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 }
1145
Ville Tervo30e76272011-02-22 16:10:53 -03001146 err = 0;
1147
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148done:
1149 hci_dev_unlock_bh(hdev);
1150 hci_dev_put(hdev);
1151 return err;
1152}
1153
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001154int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001155{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001156 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001157 DECLARE_WAITQUEUE(wait, current);
1158 int err = 0;
1159 int timeo = HZ/5;
1160
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001161 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001162 while ((chan->unacked_frames > 0 && chan->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001163 set_current_state(TASK_INTERRUPTIBLE);
1164
1165 if (!timeo)
1166 timeo = HZ/5;
1167
1168 if (signal_pending(current)) {
1169 err = sock_intr_errno(timeo);
1170 break;
1171 }
1172
1173 release_sock(sk);
1174 timeo = schedule_timeout(timeo);
1175 lock_sock(sk);
1176
1177 err = sock_error(sk);
1178 if (err)
1179 break;
1180 }
1181 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001182 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001183 return err;
1184}
1185
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001186static void l2cap_monitor_timeout(unsigned long arg)
1187{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001188 struct l2cap_chan *chan = (void *) arg;
1189 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001190
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001191 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001192
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001193 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001194 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001195 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001196 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001197 return;
1198 }
1199
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001200 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001201 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001202
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001203 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001204 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001205}
1206
1207static void l2cap_retrans_timeout(unsigned long arg)
1208{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001209 struct l2cap_chan *chan = (void *) arg;
1210 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001211
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001212 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001213
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001214 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001215 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001216 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001217
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001218 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001219
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001220 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001221 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001222}
1223
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001224static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001225{
1226 struct sk_buff *skb;
1227
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001228 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001229 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001230 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001231 break;
1232
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001233 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001234 kfree_skb(skb);
1235
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001236 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001237 }
1238
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001239 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001240 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001241}
1242
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001243void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001244{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001245 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001246 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001247
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001248 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001249
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001250 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001251 flags = ACL_START_NO_FLUSH;
1252 else
1253 flags = ACL_START;
1254
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -07001255 bt_cb(skb)->force_active = chan->force_active;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001256 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001257}
1258
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001259void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001260{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001261 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001262 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001263
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001264 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001265 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001266 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001267 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001268
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001269 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001270 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1271 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001272 }
1273
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001274 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001275
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001276 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001277 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001278}
1279
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001280static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001281{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001282 struct sk_buff *skb, *tx_skb;
1283 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001284
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001285 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001286 if (!skb)
1287 return;
1288
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001289 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001290 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001291 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001292
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001293 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001294 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001295
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001296 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001297
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001298 if (chan->remote_max_tx &&
1299 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001300 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001301 return;
1302 }
1303
1304 tx_skb = skb_clone(skb, GFP_ATOMIC);
1305 bt_cb(skb)->retries++;
1306 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001307 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001308
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001309 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001310 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001311
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001312 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001313 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001314
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001315 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1316
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001317 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001318 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1319 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1320 }
1321
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001322 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001323}
1324
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001325int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001326{
1327 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001328 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001329 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001330
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001331 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001332 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001333
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001334 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001335
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001336 if (chan->remote_max_tx &&
1337 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001338 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001339 break;
1340 }
1341
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001342 tx_skb = skb_clone(skb, GFP_ATOMIC);
1343
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001344 bt_cb(skb)->retries++;
1345
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001346 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001347 control &= L2CAP_CTRL_SAR;
1348
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001349 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001350 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001351
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001352 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1353 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001354 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1355
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001356
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001357 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001358 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1359 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1360 }
1361
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001362 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001363
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001364 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001365
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001366 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1367 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001368
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301369 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001370 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301371
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001372 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001373
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001374 if (skb_queue_is_last(&chan->tx_q, skb))
1375 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001376 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001377 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001378
1379 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001380 }
1381
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001382 return nsent;
1383}
1384
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001385static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001386{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001387 int ret;
1388
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001389 if (!skb_queue_empty(&chan->tx_q))
1390 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001391
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001392 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001393 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001394 return ret;
1395}
1396
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001397static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001398{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001399 u16 control = 0;
1400
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001401 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001402
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001403 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001404 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001405 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001406 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001407 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001408 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001409
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001410 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001411 return;
1412
1413 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001414 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001415}
1416
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001417static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001418{
1419 struct srej_list *tail;
1420 u16 control;
1421
1422 control = L2CAP_SUPER_SELECT_REJECT;
1423 control |= L2CAP_CTRL_FINAL;
1424
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001425 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001426 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1427
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001428 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001429}
1430
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001431static 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 -07001432{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001433 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001434 struct sk_buff **frag;
1435 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001437 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001438 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439
1440 sent += count;
1441 len -= count;
1442
1443 /* Continuation fragments (no L2CAP header) */
1444 frag = &skb_shinfo(skb)->frag_list;
1445 while (len) {
1446 count = min_t(unsigned int, conn->mtu, len);
1447
1448 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1449 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001450 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001451 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1452 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
1454 sent += count;
1455 len -= count;
1456
1457 frag = &(*frag)->next;
1458 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459
1460 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001461}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001463struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001464{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001465 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001466 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001467 struct sk_buff *skb;
1468 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1469 struct l2cap_hdr *lh;
1470
1471 BT_DBG("sk %p len %d", sk, (int)len);
1472
1473 count = min_t(unsigned int, (conn->mtu - hlen), len);
1474 skb = bt_skb_send_alloc(sk, count + hlen,
1475 msg->msg_flags & MSG_DONTWAIT, &err);
1476 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001477 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001478
1479 /* Create L2CAP header */
1480 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001481 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001482 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001483 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001484
1485 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1486 if (unlikely(err < 0)) {
1487 kfree_skb(skb);
1488 return ERR_PTR(err);
1489 }
1490 return skb;
1491}
1492
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001493struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001494{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001495 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001496 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001497 struct sk_buff *skb;
1498 int err, count, hlen = L2CAP_HDR_SIZE;
1499 struct l2cap_hdr *lh;
1500
1501 BT_DBG("sk %p len %d", sk, (int)len);
1502
1503 count = min_t(unsigned int, (conn->mtu - hlen), len);
1504 skb = bt_skb_send_alloc(sk, count + hlen,
1505 msg->msg_flags & MSG_DONTWAIT, &err);
1506 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001507 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001508
1509 /* Create L2CAP header */
1510 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001511 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001512 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1513
1514 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1515 if (unlikely(err < 0)) {
1516 kfree_skb(skb);
1517 return ERR_PTR(err);
1518 }
1519 return skb;
1520}
1521
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001522struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001523{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001524 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001525 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001526 struct sk_buff *skb;
1527 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1528 struct l2cap_hdr *lh;
1529
1530 BT_DBG("sk %p len %d", sk, (int)len);
1531
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001532 if (!conn)
1533 return ERR_PTR(-ENOTCONN);
1534
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001535 if (sdulen)
1536 hlen += 2;
1537
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001538 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001539 hlen += 2;
1540
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001541 count = min_t(unsigned int, (conn->mtu - hlen), len);
1542 skb = bt_skb_send_alloc(sk, count + hlen,
1543 msg->msg_flags & MSG_DONTWAIT, &err);
1544 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001545 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001546
1547 /* Create L2CAP header */
1548 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001549 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001550 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1551 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001552 if (sdulen)
1553 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001554
1555 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1556 if (unlikely(err < 0)) {
1557 kfree_skb(skb);
1558 return ERR_PTR(err);
1559 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001560
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001561 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001562 put_unaligned_le16(0, skb_put(skb, 2));
1563
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001564 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001565 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566}
1567
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001568int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001569{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001570 struct sk_buff *skb;
1571 struct sk_buff_head sar_queue;
1572 u16 control;
1573 size_t size = 0;
1574
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001575 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001576 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001577 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001578 if (IS_ERR(skb))
1579 return PTR_ERR(skb);
1580
1581 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001582 len -= chan->remote_mps;
1583 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001584
1585 while (len > 0) {
1586 size_t buflen;
1587
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001588 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001589 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001590 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001591 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001592 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001593 buflen = len;
1594 }
1595
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001596 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001597 if (IS_ERR(skb)) {
1598 skb_queue_purge(&sar_queue);
1599 return PTR_ERR(skb);
1600 }
1601
1602 __skb_queue_tail(&sar_queue, skb);
1603 len -= buflen;
1604 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001605 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001606 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1607 if (chan->tx_send_head == NULL)
1608 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001609
1610 return size;
1611}
1612
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001613int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1614{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001615 struct sk_buff *skb;
1616 u16 control;
1617 int err;
1618
1619 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001620 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001621 skb = l2cap_create_connless_pdu(chan, msg, len);
1622 if (IS_ERR(skb))
1623 return PTR_ERR(skb);
1624
1625 l2cap_do_send(chan, skb);
1626 return len;
1627 }
1628
1629 switch (chan->mode) {
1630 case L2CAP_MODE_BASIC:
1631 /* Check outgoing MTU */
1632 if (len > chan->omtu)
1633 return -EMSGSIZE;
1634
1635 /* Create a basic PDU */
1636 skb = l2cap_create_basic_pdu(chan, msg, len);
1637 if (IS_ERR(skb))
1638 return PTR_ERR(skb);
1639
1640 l2cap_do_send(chan, skb);
1641 err = len;
1642 break;
1643
1644 case L2CAP_MODE_ERTM:
1645 case L2CAP_MODE_STREAMING:
1646 /* Entire SDU fits into one PDU */
1647 if (len <= chan->remote_mps) {
1648 control = L2CAP_SDU_UNSEGMENTED;
1649 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1650 0);
1651 if (IS_ERR(skb))
1652 return PTR_ERR(skb);
1653
1654 __skb_queue_tail(&chan->tx_q, skb);
1655
1656 if (chan->tx_send_head == NULL)
1657 chan->tx_send_head = skb;
1658
1659 } else {
1660 /* Segment SDU into multiples PDUs */
1661 err = l2cap_sar_segment_sdu(chan, msg, len);
1662 if (err < 0)
1663 return err;
1664 }
1665
1666 if (chan->mode == L2CAP_MODE_STREAMING) {
1667 l2cap_streaming_send(chan);
1668 err = len;
1669 break;
1670 }
1671
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001672 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1673 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001674 err = len;
1675 break;
1676 }
1677
1678 err = l2cap_ertm_send(chan);
1679 if (err >= 0)
1680 err = len;
1681
1682 break;
1683
1684 default:
1685 BT_DBG("bad state %1.1x", chan->mode);
1686 err = -EBADFD;
1687 }
1688
1689 return err;
1690}
1691
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692/* Copy frame to all raw sockets on that connection */
1693static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1694{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001696 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697
1698 BT_DBG("conn %p", conn);
1699
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001700 read_lock(&conn->chan_lock);
1701 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001702 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001703 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 continue;
1705
1706 /* Don't send frame to the socket it came from */
1707 if (skb->sk == sk)
1708 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001709 nskb = skb_clone(skb, GFP_ATOMIC);
1710 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 continue;
1712
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001713 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 kfree_skb(nskb);
1715 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001716 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717}
1718
1719/* ---- L2CAP signalling commands ---- */
1720static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1721 u8 code, u8 ident, u16 dlen, void *data)
1722{
1723 struct sk_buff *skb, **frag;
1724 struct l2cap_cmd_hdr *cmd;
1725 struct l2cap_hdr *lh;
1726 int len, count;
1727
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001728 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1729 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730
1731 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1732 count = min_t(unsigned int, conn->mtu, len);
1733
1734 skb = bt_skb_alloc(count, GFP_ATOMIC);
1735 if (!skb)
1736 return NULL;
1737
1738 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001739 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001740
1741 if (conn->hcon->type == LE_LINK)
1742 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1743 else
1744 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745
1746 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1747 cmd->code = code;
1748 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001749 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750
1751 if (dlen) {
1752 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1753 memcpy(skb_put(skb, count), data, count);
1754 data += count;
1755 }
1756
1757 len -= skb->len;
1758
1759 /* Continuation fragments (no L2CAP header) */
1760 frag = &skb_shinfo(skb)->frag_list;
1761 while (len) {
1762 count = min_t(unsigned int, conn->mtu, len);
1763
1764 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1765 if (!*frag)
1766 goto fail;
1767
1768 memcpy(skb_put(*frag, count), data, count);
1769
1770 len -= count;
1771 data += count;
1772
1773 frag = &(*frag)->next;
1774 }
1775
1776 return skb;
1777
1778fail:
1779 kfree_skb(skb);
1780 return NULL;
1781}
1782
1783static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1784{
1785 struct l2cap_conf_opt *opt = *ptr;
1786 int len;
1787
1788 len = L2CAP_CONF_OPT_SIZE + opt->len;
1789 *ptr += len;
1790
1791 *type = opt->type;
1792 *olen = opt->len;
1793
1794 switch (opt->len) {
1795 case 1:
1796 *val = *((u8 *) opt->val);
1797 break;
1798
1799 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001800 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801 break;
1802
1803 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001804 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 break;
1806
1807 default:
1808 *val = (unsigned long) opt->val;
1809 break;
1810 }
1811
1812 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1813 return len;
1814}
1815
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1817{
1818 struct l2cap_conf_opt *opt = *ptr;
1819
1820 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1821
1822 opt->type = type;
1823 opt->len = len;
1824
1825 switch (len) {
1826 case 1:
1827 *((u8 *) opt->val) = val;
1828 break;
1829
1830 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001831 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 break;
1833
1834 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001835 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 break;
1837
1838 default:
1839 memcpy(opt->val, (void *) val, len);
1840 break;
1841 }
1842
1843 *ptr += L2CAP_CONF_OPT_SIZE + len;
1844}
1845
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001846static void l2cap_ack_timeout(unsigned long arg)
1847{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001848 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001849
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001850 bh_lock_sock(chan->sk);
1851 l2cap_send_ack(chan);
1852 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001853}
1854
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001855static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001856{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001857 struct sock *sk = chan->sk;
1858
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001859 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001860 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001861 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001862 chan->num_acked = 0;
1863 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001864
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001865 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1866 (unsigned long) chan);
1867 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1868 (unsigned long) chan);
1869 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001870
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001871 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001872
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001873 INIT_LIST_HEAD(&chan->srej_l);
1874
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001875
1876 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001877}
1878
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001879static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1880{
1881 switch (mode) {
1882 case L2CAP_MODE_STREAMING:
1883 case L2CAP_MODE_ERTM:
1884 if (l2cap_mode_supported(mode, remote_feat_mask))
1885 return mode;
1886 /* fall through */
1887 default:
1888 return L2CAP_MODE_BASIC;
1889 }
1890}
1891
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03001892static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001895 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 void *ptr = req->data;
1897
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001898 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001900 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001901 goto done;
1902
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001903 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001904 case L2CAP_MODE_STREAMING:
1905 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001906 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001907 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001908
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001909 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001910 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001911 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001912 break;
1913 }
1914
1915done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001916 if (chan->imtu != L2CAP_DEFAULT_MTU)
1917 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001918
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001919 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001920 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001921 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1922 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001923 break;
1924
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001925 rfc.mode = L2CAP_MODE_BASIC;
1926 rfc.txwin_size = 0;
1927 rfc.max_transmit = 0;
1928 rfc.retrans_timeout = 0;
1929 rfc.monitor_timeout = 0;
1930 rfc.max_pdu_size = 0;
1931
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001932 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1933 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001934 break;
1935
1936 case L2CAP_MODE_ERTM:
1937 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001938 rfc.txwin_size = chan->tx_win;
1939 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001940 rfc.retrans_timeout = 0;
1941 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001942 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001943 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1944 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001945
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001946 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1947 (unsigned long) &rfc);
1948
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001949 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001950 break;
1951
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001952 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001953 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001954 chan->fcs = L2CAP_FCS_NONE;
1955 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001956 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001957 break;
1958
1959 case L2CAP_MODE_STREAMING:
1960 rfc.mode = L2CAP_MODE_STREAMING;
1961 rfc.txwin_size = 0;
1962 rfc.max_transmit = 0;
1963 rfc.retrans_timeout = 0;
1964 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001965 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001966 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1967 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001968
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001969 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1970 (unsigned long) &rfc);
1971
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001972 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001973 break;
1974
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001975 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001976 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001977 chan->fcs = L2CAP_FCS_NONE;
1978 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001979 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001980 break;
1981 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001983 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001984 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985
1986 return ptr - data;
1987}
1988
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001989static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001991 struct l2cap_conf_rsp *rsp = data;
1992 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001993 void *req = chan->conf_req;
1994 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001995 int type, hint, olen;
1996 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001997 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001998 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001999 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002001 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002002
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002003 while (len >= L2CAP_CONF_OPT_SIZE) {
2004 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002006 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002007 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002008
2009 switch (type) {
2010 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002011 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002012 break;
2013
2014 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002015 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002016 break;
2017
2018 case L2CAP_CONF_QOS:
2019 break;
2020
Marcel Holtmann6464f352007-10-20 13:39:51 +02002021 case L2CAP_CONF_RFC:
2022 if (olen == sizeof(rfc))
2023 memcpy(&rfc, (void *) val, olen);
2024 break;
2025
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002026 case L2CAP_CONF_FCS:
2027 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002028 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002029
2030 break;
2031
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002032 default:
2033 if (hint)
2034 break;
2035
2036 result = L2CAP_CONF_UNKNOWN;
2037 *((u8 *) ptr++) = type;
2038 break;
2039 }
2040 }
2041
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002042 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002043 goto done;
2044
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002045 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002046 case L2CAP_MODE_STREAMING:
2047 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002048 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002049 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002050 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002051 break;
2052 }
2053
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002054 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002055 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002056
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002057 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002058 }
2059
2060done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002061 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002062 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002063 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002064
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002065 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002066 return -ECONNREFUSED;
2067
2068 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2069 sizeof(rfc), (unsigned long) &rfc);
2070 }
2071
2072
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002073 if (result == L2CAP_CONF_SUCCESS) {
2074 /* Configure output options and let the other side know
2075 * which ones we don't like. */
2076
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002077 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2078 result = L2CAP_CONF_UNACCEPT;
2079 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002080 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002081 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002082 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002083 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002084
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002085 switch (rfc.mode) {
2086 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002087 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002088 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002089 break;
2090
2091 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002092 chan->remote_tx_win = rfc.txwin_size;
2093 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002094
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002095 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2096 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002097
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002098 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002099
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002100 rfc.retrans_timeout =
2101 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2102 rfc.monitor_timeout =
2103 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002104
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002105 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002106
2107 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2108 sizeof(rfc), (unsigned long) &rfc);
2109
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002110 break;
2111
2112 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002113 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2114 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002115
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002116 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002117
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002118 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002119
2120 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2121 sizeof(rfc), (unsigned long) &rfc);
2122
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002123 break;
2124
2125 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002126 result = L2CAP_CONF_UNACCEPT;
2127
2128 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002129 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002130 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002131
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002132 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002133 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002134 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002135 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002136 rsp->result = cpu_to_le16(result);
2137 rsp->flags = cpu_to_le16(0x0000);
2138
2139 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140}
2141
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002142static 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 -03002143{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002144 struct l2cap_conf_req *req = data;
2145 void *ptr = req->data;
2146 int type, olen;
2147 unsigned long val;
2148 struct l2cap_conf_rfc rfc;
2149
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002150 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002151
2152 while (len >= L2CAP_CONF_OPT_SIZE) {
2153 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2154
2155 switch (type) {
2156 case L2CAP_CONF_MTU:
2157 if (val < L2CAP_DEFAULT_MIN_MTU) {
2158 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002159 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002160 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002161 chan->imtu = val;
2162 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002163 break;
2164
2165 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002166 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002167 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002168 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002169 break;
2170
2171 case L2CAP_CONF_RFC:
2172 if (olen == sizeof(rfc))
2173 memcpy(&rfc, (void *)val, olen);
2174
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002175 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002176 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002177 return -ECONNREFUSED;
2178
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002179 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002180
2181 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2182 sizeof(rfc), (unsigned long) &rfc);
2183 break;
2184 }
2185 }
2186
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002187 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002188 return -ECONNREFUSED;
2189
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002190 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002191
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002192 if (*result == L2CAP_CONF_SUCCESS) {
2193 switch (rfc.mode) {
2194 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002195 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2196 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2197 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002198 break;
2199 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002200 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002201 }
2202 }
2203
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002204 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002205 req->flags = cpu_to_le16(0x0000);
2206
2207 return ptr - data;
2208}
2209
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002210static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211{
2212 struct l2cap_conf_rsp *rsp = data;
2213 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002215 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002217 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002218 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002219 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220
2221 return ptr - data;
2222}
2223
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002224void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002225{
2226 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002227 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002228 u8 buf[128];
2229
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002230 rsp.scid = cpu_to_le16(chan->dcid);
2231 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002232 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2233 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2234 l2cap_send_cmd(conn, chan->ident,
2235 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2236
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002237 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002238 return;
2239
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002240 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2241 l2cap_build_conf_req(chan, buf), buf);
2242 chan->num_conf_req++;
2243}
2244
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002245static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002246{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002247 int type, olen;
2248 unsigned long val;
2249 struct l2cap_conf_rfc rfc;
2250
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002251 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002252
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002253 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002254 return;
2255
2256 while (len >= L2CAP_CONF_OPT_SIZE) {
2257 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2258
2259 switch (type) {
2260 case L2CAP_CONF_RFC:
2261 if (olen == sizeof(rfc))
2262 memcpy(&rfc, (void *)val, olen);
2263 goto done;
2264 }
2265 }
2266
2267done:
2268 switch (rfc.mode) {
2269 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002270 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2271 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2272 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002273 break;
2274 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002275 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002276 }
2277}
2278
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002279static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2280{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002281 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002282
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002283 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002284 return 0;
2285
2286 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2287 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002288 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002289
2290 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002291 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002292
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002293 l2cap_conn_start(conn);
2294 }
2295
2296 return 0;
2297}
2298
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2300{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2302 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002303 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002304 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002305 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306
2307 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002308 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309
2310 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2311
2312 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002313 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2314 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 result = L2CAP_CR_BAD_PSM;
2316 goto sendresp;
2317 }
2318
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002319 parent = pchan->sk;
2320
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002321 bh_lock_sock(parent);
2322
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002323 /* Check if the ACL is secure enough (if not SDP) */
2324 if (psm != cpu_to_le16(0x0001) &&
2325 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002326 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002327 result = L2CAP_CR_SEC_BLOCK;
2328 goto response;
2329 }
2330
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331 result = L2CAP_CR_NO_MEM;
2332
2333 /* Check for backlog size */
2334 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002335 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336 goto response;
2337 }
2338
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002339 chan = pchan->ops->new_connection(pchan->data);
2340 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 goto response;
2342
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002343 sk = chan->sk;
2344
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002345 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346
2347 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002348 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2349 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002351 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 goto response;
2353 }
2354
2355 hci_conn_hold(conn->hcon);
2356
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 bacpy(&bt_sk(sk)->src, conn->src);
2358 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002359 chan->psm = psm;
2360 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002362 bt_accept_enqueue(parent, sk);
2363
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002364 __l2cap_chan_add(conn, chan);
2365
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002366 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002368 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002370 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371
Marcel Holtmann984947d2009-02-06 23:35:19 +01002372 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002373 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002374 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002375 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002376 result = L2CAP_CR_PEND;
2377 status = L2CAP_CS_AUTHOR_PEND;
2378 parent->sk_data_ready(parent, 0);
2379 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002380 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002381 result = L2CAP_CR_SUCCESS;
2382 status = L2CAP_CS_NO_INFO;
2383 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002384 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002385 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002386 result = L2CAP_CR_PEND;
2387 status = L2CAP_CS_AUTHEN_PEND;
2388 }
2389 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002390 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002391 result = L2CAP_CR_PEND;
2392 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393 }
2394
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002395 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396
2397response:
2398 bh_unlock_sock(parent);
2399
2400sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002401 rsp.scid = cpu_to_le16(scid);
2402 rsp.dcid = cpu_to_le16(dcid);
2403 rsp.result = cpu_to_le16(result);
2404 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002406
2407 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2408 struct l2cap_info_req info;
2409 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2410
2411 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2412 conn->info_ident = l2cap_get_ident(conn);
2413
2414 mod_timer(&conn->info_timer, jiffies +
2415 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2416
2417 l2cap_send_cmd(conn, conn->info_ident,
2418 L2CAP_INFO_REQ, sizeof(info), &info);
2419 }
2420
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002421 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002422 result == L2CAP_CR_SUCCESS) {
2423 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002424 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002425 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002426 l2cap_build_conf_req(chan, buf), buf);
2427 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002428 }
2429
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 return 0;
2431}
2432
2433static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2434{
2435 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2436 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002437 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438 struct sock *sk;
2439 u8 req[128];
2440
2441 scid = __le16_to_cpu(rsp->scid);
2442 dcid = __le16_to_cpu(rsp->dcid);
2443 result = __le16_to_cpu(rsp->result);
2444 status = __le16_to_cpu(rsp->status);
2445
2446 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2447
2448 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002449 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002450 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002451 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002453 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002454 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002455 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456 }
2457
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002458 sk = chan->sk;
2459
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460 switch (result) {
2461 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002462 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002463 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002464 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002465 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002466
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002467 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002468 break;
2469
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002471 l2cap_build_conf_req(chan, req), req);
2472 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473 break;
2474
2475 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002476 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 break;
2478
2479 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002480 /* don't delete l2cap channel if sk is owned by user */
2481 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002482 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002483 __clear_chan_timer(chan);
2484 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002485 break;
2486 }
2487
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002488 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489 break;
2490 }
2491
2492 bh_unlock_sock(sk);
2493 return 0;
2494}
2495
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002496static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002497{
2498 /* FCS is enabled only in ERTM or streaming mode, if one or both
2499 * sides request it.
2500 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002501 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002502 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002503 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002504 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002505}
2506
Al Viro88219a02007-07-29 00:17:25 -07002507static 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 -07002508{
2509 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2510 u16 dcid, flags;
2511 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002512 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002514 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515
2516 dcid = __le16_to_cpu(req->dcid);
2517 flags = __le16_to_cpu(req->flags);
2518
2519 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2520
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002521 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002522 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523 return -ENOENT;
2524
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002525 sk = chan->sk;
2526
David S. Miller033b1142011-07-21 13:38:42 -07002527 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002528 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002529
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002530 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2531 rej.scid = cpu_to_le16(chan->scid);
2532 rej.dcid = cpu_to_le16(chan->dcid);
2533
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002534 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2535 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002536 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002537 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002538
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002539 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002540 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002541 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002542 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002543 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002544 L2CAP_CONF_REJECT, flags), rsp);
2545 goto unlock;
2546 }
2547
2548 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002549 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2550 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551
2552 if (flags & 0x0001) {
2553 /* Incomplete config. Send empty response. */
2554 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002555 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002556 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557 goto unlock;
2558 }
2559
2560 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002561 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002562 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002563 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002565 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002567 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002568 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002569
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002570 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002571 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002572
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002573 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002574 goto unlock;
2575
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002576 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002577 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002578
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002579 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002580
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002581 chan->next_tx_seq = 0;
2582 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002583 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002584 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002585 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002586
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002588 goto unlock;
2589 }
2590
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002591 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002592 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002594 l2cap_build_conf_req(chan, buf), buf);
2595 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 }
2597
2598unlock:
2599 bh_unlock_sock(sk);
2600 return 0;
2601}
2602
2603static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2604{
2605 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2606 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002607 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002609 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610
2611 scid = __le16_to_cpu(rsp->scid);
2612 flags = __le16_to_cpu(rsp->flags);
2613 result = __le16_to_cpu(rsp->result);
2614
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002615 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2616 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002618 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002619 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 return 0;
2621
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002622 sk = chan->sk;
2623
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624 switch (result) {
2625 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002626 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 break;
2628
2629 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002630 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002631 char req[64];
2632
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002633 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002634 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002635 goto done;
2636 }
2637
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002638 /* throw out any old stored conf requests */
2639 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002640 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2641 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002642 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002643 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002644 goto done;
2645 }
2646
2647 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2648 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002649 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002650 if (result != L2CAP_CONF_SUCCESS)
2651 goto done;
2652 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653 }
2654
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002655 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002656 sk->sk_err = ECONNRESET;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002657 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002658 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659 goto done;
2660 }
2661
2662 if (flags & 0x01)
2663 goto done;
2664
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002665 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002667 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002668 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002669
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002670 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002671 chan->next_tx_seq = 0;
2672 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002673 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002674 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002675 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002676
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677 l2cap_chan_ready(sk);
2678 }
2679
2680done:
2681 bh_unlock_sock(sk);
2682 return 0;
2683}
2684
2685static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2686{
2687 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2688 struct l2cap_disconn_rsp rsp;
2689 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002690 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691 struct sock *sk;
2692
2693 scid = __le16_to_cpu(req->scid);
2694 dcid = __le16_to_cpu(req->dcid);
2695
2696 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2697
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002698 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002699 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 return 0;
2701
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002702 sk = chan->sk;
2703
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002704 rsp.dcid = cpu_to_le16(chan->scid);
2705 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2707
2708 sk->sk_shutdown = SHUTDOWN_MASK;
2709
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002710 /* don't delete l2cap channel if sk is owned by user */
2711 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002712 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002713 __clear_chan_timer(chan);
2714 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002715 bh_unlock_sock(sk);
2716 return 0;
2717 }
2718
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002719 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 bh_unlock_sock(sk);
2721
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002722 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723 return 0;
2724}
2725
2726static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2727{
2728 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2729 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002730 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731 struct sock *sk;
2732
2733 scid = __le16_to_cpu(rsp->scid);
2734 dcid = __le16_to_cpu(rsp->dcid);
2735
2736 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2737
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002738 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002739 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 return 0;
2741
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002742 sk = chan->sk;
2743
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002744 /* don't delete l2cap channel if sk is owned by user */
2745 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002746 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002747 __clear_chan_timer(chan);
2748 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002749 bh_unlock_sock(sk);
2750 return 0;
2751 }
2752
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002753 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754 bh_unlock_sock(sk);
2755
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002756 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757 return 0;
2758}
2759
2760static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2761{
2762 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 u16 type;
2764
2765 type = __le16_to_cpu(req->type);
2766
2767 BT_DBG("type 0x%4.4x", type);
2768
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002769 if (type == L2CAP_IT_FEAT_MASK) {
2770 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002771 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002772 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2773 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2774 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002775 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002776 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2777 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002778 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002779 l2cap_send_cmd(conn, cmd->ident,
2780 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002781 } else if (type == L2CAP_IT_FIXED_CHAN) {
2782 u8 buf[12];
2783 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2784 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2785 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2786 memcpy(buf + 4, l2cap_fixed_chan, 8);
2787 l2cap_send_cmd(conn, cmd->ident,
2788 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002789 } else {
2790 struct l2cap_info_rsp rsp;
2791 rsp.type = cpu_to_le16(type);
2792 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2793 l2cap_send_cmd(conn, cmd->ident,
2794 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2795 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796
2797 return 0;
2798}
2799
2800static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2801{
2802 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2803 u16 type, result;
2804
2805 type = __le16_to_cpu(rsp->type);
2806 result = __le16_to_cpu(rsp->result);
2807
2808 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2809
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002810 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2811 if (cmd->ident != conn->info_ident ||
2812 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2813 return 0;
2814
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002815 del_timer(&conn->info_timer);
2816
Ville Tervoadb08ed2010-08-04 09:43:33 +03002817 if (result != L2CAP_IR_SUCCESS) {
2818 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2819 conn->info_ident = 0;
2820
2821 l2cap_conn_start(conn);
2822
2823 return 0;
2824 }
2825
Marcel Holtmann984947d2009-02-06 23:35:19 +01002826 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002827 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002828
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002829 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002830 struct l2cap_info_req req;
2831 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2832
2833 conn->info_ident = l2cap_get_ident(conn);
2834
2835 l2cap_send_cmd(conn, conn->info_ident,
2836 L2CAP_INFO_REQ, sizeof(req), &req);
2837 } else {
2838 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2839 conn->info_ident = 0;
2840
2841 l2cap_conn_start(conn);
2842 }
2843 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002844 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002845 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002846
2847 l2cap_conn_start(conn);
2848 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002849
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850 return 0;
2851}
2852
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002853static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002854 u16 to_multiplier)
2855{
2856 u16 max_latency;
2857
2858 if (min > max || min < 6 || max > 3200)
2859 return -EINVAL;
2860
2861 if (to_multiplier < 10 || to_multiplier > 3200)
2862 return -EINVAL;
2863
2864 if (max >= to_multiplier * 8)
2865 return -EINVAL;
2866
2867 max_latency = (to_multiplier * 8 / max) - 1;
2868 if (latency > 499 || latency > max_latency)
2869 return -EINVAL;
2870
2871 return 0;
2872}
2873
2874static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2875 struct l2cap_cmd_hdr *cmd, u8 *data)
2876{
2877 struct hci_conn *hcon = conn->hcon;
2878 struct l2cap_conn_param_update_req *req;
2879 struct l2cap_conn_param_update_rsp rsp;
2880 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002881 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002882
2883 if (!(hcon->link_mode & HCI_LM_MASTER))
2884 return -EINVAL;
2885
2886 cmd_len = __le16_to_cpu(cmd->len);
2887 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2888 return -EPROTO;
2889
2890 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002891 min = __le16_to_cpu(req->min);
2892 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002893 latency = __le16_to_cpu(req->latency);
2894 to_multiplier = __le16_to_cpu(req->to_multiplier);
2895
2896 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2897 min, max, latency, to_multiplier);
2898
2899 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002900
2901 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2902 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002903 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2904 else
2905 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2906
2907 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2908 sizeof(rsp), &rsp);
2909
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002910 if (!err)
2911 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2912
Claudio Takahaside731152011-02-11 19:28:55 -02002913 return 0;
2914}
2915
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002916static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2917 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2918{
2919 int err = 0;
2920
2921 switch (cmd->code) {
2922 case L2CAP_COMMAND_REJ:
2923 l2cap_command_rej(conn, cmd, data);
2924 break;
2925
2926 case L2CAP_CONN_REQ:
2927 err = l2cap_connect_req(conn, cmd, data);
2928 break;
2929
2930 case L2CAP_CONN_RSP:
2931 err = l2cap_connect_rsp(conn, cmd, data);
2932 break;
2933
2934 case L2CAP_CONF_REQ:
2935 err = l2cap_config_req(conn, cmd, cmd_len, data);
2936 break;
2937
2938 case L2CAP_CONF_RSP:
2939 err = l2cap_config_rsp(conn, cmd, data);
2940 break;
2941
2942 case L2CAP_DISCONN_REQ:
2943 err = l2cap_disconnect_req(conn, cmd, data);
2944 break;
2945
2946 case L2CAP_DISCONN_RSP:
2947 err = l2cap_disconnect_rsp(conn, cmd, data);
2948 break;
2949
2950 case L2CAP_ECHO_REQ:
2951 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2952 break;
2953
2954 case L2CAP_ECHO_RSP:
2955 break;
2956
2957 case L2CAP_INFO_REQ:
2958 err = l2cap_information_req(conn, cmd, data);
2959 break;
2960
2961 case L2CAP_INFO_RSP:
2962 err = l2cap_information_rsp(conn, cmd, data);
2963 break;
2964
2965 default:
2966 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2967 err = -EINVAL;
2968 break;
2969 }
2970
2971 return err;
2972}
2973
2974static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2975 struct l2cap_cmd_hdr *cmd, u8 *data)
2976{
2977 switch (cmd->code) {
2978 case L2CAP_COMMAND_REJ:
2979 return 0;
2980
2981 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002982 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002983
2984 case L2CAP_CONN_PARAM_UPDATE_RSP:
2985 return 0;
2986
2987 default:
2988 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2989 return -EINVAL;
2990 }
2991}
2992
2993static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2994 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995{
2996 u8 *data = skb->data;
2997 int len = skb->len;
2998 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002999 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000
3001 l2cap_raw_recv(conn, skb);
3002
3003 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003004 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3006 data += L2CAP_CMD_HDR_SIZE;
3007 len -= L2CAP_CMD_HDR_SIZE;
3008
Al Viro88219a02007-07-29 00:17:25 -07003009 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010
Al Viro88219a02007-07-29 00:17:25 -07003011 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 -07003012
Al Viro88219a02007-07-29 00:17:25 -07003013 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014 BT_DBG("corrupted command");
3015 break;
3016 }
3017
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003018 if (conn->hcon->type == LE_LINK)
3019 err = l2cap_le_sig_cmd(conn, &cmd, data);
3020 else
3021 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022
3023 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003024 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003025
3026 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027
3028 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003029 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3031 }
3032
Al Viro88219a02007-07-29 00:17:25 -07003033 data += cmd_len;
3034 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035 }
3036
3037 kfree_skb(skb);
3038}
3039
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003040static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003041{
3042 u16 our_fcs, rcv_fcs;
3043 int hdr_size = L2CAP_HDR_SIZE + 2;
3044
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003045 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003046 skb_trim(skb, skb->len - 2);
3047 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3048 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3049
3050 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003051 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003052 }
3053 return 0;
3054}
3055
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003056static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003057{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003058 u16 control = 0;
3059
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003060 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003061
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003062 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003063
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003064 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003065 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003066 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003067 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003068 }
3069
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003070 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003071 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003072
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003073 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003074
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003075 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003076 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003077 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003078 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003079 }
3080}
3081
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003082static 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 -03003083{
3084 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003085 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003086
3087 bt_cb(skb)->tx_seq = tx_seq;
3088 bt_cb(skb)->sar = sar;
3089
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003090 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003091 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003092 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003093 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003094 }
3095
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003096 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003097 if (tx_seq_offset < 0)
3098 tx_seq_offset += 64;
3099
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003100 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003101 if (bt_cb(next_skb)->tx_seq == tx_seq)
3102 return -EINVAL;
3103
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003104 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003105 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003106 if (next_tx_seq_offset < 0)
3107 next_tx_seq_offset += 64;
3108
3109 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003110 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003111 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003112 }
3113
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003114 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003115 break;
3116
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003117 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003118
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003119 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003120
3121 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003122}
3123
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003124static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003125{
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003126 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003127 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003128
3129 switch (control & L2CAP_CTRL_SAR) {
3130 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003131 if (test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003132 goto drop;
3133
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003134 return chan->ops->recv(chan->data, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003135
3136 case L2CAP_SDU_START:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003137 if (test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003138 goto drop;
3139
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003140 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003141
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003142 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003143 goto disconnect;
3144
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003145 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3146 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003147 return -ENOMEM;
3148
3149 /* pull sdu_len bytes only after alloc, because of Local Busy
3150 * condition we have to be sure that this will be executed
3151 * only once, i.e., when alloc does not fail */
3152 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003153
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003154 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003155
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003156 set_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003157 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003158 break;
3159
3160 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003161 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003162 goto disconnect;
3163
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003164 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003165 goto disconnect;
3166
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003167 chan->partial_sdu_len += skb->len;
3168 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003169 goto drop;
3170
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003171 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003172
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003173 break;
3174
3175 case L2CAP_SDU_END:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003176 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003177 goto disconnect;
3178
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003179 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003180 goto disconnect;
3181
Mat Martineaufadd1922011-07-07 09:39:03 -07003182 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003183
Mat Martineaufadd1922011-07-07 09:39:03 -07003184 if (chan->partial_sdu_len > chan->imtu)
3185 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003186
Mat Martineaufadd1922011-07-07 09:39:03 -07003187 if (chan->partial_sdu_len != chan->sdu_len)
3188 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003189
Mat Martineaufadd1922011-07-07 09:39:03 -07003190 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003191
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003192 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003193 if (!_skb) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003194 return -ENOMEM;
3195 }
3196
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003197 err = chan->ops->recv(chan->data, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003198 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003199 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003200 return err;
3201 }
3202
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003203 clear_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003204
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003205 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003206 break;
3207 }
3208
3209 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003210 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003211
3212drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003213 kfree_skb(chan->sdu);
3214 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003215
3216disconnect:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003217 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003218 kfree_skb(skb);
3219 return 0;
3220}
3221
Mat Martineau26f880d2011-07-07 09:39:01 -07003222static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003223{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003224 u16 control;
3225
Mat Martineau26f880d2011-07-07 09:39:01 -07003226 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003227
Mat Martineau26f880d2011-07-07 09:39:01 -07003228 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3229
3230 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3231 control |= L2CAP_SUPER_RCV_NOT_READY;
3232 l2cap_send_sframe(chan, control);
3233
3234 set_bit(CONN_RNR_SENT, &chan->conn_state);
3235
3236 __clear_ack_timer(chan);
3237}
3238
3239static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3240{
3241 u16 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003242
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003243 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003244 goto done;
3245
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003246 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003247 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003248 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003249 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003250
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003251 __clear_retrans_timer(chan);
3252 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003253
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003254 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003255
3256done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003257 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3258 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003259
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003260 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003261}
3262
Mat Martineaue3281402011-07-07 09:39:02 -07003263void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003264{
Mat Martineaue3281402011-07-07 09:39:02 -07003265 if (chan->mode == L2CAP_MODE_ERTM) {
3266 if (busy)
3267 l2cap_ertm_enter_local_busy(chan);
3268 else
3269 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003270 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003271}
3272
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003273static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003274{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003275 struct sk_buff *_skb;
3276 int err = -EINVAL;
3277
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003278 /*
3279 * TODO: We have to notify the userland if some data is lost with the
3280 * Streaming Mode.
3281 */
3282
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003283 switch (control & L2CAP_CTRL_SAR) {
3284 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003285 if (test_bit(CONN_SAR_SDU, &chan->conn_state)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003286 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003287 break;
3288 }
3289
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003290 err = chan->ops->recv(chan->data, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003291 if (!err)
3292 return 0;
3293
3294 break;
3295
3296 case L2CAP_SDU_START:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003297 if (test_bit(CONN_SAR_SDU, &chan->conn_state)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003298 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003299 break;
3300 }
3301
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003302 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003303 skb_pull(skb, 2);
3304
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003305 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003306 err = -EMSGSIZE;
3307 break;
3308 }
3309
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003310 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3311 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003312 err = -ENOMEM;
3313 break;
3314 }
3315
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003316 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003317
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003318 set_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003319 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003320 err = 0;
3321 break;
3322
3323 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003324 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003325 break;
3326
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003327 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003328
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003329 chan->partial_sdu_len += skb->len;
3330 if (chan->partial_sdu_len > chan->sdu_len)
3331 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003332 else
3333 err = 0;
3334
3335 break;
3336
3337 case L2CAP_SDU_END:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003338 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003339 break;
3340
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003341 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003342
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003343 clear_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003344 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003345
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003346 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003347 goto drop;
3348
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003349 if (chan->partial_sdu_len == chan->sdu_len) {
3350 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003351 err = chan->ops->recv(chan->data, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003352 if (err < 0)
3353 kfree_skb(_skb);
3354 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003355 err = 0;
3356
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003357drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003358 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003359 break;
3360 }
3361
3362 kfree_skb(skb);
3363 return err;
3364}
3365
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003366static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003367{
3368 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003369 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003370
Mat Martineaue3281402011-07-07 09:39:02 -07003371 while ((skb = skb_peek(&chan->srej_q)) &&
3372 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3373 int err;
3374
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003375 if (bt_cb(skb)->tx_seq != tx_seq)
3376 break;
3377
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003378 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003379 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Mat Martineaue3281402011-07-07 09:39:02 -07003380 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
3381
3382 if (err < 0) {
3383 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3384 break;
3385 }
3386
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003387 chan->buffer_seq_srej =
3388 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003389 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003390 }
3391}
3392
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003393static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003394{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003395 struct srej_list *l, *tmp;
3396 u16 control;
3397
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003398 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003399 if (l->tx_seq == tx_seq) {
3400 list_del(&l->list);
3401 kfree(l);
3402 return;
3403 }
3404 control = L2CAP_SUPER_SELECT_REJECT;
3405 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003406 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003407 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003408 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003409 }
3410}
3411
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003412static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003413{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003414 struct srej_list *new;
3415 u16 control;
3416
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003417 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003418 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003419 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003420 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003421
3422 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003423 new->tx_seq = chan->expected_tx_seq;
3424 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003425 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003426 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003427 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003428}
3429
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003430static 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 -03003431{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003432 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003433 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003434 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003435 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003436 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003437 int err = 0;
3438
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003439 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3440 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003441
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003442 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003443 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003444 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003445 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003446 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003447 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003448 }
3449
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003450 chan->expected_ack_seq = req_seq;
3451 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003452
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003453 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003454 if (tx_seq_offset < 0)
3455 tx_seq_offset += 64;
3456
3457 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003458 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003459 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003460 goto drop;
3461 }
3462
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003463 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003464 goto drop;
3465
Mat Martineau02f1b642011-06-29 14:35:19 -07003466 if (tx_seq == chan->expected_tx_seq)
3467 goto expected;
3468
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003469 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003470 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003471
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003472 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003473 struct srej_list, list);
3474 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003475 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003476 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003477
3478 list_del(&first->list);
3479 kfree(first);
3480
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003481 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003482 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003483 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003484 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003485 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003486 }
3487 } else {
3488 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003489
3490 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003491 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003492 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003493
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003494 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003495 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003496 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003497 return 0;
3498 }
3499 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003500 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003501 }
3502 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003503 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003504 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003505 if (expected_tx_seq_offset < 0)
3506 expected_tx_seq_offset += 64;
3507
3508 /* duplicated tx_seq */
3509 if (tx_seq_offset < expected_tx_seq_offset)
3510 goto drop;
3511
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003512 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003513
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003514 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003515
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003516 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003517 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003518
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003519 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003520 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003521
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003522 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003523
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003524 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003525
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003526 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003527 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003528 return 0;
3529
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003530expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003531 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003532
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003533 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003534 bt_cb(skb)->tx_seq = tx_seq;
3535 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003536 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003537 return 0;
3538 }
3539
Mat Martineaufadd1922011-07-07 09:39:03 -07003540 err = l2cap_ertm_reassembly_sdu(chan, skb, rx_control);
3541 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Mat Martineaue3281402011-07-07 09:39:02 -07003542 if (err < 0) {
3543 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3544 return err;
3545 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003546
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003547 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003548 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003549 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003550 }
3551
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003552 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003553
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003554 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3555 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003556 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003557
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003558 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003559
3560drop:
3561 kfree_skb(skb);
3562 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003563}
3564
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003565static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003566{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003567 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003568 rx_control);
3569
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003570 chan->expected_ack_seq = __get_reqseq(rx_control);
3571 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003572
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003573 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003574 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3575 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3576 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003577 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003578 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003579
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003580 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003581 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003582 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003583 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003584 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003585
3586 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003587 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003588
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003589 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003590 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003591
3592 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003593 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003594 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003595 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003596
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003597 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3598 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003599 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003600 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003601 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003602 }
3603}
3604
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003605static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003606{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003607 u8 tx_seq = __get_reqseq(rx_control);
3608
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003609 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003610
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003611 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003612
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003613 chan->expected_ack_seq = tx_seq;
3614 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003615
3616 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003617 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003618 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003619 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003620 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003621
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003622 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3623 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003624 }
3625}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003626static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003627{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003628 u8 tx_seq = __get_reqseq(rx_control);
3629
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003630 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003631
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003632 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003633
3634 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003635 chan->expected_ack_seq = tx_seq;
3636 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003637
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003638 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003639 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003640
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003641 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003642
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003643 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003644 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003645 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003646 }
3647 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003648 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003649 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003650 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003651 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003652 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003653 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003654 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003655 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003656 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003657 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003658 }
3659 }
3660}
3661
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003662static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003663{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003664 u8 tx_seq = __get_reqseq(rx_control);
3665
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003666 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003667
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003668 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003669 chan->expected_ack_seq = tx_seq;
3670 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003671
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003672 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003673 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003674
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003675 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003676 __clear_retrans_timer(chan);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003677 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003678 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003679 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003680 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003681
3682 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003683 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003684 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003685 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003686}
3687
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003688static 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 -03003689{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003690 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003691
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003692 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003693 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003694 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003695 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003696 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003697 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003698 }
3699
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003700 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3701 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003702 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003703 break;
3704
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003705 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003706 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003707 break;
3708
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003709 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003710 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003711 break;
3712
3713 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003714 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003715 break;
3716 }
3717
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003718 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003719 return 0;
3720}
3721
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003722static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3723{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003724 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003725 u16 control;
3726 u8 req_seq;
3727 int len, next_tx_seq_offset, req_seq_offset;
3728
3729 control = get_unaligned_le16(skb->data);
3730 skb_pull(skb, 2);
3731 len = skb->len;
3732
3733 /*
3734 * We can just drop the corrupted I-frame here.
3735 * Receiver will miss it and start proper recovery
3736 * procedures and ask retransmission.
3737 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003738 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003739 goto drop;
3740
3741 if (__is_sar_start(control) && __is_iframe(control))
3742 len -= 2;
3743
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003744 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003745 len -= 2;
3746
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003747 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003748 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003749 goto drop;
3750 }
3751
3752 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003753 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003754 if (req_seq_offset < 0)
3755 req_seq_offset += 64;
3756
3757 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003758 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003759 if (next_tx_seq_offset < 0)
3760 next_tx_seq_offset += 64;
3761
3762 /* check for invalid req-seq */
3763 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003764 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003765 goto drop;
3766 }
3767
3768 if (__is_iframe(control)) {
3769 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003770 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003771 goto drop;
3772 }
3773
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003774 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003775 } else {
3776 if (len != 0) {
3777 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003778 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003779 goto drop;
3780 }
3781
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003782 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003783 }
3784
3785 return 0;
3786
3787drop:
3788 kfree_skb(skb);
3789 return 0;
3790}
3791
Linus Torvalds1da177e2005-04-16 15:20:36 -07003792static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3793{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003794 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003795 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003796 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003797 u8 tx_seq;
3798 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003799
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003800 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003801 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802 BT_DBG("unknown cid 0x%4.4x", cid);
3803 goto drop;
3804 }
3805
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003806 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003807
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003808 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003810 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003811 goto drop;
3812
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003813 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003814 case L2CAP_MODE_BASIC:
3815 /* If socket recv buffers overflows we drop data here
3816 * which is *bad* because L2CAP has to be reliable.
3817 * But we don't have any other choice. L2CAP doesn't
3818 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003820 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003821 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003823 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003824 goto done;
3825 break;
3826
3827 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003828 if (!sock_owned_by_user(sk)) {
3829 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003830 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003831 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003832 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003833 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003834
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003835 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003836
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003837 case L2CAP_MODE_STREAMING:
3838 control = get_unaligned_le16(skb->data);
3839 skb_pull(skb, 2);
3840 len = skb->len;
3841
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003842 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003843 goto drop;
3844
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003845 if (__is_sar_start(control))
3846 len -= 2;
3847
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003848 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003849 len -= 2;
3850
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003851 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003852 goto drop;
3853
3854 tx_seq = __get_txseq(control);
3855
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003856 if (chan->expected_tx_seq == tx_seq)
3857 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003858 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003859 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003860
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003861 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003862
3863 goto done;
3864
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003865 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003866 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003867 break;
3868 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869
3870drop:
3871 kfree_skb(skb);
3872
3873done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003874 if (sk)
3875 bh_unlock_sock(sk);
3876
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877 return 0;
3878}
3879
Al Viro8e036fc2007-07-29 00:16:36 -07003880static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003882 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003883 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003884
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003885 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3886 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887 goto drop;
3888
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003889 sk = chan->sk;
3890
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003891 bh_lock_sock(sk);
3892
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893 BT_DBG("sk %p, len %d", sk, skb->len);
3894
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003895 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896 goto drop;
3897
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003898 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899 goto drop;
3900
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003901 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902 goto done;
3903
3904drop:
3905 kfree_skb(skb);
3906
3907done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003908 if (sk)
3909 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910 return 0;
3911}
3912
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003913static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3914{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003915 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003916 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003917
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003918 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3919 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003920 goto drop;
3921
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003922 sk = chan->sk;
3923
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003924 bh_lock_sock(sk);
3925
3926 BT_DBG("sk %p, len %d", sk, skb->len);
3927
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003928 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003929 goto drop;
3930
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003931 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003932 goto drop;
3933
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003934 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003935 goto done;
3936
3937drop:
3938 kfree_skb(skb);
3939
3940done:
3941 if (sk)
3942 bh_unlock_sock(sk);
3943 return 0;
3944}
3945
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3947{
3948 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003949 u16 cid, len;
3950 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951
3952 skb_pull(skb, L2CAP_HDR_SIZE);
3953 cid = __le16_to_cpu(lh->cid);
3954 len = __le16_to_cpu(lh->len);
3955
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003956 if (len != skb->len) {
3957 kfree_skb(skb);
3958 return;
3959 }
3960
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3962
3963 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003964 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003965 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966 l2cap_sig_channel(conn, skb);
3967 break;
3968
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003969 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003970 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003971 skb_pull(skb, 2);
3972 l2cap_conless_channel(conn, psm, skb);
3973 break;
3974
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003975 case L2CAP_CID_LE_DATA:
3976 l2cap_att_channel(conn, cid, skb);
3977 break;
3978
Anderson Brigliab501d6a2011-06-07 18:46:31 -03003979 case L2CAP_CID_SMP:
3980 if (smp_sig_channel(conn, skb))
3981 l2cap_conn_del(conn->hcon, EACCES);
3982 break;
3983
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984 default:
3985 l2cap_data_channel(conn, cid, skb);
3986 break;
3987 }
3988}
3989
3990/* ---- L2CAP interface with lower layer (HCI) ---- */
3991
3992static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3993{
3994 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003995 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996
3997 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003998 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999
4000 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4001
4002 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004003 read_lock(&chan_list_lock);
4004 list_for_each_entry(c, &chan_list, global_l) {
4005 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004006
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004007 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008 continue;
4009
4010 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004011 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004012 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004013 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004015 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4016 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004017 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004018 lm2 |= HCI_LM_MASTER;
4019 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004021 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022
4023 return exact ? lm1 : lm2;
4024}
4025
4026static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4027{
Marcel Holtmann01394182006-07-03 10:02:46 +02004028 struct l2cap_conn *conn;
4029
Linus Torvalds1da177e2005-04-16 15:20:36 -07004030 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4031
Ville Tervoacd7d372011-02-10 22:38:49 -03004032 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004033 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034
4035 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036 conn = l2cap_conn_add(hcon, status);
4037 if (conn)
4038 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004039 } else
Joe Perchese1750722011-06-29 18:18:29 -07004040 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041
4042 return 0;
4043}
4044
Marcel Holtmann2950f212009-02-12 14:02:50 +01004045static int l2cap_disconn_ind(struct hci_conn *hcon)
4046{
4047 struct l2cap_conn *conn = hcon->l2cap_data;
4048
4049 BT_DBG("hcon %p", hcon);
4050
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03004051 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004052 return 0x13;
4053
4054 return conn->disc_reason;
4055}
4056
4057static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058{
4059 BT_DBG("hcon %p reason %d", hcon, reason);
4060
Ville Tervoacd7d372011-02-10 22:38:49 -03004061 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004062 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063
Joe Perchese1750722011-06-29 18:18:29 -07004064 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004065
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066 return 0;
4067}
4068
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004069static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004070{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004071 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004072 return;
4073
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004074 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004075 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004076 __clear_chan_timer(chan);
4077 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004078 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004079 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004080 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004081 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004082 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004083 }
4084}
4085
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004086static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004088 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004089 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090
Marcel Holtmann01394182006-07-03 10:02:46 +02004091 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004093
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094 BT_DBG("conn %p", conn);
4095
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004096 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004098 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004099 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004100
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101 bh_lock_sock(sk);
4102
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004103 BT_DBG("chan->scid %d", chan->scid);
4104
4105 if (chan->scid == L2CAP_CID_LE_DATA) {
4106 if (!status && encrypt) {
4107 chan->sec_level = hcon->sec_level;
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03004108 del_timer(&conn->security_timer);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004109 l2cap_chan_ready(sk);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03004110 smp_distribute_keys(conn, 0);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004111 }
4112
4113 bh_unlock_sock(sk);
4114 continue;
4115 }
4116
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004117 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004118 bh_unlock_sock(sk);
4119 continue;
4120 }
4121
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004122 if (!status && (chan->state == BT_CONNECTED ||
4123 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004124 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004125 bh_unlock_sock(sk);
4126 continue;
4127 }
4128
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004129 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004130 if (!status) {
4131 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004132 req.scid = cpu_to_le16(chan->scid);
4133 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004134
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004135 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004136 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004137
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004138 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004139 L2CAP_CONN_REQ, sizeof(req), &req);
4140 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004141 __clear_chan_timer(chan);
4142 __set_chan_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004143 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004144 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004145 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004146 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004147
4148 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004149 if (bt_sk(sk)->defer_setup) {
4150 struct sock *parent = bt_sk(sk)->parent;
4151 res = L2CAP_CR_PEND;
4152 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004153 if (parent)
4154 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004155 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004156 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004157 res = L2CAP_CR_SUCCESS;
4158 stat = L2CAP_CS_NO_INFO;
4159 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004160 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004161 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004162 __set_chan_timer(chan, HZ / 10);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004163 res = L2CAP_CR_SEC_BLOCK;
4164 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004165 }
4166
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004167 rsp.scid = cpu_to_le16(chan->dcid);
4168 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004169 rsp.result = cpu_to_le16(res);
4170 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004171 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4172 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173 }
4174
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 bh_unlock_sock(sk);
4176 }
4177
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004178 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004179
Linus Torvalds1da177e2005-04-16 15:20:36 -07004180 return 0;
4181}
4182
4183static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4184{
4185 struct l2cap_conn *conn = hcon->l2cap_data;
4186
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004187 if (!conn)
4188 conn = l2cap_conn_add(hcon, 0);
4189
4190 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191 goto drop;
4192
4193 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4194
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004195 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004196 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004197 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004198 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199 int len;
4200
4201 if (conn->rx_len) {
4202 BT_ERR("Unexpected start frame (len %d)", skb->len);
4203 kfree_skb(conn->rx_skb);
4204 conn->rx_skb = NULL;
4205 conn->rx_len = 0;
4206 l2cap_conn_unreliable(conn, ECOMM);
4207 }
4208
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004209 /* Start fragment always begin with Basic L2CAP header */
4210 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211 BT_ERR("Frame is too short (len %d)", skb->len);
4212 l2cap_conn_unreliable(conn, ECOMM);
4213 goto drop;
4214 }
4215
4216 hdr = (struct l2cap_hdr *) skb->data;
4217 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004218 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004219
4220 if (len == skb->len) {
4221 /* Complete frame received */
4222 l2cap_recv_frame(conn, skb);
4223 return 0;
4224 }
4225
4226 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4227
4228 if (skb->len > len) {
4229 BT_ERR("Frame is too long (len %d, expected len %d)",
4230 skb->len, len);
4231 l2cap_conn_unreliable(conn, ECOMM);
4232 goto drop;
4233 }
4234
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004235 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004236
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004237 if (chan && chan->sk) {
4238 struct sock *sk = chan->sk;
4239
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004240 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004241 BT_ERR("Frame exceeding recv MTU (len %d, "
4242 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004243 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004244 bh_unlock_sock(sk);
4245 l2cap_conn_unreliable(conn, ECOMM);
4246 goto drop;
4247 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004248 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004249 }
4250
Linus Torvalds1da177e2005-04-16 15:20:36 -07004251 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004252 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4253 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254 goto drop;
4255
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004256 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004257 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004258 conn->rx_len = len - skb->len;
4259 } else {
4260 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4261
4262 if (!conn->rx_len) {
4263 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4264 l2cap_conn_unreliable(conn, ECOMM);
4265 goto drop;
4266 }
4267
4268 if (skb->len > conn->rx_len) {
4269 BT_ERR("Fragment is too long (len %d, expected %d)",
4270 skb->len, conn->rx_len);
4271 kfree_skb(conn->rx_skb);
4272 conn->rx_skb = NULL;
4273 conn->rx_len = 0;
4274 l2cap_conn_unreliable(conn, ECOMM);
4275 goto drop;
4276 }
4277
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004278 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004279 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280 conn->rx_len -= skb->len;
4281
4282 if (!conn->rx_len) {
4283 /* Complete frame received */
4284 l2cap_recv_frame(conn, conn->rx_skb);
4285 conn->rx_skb = NULL;
4286 }
4287 }
4288
4289drop:
4290 kfree_skb(skb);
4291 return 0;
4292}
4293
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004294static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004296 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004298 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004300 list_for_each_entry(c, &chan_list, global_l) {
4301 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004302
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004303 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 +01004304 batostr(&bt_sk(sk)->src),
4305 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004306 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004307 c->scid, c->dcid, c->imtu, c->omtu,
4308 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004309}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004311 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004312
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004313 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314}
4315
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004316static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4317{
4318 return single_open(file, l2cap_debugfs_show, inode->i_private);
4319}
4320
4321static const struct file_operations l2cap_debugfs_fops = {
4322 .open = l2cap_debugfs_open,
4323 .read = seq_read,
4324 .llseek = seq_lseek,
4325 .release = single_release,
4326};
4327
4328static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330static struct hci_proto l2cap_hci_proto = {
4331 .name = "L2CAP",
4332 .id = HCI_PROTO_L2CAP,
4333 .connect_ind = l2cap_connect_ind,
4334 .connect_cfm = l2cap_connect_cfm,
4335 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004336 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004337 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338 .recv_acldata = l2cap_recv_acldata
4339};
4340
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004341int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342{
4343 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004344
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004345 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346 if (err < 0)
4347 return err;
4348
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349 err = hci_register_proto(&l2cap_hci_proto);
4350 if (err < 0) {
4351 BT_ERR("L2CAP protocol registration failed");
4352 bt_sock_unregister(BTPROTO_L2CAP);
4353 goto error;
4354 }
4355
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004356 if (bt_debugfs) {
4357 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4358 bt_debugfs, NULL, &l2cap_debugfs_fops);
4359 if (!l2cap_debugfs)
4360 BT_ERR("Failed to create L2CAP debug file");
4361 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004362
Linus Torvalds1da177e2005-04-16 15:20:36 -07004363 return 0;
4364
4365error:
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004366 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367 return err;
4368}
4369
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004370void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004372 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004373
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4375 BT_ERR("L2CAP protocol unregistration failed");
4376
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004377 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004378}
4379
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004380module_param(disable_ertm, bool, 0644);
4381MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");