blob: 8136752d824bb5fc6246385c3c157e464eba3495 [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. Padovan710f9b02011-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
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300989 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) {
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300990 del_timer(&conn->security_timer);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300991 hci_conn_put(hcon);
992 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300993
994 hcon->l2cap_data = NULL;
995 kfree(conn);
996}
997
998static void security_timeout(unsigned long arg)
999{
1000 struct l2cap_conn *conn = (void *) arg;
1001
1002 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1003}
1004
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1006{
Marcel Holtmann01394182006-07-03 10:02:46 +02001007 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008
Marcel Holtmann01394182006-07-03 10:02:46 +02001009 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 return conn;
1011
Marcel Holtmann01394182006-07-03 10:02:46 +02001012 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1013 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015
1016 hcon->l2cap_data = conn;
1017 conn->hcon = hcon;
1018
Marcel Holtmann01394182006-07-03 10:02:46 +02001019 BT_DBG("hcon %p conn %p", hcon, conn);
1020
Ville Tervoacd7d372011-02-10 22:38:49 -03001021 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1022 conn->mtu = hcon->hdev->le_mtu;
1023 else
1024 conn->mtu = hcon->hdev->acl_mtu;
1025
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 conn->src = &hcon->hdev->bdaddr;
1027 conn->dst = &hcon->dst;
1028
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001029 conn->feat_mask = 0;
1030
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001032 rwlock_init(&conn->chan_lock);
1033
1034 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001036 if (hcon->type == LE_LINK)
1037 setup_timer(&conn->security_timer, security_timeout,
1038 (unsigned long) conn);
1039 else
Ville Tervob62f3282011-02-10 22:38:50 -03001040 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +00001041 (unsigned long) conn);
1042
Marcel Holtmann2950f212009-02-12 14:02:50 +01001043 conn->disc_reason = 0x13;
1044
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 return conn;
1046}
1047
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001048static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001050 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001051 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001052 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053}
1054
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056
1057/* Find socket with psm and source bdaddr.
1058 * Returns closest match.
1059 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001060static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001062 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001064 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001065
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001066 list_for_each_entry(c, &chan_list, global_l) {
1067 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001068
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001069 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 continue;
1071
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001072 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001074 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001075 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001076 return c;
1077 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078
1079 /* Closest match */
1080 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001081 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 }
1083 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001085 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001086
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001087 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088}
1089
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001090int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001092 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 bdaddr_t *src = &bt_sk(sk)->src;
1094 bdaddr_t *dst = &bt_sk(sk)->dst;
1095 struct l2cap_conn *conn;
1096 struct hci_conn *hcon;
1097 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001098 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001099 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001101 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001102 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001104 hdev = hci_get_route(dst, src);
1105 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 return -EHOSTUNREACH;
1107
1108 hci_dev_lock_bh(hdev);
1109
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001110 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001111
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001112 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001113 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001114 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001115 else
1116 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001117 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001118
Ville Tervo30e76272011-02-22 16:10:53 -03001119 if (IS_ERR(hcon)) {
1120 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001122 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123
1124 conn = l2cap_conn_add(hcon, 0);
1125 if (!conn) {
1126 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001127 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 goto done;
1129 }
1130
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 /* Update source addr of the socket */
1132 bacpy(src, conn->src);
1133
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001134 l2cap_chan_add(conn, chan);
1135
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001136 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001137 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138
1139 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001140 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001141 __clear_chan_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001142 if (l2cap_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001143 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001144 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001145 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 }
1147
Ville Tervo30e76272011-02-22 16:10:53 -03001148 err = 0;
1149
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150done:
1151 hci_dev_unlock_bh(hdev);
1152 hci_dev_put(hdev);
1153 return err;
1154}
1155
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001156int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001157{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001158 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001159 DECLARE_WAITQUEUE(wait, current);
1160 int err = 0;
1161 int timeo = HZ/5;
1162
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001163 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001164 set_current_state(TASK_INTERRUPTIBLE);
1165 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001166 if (!timeo)
1167 timeo = HZ/5;
1168
1169 if (signal_pending(current)) {
1170 err = sock_intr_errno(timeo);
1171 break;
1172 }
1173
1174 release_sock(sk);
1175 timeo = schedule_timeout(timeo);
1176 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001177 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001178
1179 err = sock_error(sk);
1180 if (err)
1181 break;
1182 }
1183 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001184 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001185 return err;
1186}
1187
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001188static void l2cap_monitor_timeout(unsigned long arg)
1189{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001190 struct l2cap_chan *chan = (void *) arg;
1191 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001192
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001193 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001194
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001195 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001196 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001197 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001198 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001199 return;
1200 }
1201
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001202 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001203 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001204
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001205 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001206 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001207}
1208
1209static void l2cap_retrans_timeout(unsigned long arg)
1210{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001211 struct l2cap_chan *chan = (void *) arg;
1212 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001213
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001214 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001215
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001216 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001217 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001218 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001219
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001220 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001221
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001222 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001223 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001224}
1225
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001226static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001227{
1228 struct sk_buff *skb;
1229
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001230 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001231 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001232 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001233 break;
1234
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001235 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001236 kfree_skb(skb);
1237
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001238 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001239 }
1240
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001241 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001242 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001243}
1244
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001245void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001246{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001247 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001248 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001249
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001250 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001251
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001252 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001253 flags = ACL_START_NO_FLUSH;
1254 else
1255 flags = ACL_START;
1256
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -07001257 bt_cb(skb)->force_active = chan->force_active;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001258 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001259}
1260
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001261void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001262{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001263 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001264 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001265
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001266 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001267 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001268 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001269 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001270
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001271 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001272 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1273 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001274 }
1275
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001276 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001277
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001278 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001279 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001280}
1281
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001282static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001283{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001284 struct sk_buff *skb, *tx_skb;
1285 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001286
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001287 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001288 if (!skb)
1289 return;
1290
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001291 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001292 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001293 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001294
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001295 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001296 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001297
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001298 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001299
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001300 if (chan->remote_max_tx &&
1301 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001302 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001303 return;
1304 }
1305
1306 tx_skb = skb_clone(skb, GFP_ATOMIC);
1307 bt_cb(skb)->retries++;
1308 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001309 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001310
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001311 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001312 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001313
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001314 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001315 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001316
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001317 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1318
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001319 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001320 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1321 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1322 }
1323
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001324 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001325}
1326
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001327int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001328{
1329 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001330 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001331 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001332
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001333 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001334 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001335
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001336 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001337
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001338 if (chan->remote_max_tx &&
1339 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001340 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001341 break;
1342 }
1343
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001344 tx_skb = skb_clone(skb, GFP_ATOMIC);
1345
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001346 bt_cb(skb)->retries++;
1347
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001348 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001349 control &= L2CAP_CTRL_SAR;
1350
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001351 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001352 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001353
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001354 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1355 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001356 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1357
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001358
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001359 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001360 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1361 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1362 }
1363
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001364 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001365
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001366 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001367
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001368 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1369 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001370
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301371 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001372 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301373
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001374 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001375
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001376 if (skb_queue_is_last(&chan->tx_q, skb))
1377 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001378 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001379 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001380
1381 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001382 }
1383
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001384 return nsent;
1385}
1386
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001387static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001388{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001389 int ret;
1390
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001391 if (!skb_queue_empty(&chan->tx_q))
1392 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001393
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001394 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001395 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001396 return ret;
1397}
1398
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001399static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001400{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001401 u16 control = 0;
1402
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001403 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001404
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001405 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001406 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001407 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001408 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001409 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001410 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001411
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001412 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001413 return;
1414
1415 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001416 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001417}
1418
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001419static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001420{
1421 struct srej_list *tail;
1422 u16 control;
1423
1424 control = L2CAP_SUPER_SELECT_REJECT;
1425 control |= L2CAP_CTRL_FINAL;
1426
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001427 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001428 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1429
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001430 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001431}
1432
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001433static 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 -07001434{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001435 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001436 struct sk_buff **frag;
1437 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001439 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001440 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441
1442 sent += count;
1443 len -= count;
1444
1445 /* Continuation fragments (no L2CAP header) */
1446 frag = &skb_shinfo(skb)->frag_list;
1447 while (len) {
1448 count = min_t(unsigned int, conn->mtu, len);
1449
1450 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1451 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001452 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001453 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1454 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455
1456 sent += count;
1457 len -= count;
1458
1459 frag = &(*frag)->next;
1460 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461
1462 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001463}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001465struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001466{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001467 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001468 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001469 struct sk_buff *skb;
1470 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1471 struct l2cap_hdr *lh;
1472
1473 BT_DBG("sk %p len %d", sk, (int)len);
1474
1475 count = min_t(unsigned int, (conn->mtu - hlen), len);
1476 skb = bt_skb_send_alloc(sk, count + hlen,
1477 msg->msg_flags & MSG_DONTWAIT, &err);
1478 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001479 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001480
1481 /* Create L2CAP header */
1482 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001483 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001484 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001485 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001486
1487 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1488 if (unlikely(err < 0)) {
1489 kfree_skb(skb);
1490 return ERR_PTR(err);
1491 }
1492 return skb;
1493}
1494
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001495struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001496{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001497 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001498 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001499 struct sk_buff *skb;
1500 int err, count, hlen = L2CAP_HDR_SIZE;
1501 struct l2cap_hdr *lh;
1502
1503 BT_DBG("sk %p len %d", sk, (int)len);
1504
1505 count = min_t(unsigned int, (conn->mtu - hlen), len);
1506 skb = bt_skb_send_alloc(sk, count + hlen,
1507 msg->msg_flags & MSG_DONTWAIT, &err);
1508 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001509 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001510
1511 /* Create L2CAP header */
1512 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001513 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001514 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1515
1516 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1517 if (unlikely(err < 0)) {
1518 kfree_skb(skb);
1519 return ERR_PTR(err);
1520 }
1521 return skb;
1522}
1523
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001524struct 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 -03001525{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001526 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001527 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001528 struct sk_buff *skb;
1529 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1530 struct l2cap_hdr *lh;
1531
1532 BT_DBG("sk %p len %d", sk, (int)len);
1533
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001534 if (!conn)
1535 return ERR_PTR(-ENOTCONN);
1536
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001537 if (sdulen)
1538 hlen += 2;
1539
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001540 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001541 hlen += 2;
1542
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001543 count = min_t(unsigned int, (conn->mtu - hlen), len);
1544 skb = bt_skb_send_alloc(sk, count + hlen,
1545 msg->msg_flags & MSG_DONTWAIT, &err);
1546 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001547 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001548
1549 /* Create L2CAP header */
1550 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001551 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001552 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1553 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001554 if (sdulen)
1555 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001556
1557 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1558 if (unlikely(err < 0)) {
1559 kfree_skb(skb);
1560 return ERR_PTR(err);
1561 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001562
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001563 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001564 put_unaligned_le16(0, skb_put(skb, 2));
1565
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001566 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001567 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568}
1569
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001570int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001571{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001572 struct sk_buff *skb;
1573 struct sk_buff_head sar_queue;
1574 u16 control;
1575 size_t size = 0;
1576
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001577 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001578 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001579 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001580 if (IS_ERR(skb))
1581 return PTR_ERR(skb);
1582
1583 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001584 len -= chan->remote_mps;
1585 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001586
1587 while (len > 0) {
1588 size_t buflen;
1589
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001590 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001591 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001592 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001593 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001594 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001595 buflen = len;
1596 }
1597
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001598 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001599 if (IS_ERR(skb)) {
1600 skb_queue_purge(&sar_queue);
1601 return PTR_ERR(skb);
1602 }
1603
1604 __skb_queue_tail(&sar_queue, skb);
1605 len -= buflen;
1606 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001607 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001608 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1609 if (chan->tx_send_head == NULL)
1610 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001611
1612 return size;
1613}
1614
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001615int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1616{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001617 struct sk_buff *skb;
1618 u16 control;
1619 int err;
1620
1621 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001622 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001623 skb = l2cap_create_connless_pdu(chan, msg, len);
1624 if (IS_ERR(skb))
1625 return PTR_ERR(skb);
1626
1627 l2cap_do_send(chan, skb);
1628 return len;
1629 }
1630
1631 switch (chan->mode) {
1632 case L2CAP_MODE_BASIC:
1633 /* Check outgoing MTU */
1634 if (len > chan->omtu)
1635 return -EMSGSIZE;
1636
1637 /* Create a basic PDU */
1638 skb = l2cap_create_basic_pdu(chan, msg, len);
1639 if (IS_ERR(skb))
1640 return PTR_ERR(skb);
1641
1642 l2cap_do_send(chan, skb);
1643 err = len;
1644 break;
1645
1646 case L2CAP_MODE_ERTM:
1647 case L2CAP_MODE_STREAMING:
1648 /* Entire SDU fits into one PDU */
1649 if (len <= chan->remote_mps) {
1650 control = L2CAP_SDU_UNSEGMENTED;
1651 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1652 0);
1653 if (IS_ERR(skb))
1654 return PTR_ERR(skb);
1655
1656 __skb_queue_tail(&chan->tx_q, skb);
1657
1658 if (chan->tx_send_head == NULL)
1659 chan->tx_send_head = skb;
1660
1661 } else {
1662 /* Segment SDU into multiples PDUs */
1663 err = l2cap_sar_segment_sdu(chan, msg, len);
1664 if (err < 0)
1665 return err;
1666 }
1667
1668 if (chan->mode == L2CAP_MODE_STREAMING) {
1669 l2cap_streaming_send(chan);
1670 err = len;
1671 break;
1672 }
1673
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001674 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1675 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001676 err = len;
1677 break;
1678 }
1679
1680 err = l2cap_ertm_send(chan);
1681 if (err >= 0)
1682 err = len;
1683
1684 break;
1685
1686 default:
1687 BT_DBG("bad state %1.1x", chan->mode);
1688 err = -EBADFD;
1689 }
1690
1691 return err;
1692}
1693
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694/* Copy frame to all raw sockets on that connection */
1695static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1696{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001698 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699
1700 BT_DBG("conn %p", conn);
1701
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001702 read_lock(&conn->chan_lock);
1703 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001704 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001705 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 continue;
1707
1708 /* Don't send frame to the socket it came from */
1709 if (skb->sk == sk)
1710 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001711 nskb = skb_clone(skb, GFP_ATOMIC);
1712 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 continue;
1714
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001715 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 kfree_skb(nskb);
1717 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001718 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719}
1720
1721/* ---- L2CAP signalling commands ---- */
1722static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1723 u8 code, u8 ident, u16 dlen, void *data)
1724{
1725 struct sk_buff *skb, **frag;
1726 struct l2cap_cmd_hdr *cmd;
1727 struct l2cap_hdr *lh;
1728 int len, count;
1729
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001730 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1731 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732
1733 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1734 count = min_t(unsigned int, conn->mtu, len);
1735
1736 skb = bt_skb_alloc(count, GFP_ATOMIC);
1737 if (!skb)
1738 return NULL;
1739
1740 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001741 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001742
1743 if (conn->hcon->type == LE_LINK)
1744 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1745 else
1746 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747
1748 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1749 cmd->code = code;
1750 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001751 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752
1753 if (dlen) {
1754 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1755 memcpy(skb_put(skb, count), data, count);
1756 data += count;
1757 }
1758
1759 len -= skb->len;
1760
1761 /* Continuation fragments (no L2CAP header) */
1762 frag = &skb_shinfo(skb)->frag_list;
1763 while (len) {
1764 count = min_t(unsigned int, conn->mtu, len);
1765
1766 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1767 if (!*frag)
1768 goto fail;
1769
1770 memcpy(skb_put(*frag, count), data, count);
1771
1772 len -= count;
1773 data += count;
1774
1775 frag = &(*frag)->next;
1776 }
1777
1778 return skb;
1779
1780fail:
1781 kfree_skb(skb);
1782 return NULL;
1783}
1784
1785static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1786{
1787 struct l2cap_conf_opt *opt = *ptr;
1788 int len;
1789
1790 len = L2CAP_CONF_OPT_SIZE + opt->len;
1791 *ptr += len;
1792
1793 *type = opt->type;
1794 *olen = opt->len;
1795
1796 switch (opt->len) {
1797 case 1:
1798 *val = *((u8 *) opt->val);
1799 break;
1800
1801 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001802 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 break;
1804
1805 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001806 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 break;
1808
1809 default:
1810 *val = (unsigned long) opt->val;
1811 break;
1812 }
1813
1814 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1815 return len;
1816}
1817
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1819{
1820 struct l2cap_conf_opt *opt = *ptr;
1821
1822 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1823
1824 opt->type = type;
1825 opt->len = len;
1826
1827 switch (len) {
1828 case 1:
1829 *((u8 *) opt->val) = val;
1830 break;
1831
1832 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001833 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 break;
1835
1836 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001837 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 break;
1839
1840 default:
1841 memcpy(opt->val, (void *) val, len);
1842 break;
1843 }
1844
1845 *ptr += L2CAP_CONF_OPT_SIZE + len;
1846}
1847
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001848static void l2cap_ack_timeout(unsigned long arg)
1849{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001850 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001851
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001852 bh_lock_sock(chan->sk);
1853 l2cap_send_ack(chan);
1854 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001855}
1856
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001857static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001858{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001859 struct sock *sk = chan->sk;
1860
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001861 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001862 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001863 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001864 chan->num_acked = 0;
1865 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001866
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001867 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1868 (unsigned long) chan);
1869 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1870 (unsigned long) chan);
1871 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001872
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001873 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001874
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001875 INIT_LIST_HEAD(&chan->srej_l);
1876
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001877
1878 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001879}
1880
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001881static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1882{
1883 switch (mode) {
1884 case L2CAP_MODE_STREAMING:
1885 case L2CAP_MODE_ERTM:
1886 if (l2cap_mode_supported(mode, remote_feat_mask))
1887 return mode;
1888 /* fall through */
1889 default:
1890 return L2CAP_MODE_BASIC;
1891 }
1892}
1893
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001894static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001897 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 void *ptr = req->data;
1899
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001900 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001902 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001903 goto done;
1904
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001905 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001906 case L2CAP_MODE_STREAMING:
1907 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001908 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001909 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001910
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001911 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001912 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001913 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001914 break;
1915 }
1916
1917done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001918 if (chan->imtu != L2CAP_DEFAULT_MTU)
1919 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001920
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001921 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001922 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001923 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1924 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001925 break;
1926
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001927 rfc.mode = L2CAP_MODE_BASIC;
1928 rfc.txwin_size = 0;
1929 rfc.max_transmit = 0;
1930 rfc.retrans_timeout = 0;
1931 rfc.monitor_timeout = 0;
1932 rfc.max_pdu_size = 0;
1933
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001934 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1935 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001936 break;
1937
1938 case L2CAP_MODE_ERTM:
1939 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001940 rfc.txwin_size = chan->tx_win;
1941 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001942 rfc.retrans_timeout = 0;
1943 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001944 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001945 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1946 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001947
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001948 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1949 (unsigned long) &rfc);
1950
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001951 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001952 break;
1953
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001954 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001955 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001956 chan->fcs = L2CAP_FCS_NONE;
1957 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001958 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001959 break;
1960
1961 case L2CAP_MODE_STREAMING:
1962 rfc.mode = L2CAP_MODE_STREAMING;
1963 rfc.txwin_size = 0;
1964 rfc.max_transmit = 0;
1965 rfc.retrans_timeout = 0;
1966 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001967 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001968 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1969 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001970
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001971 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1972 (unsigned long) &rfc);
1973
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001974 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001975 break;
1976
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001977 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001978 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001979 chan->fcs = L2CAP_FCS_NONE;
1980 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001981 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001982 break;
1983 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001985 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001986 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987
1988 return ptr - data;
1989}
1990
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001991static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001993 struct l2cap_conf_rsp *rsp = data;
1994 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001995 void *req = chan->conf_req;
1996 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001997 int type, hint, olen;
1998 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001999 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002000 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002001 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002003 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002004
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002005 while (len >= L2CAP_CONF_OPT_SIZE) {
2006 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002008 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002009 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002010
2011 switch (type) {
2012 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002013 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002014 break;
2015
2016 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002017 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002018 break;
2019
2020 case L2CAP_CONF_QOS:
2021 break;
2022
Marcel Holtmann6464f352007-10-20 13:39:51 +02002023 case L2CAP_CONF_RFC:
2024 if (olen == sizeof(rfc))
2025 memcpy(&rfc, (void *) val, olen);
2026 break;
2027
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002028 case L2CAP_CONF_FCS:
2029 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002030 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002031
2032 break;
2033
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002034 default:
2035 if (hint)
2036 break;
2037
2038 result = L2CAP_CONF_UNKNOWN;
2039 *((u8 *) ptr++) = type;
2040 break;
2041 }
2042 }
2043
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002044 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002045 goto done;
2046
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002047 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002048 case L2CAP_MODE_STREAMING:
2049 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002050 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002051 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002052 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002053 break;
2054 }
2055
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002056 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002057 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002058
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002059 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002060 }
2061
2062done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002063 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002064 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002065 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002066
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002067 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002068 return -ECONNREFUSED;
2069
2070 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2071 sizeof(rfc), (unsigned long) &rfc);
2072 }
2073
2074
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002075 if (result == L2CAP_CONF_SUCCESS) {
2076 /* Configure output options and let the other side know
2077 * which ones we don't like. */
2078
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002079 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2080 result = L2CAP_CONF_UNACCEPT;
2081 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002082 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002083 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002084 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002085 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002086
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002087 switch (rfc.mode) {
2088 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002089 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002090 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002091 break;
2092
2093 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002094 chan->remote_tx_win = rfc.txwin_size;
2095 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002096
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002097 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2098 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002099
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002100 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002101
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002102 rfc.retrans_timeout =
2103 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2104 rfc.monitor_timeout =
2105 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002106
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002107 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002108
2109 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2110 sizeof(rfc), (unsigned long) &rfc);
2111
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002112 break;
2113
2114 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002115 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2116 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002117
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002118 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002119
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002120 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002121
2122 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2123 sizeof(rfc), (unsigned long) &rfc);
2124
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002125 break;
2126
2127 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002128 result = L2CAP_CONF_UNACCEPT;
2129
2130 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002131 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002132 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002133
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002134 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002135 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002136 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002137 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002138 rsp->result = cpu_to_le16(result);
2139 rsp->flags = cpu_to_le16(0x0000);
2140
2141 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142}
2143
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002144static 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 -03002145{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002146 struct l2cap_conf_req *req = data;
2147 void *ptr = req->data;
2148 int type, olen;
2149 unsigned long val;
2150 struct l2cap_conf_rfc rfc;
2151
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002152 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002153
2154 while (len >= L2CAP_CONF_OPT_SIZE) {
2155 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2156
2157 switch (type) {
2158 case L2CAP_CONF_MTU:
2159 if (val < L2CAP_DEFAULT_MIN_MTU) {
2160 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002161 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002162 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002163 chan->imtu = val;
2164 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002165 break;
2166
2167 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002168 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002169 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002170 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002171 break;
2172
2173 case L2CAP_CONF_RFC:
2174 if (olen == sizeof(rfc))
2175 memcpy(&rfc, (void *)val, olen);
2176
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002177 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002178 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002179 return -ECONNREFUSED;
2180
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002181 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002182
2183 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2184 sizeof(rfc), (unsigned long) &rfc);
2185 break;
2186 }
2187 }
2188
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002189 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002190 return -ECONNREFUSED;
2191
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002192 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002193
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002194 if (*result == L2CAP_CONF_SUCCESS) {
2195 switch (rfc.mode) {
2196 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002197 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2198 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2199 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002200 break;
2201 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002202 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002203 }
2204 }
2205
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002206 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002207 req->flags = cpu_to_le16(0x0000);
2208
2209 return ptr - data;
2210}
2211
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002212static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213{
2214 struct l2cap_conf_rsp *rsp = data;
2215 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002217 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002219 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002220 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002221 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222
2223 return ptr - data;
2224}
2225
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002226void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002227{
2228 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002229 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002230 u8 buf[128];
2231
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002232 rsp.scid = cpu_to_le16(chan->dcid);
2233 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002234 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2235 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2236 l2cap_send_cmd(conn, chan->ident,
2237 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2238
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002239 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002240 return;
2241
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002242 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2243 l2cap_build_conf_req(chan, buf), buf);
2244 chan->num_conf_req++;
2245}
2246
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002247static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002248{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002249 int type, olen;
2250 unsigned long val;
2251 struct l2cap_conf_rfc rfc;
2252
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002253 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002254
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002255 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002256 return;
2257
2258 while (len >= L2CAP_CONF_OPT_SIZE) {
2259 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2260
2261 switch (type) {
2262 case L2CAP_CONF_RFC:
2263 if (olen == sizeof(rfc))
2264 memcpy(&rfc, (void *)val, olen);
2265 goto done;
2266 }
2267 }
2268
2269done:
2270 switch (rfc.mode) {
2271 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002272 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2273 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2274 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002275 break;
2276 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002277 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002278 }
2279}
2280
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002281static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2282{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002283 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002284
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002285 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002286 return 0;
2287
2288 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2289 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002290 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002291
2292 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002293 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002294
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002295 l2cap_conn_start(conn);
2296 }
2297
2298 return 0;
2299}
2300
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2302{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2304 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002305 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002306 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002307 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308
2309 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002310 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311
2312 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2313
2314 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002315 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2316 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 result = L2CAP_CR_BAD_PSM;
2318 goto sendresp;
2319 }
2320
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002321 parent = pchan->sk;
2322
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002323 bh_lock_sock(parent);
2324
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002325 /* Check if the ACL is secure enough (if not SDP) */
2326 if (psm != cpu_to_le16(0x0001) &&
2327 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002328 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002329 result = L2CAP_CR_SEC_BLOCK;
2330 goto response;
2331 }
2332
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 result = L2CAP_CR_NO_MEM;
2334
2335 /* Check for backlog size */
2336 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002337 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 goto response;
2339 }
2340
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002341 chan = pchan->ops->new_connection(pchan->data);
2342 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343 goto response;
2344
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002345 sk = chan->sk;
2346
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002347 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348
2349 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002350 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2351 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002353 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 goto response;
2355 }
2356
2357 hci_conn_hold(conn->hcon);
2358
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 bacpy(&bt_sk(sk)->src, conn->src);
2360 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002361 chan->psm = psm;
2362 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002364 bt_accept_enqueue(parent, sk);
2365
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002366 __l2cap_chan_add(conn, chan);
2367
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002368 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002370 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002372 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373
Marcel Holtmann984947d2009-02-06 23:35:19 +01002374 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002375 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002376 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002377 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002378 result = L2CAP_CR_PEND;
2379 status = L2CAP_CS_AUTHOR_PEND;
2380 parent->sk_data_ready(parent, 0);
2381 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002382 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002383 result = L2CAP_CR_SUCCESS;
2384 status = L2CAP_CS_NO_INFO;
2385 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002386 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002387 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002388 result = L2CAP_CR_PEND;
2389 status = L2CAP_CS_AUTHEN_PEND;
2390 }
2391 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002392 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002393 result = L2CAP_CR_PEND;
2394 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 }
2396
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002397 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398
2399response:
2400 bh_unlock_sock(parent);
2401
2402sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002403 rsp.scid = cpu_to_le16(scid);
2404 rsp.dcid = cpu_to_le16(dcid);
2405 rsp.result = cpu_to_le16(result);
2406 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002408
2409 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2410 struct l2cap_info_req info;
2411 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2412
2413 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2414 conn->info_ident = l2cap_get_ident(conn);
2415
2416 mod_timer(&conn->info_timer, jiffies +
2417 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2418
2419 l2cap_send_cmd(conn, conn->info_ident,
2420 L2CAP_INFO_REQ, sizeof(info), &info);
2421 }
2422
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002423 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002424 result == L2CAP_CR_SUCCESS) {
2425 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002426 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002427 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002428 l2cap_build_conf_req(chan, buf), buf);
2429 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002430 }
2431
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 return 0;
2433}
2434
2435static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2436{
2437 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2438 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002439 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440 struct sock *sk;
2441 u8 req[128];
2442
2443 scid = __le16_to_cpu(rsp->scid);
2444 dcid = __le16_to_cpu(rsp->dcid);
2445 result = __le16_to_cpu(rsp->result);
2446 status = __le16_to_cpu(rsp->status);
2447
2448 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2449
2450 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002451 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002452 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002453 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002455 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002456 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002457 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 }
2459
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002460 sk = chan->sk;
2461
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462 switch (result) {
2463 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002464 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002465 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002466 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002467 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002468
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002469 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002470 break;
2471
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002473 l2cap_build_conf_req(chan, req), req);
2474 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475 break;
2476
2477 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002478 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 break;
2480
2481 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002482 /* don't delete l2cap channel if sk is owned by user */
2483 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002484 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002485 __clear_chan_timer(chan);
2486 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002487 break;
2488 }
2489
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002490 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491 break;
2492 }
2493
2494 bh_unlock_sock(sk);
2495 return 0;
2496}
2497
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002498static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002499{
2500 /* FCS is enabled only in ERTM or streaming mode, if one or both
2501 * sides request it.
2502 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002503 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002504 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002505 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002506 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002507}
2508
Al Viro88219a02007-07-29 00:17:25 -07002509static 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 -07002510{
2511 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2512 u16 dcid, flags;
2513 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002514 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002516 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517
2518 dcid = __le16_to_cpu(req->dcid);
2519 flags = __le16_to_cpu(req->flags);
2520
2521 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2522
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002523 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002524 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525 return -ENOENT;
2526
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002527 sk = chan->sk;
2528
David S. Miller033b1142011-07-21 13:38:42 -07002529 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002530 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002531
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002532 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2533 rej.scid = cpu_to_le16(chan->scid);
2534 rej.dcid = cpu_to_le16(chan->dcid);
2535
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002536 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2537 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002538 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002539 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002540
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002541 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002542 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002543 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002544 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002545 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002546 L2CAP_CONF_REJECT, flags), rsp);
2547 goto unlock;
2548 }
2549
2550 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002551 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2552 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553
2554 if (flags & 0x0001) {
2555 /* Incomplete config. Send empty response. */
2556 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002557 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002558 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559 goto unlock;
2560 }
2561
2562 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002563 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002564 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002565 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002567 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002569 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002570 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002571
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002572 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002573 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002574
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002575 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002576 goto unlock;
2577
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002578 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002579 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002580
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002581 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002582
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002583 chan->next_tx_seq = 0;
2584 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002585 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002586 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002587 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002588
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002590 goto unlock;
2591 }
2592
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002593 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002594 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002596 l2cap_build_conf_req(chan, buf), buf);
2597 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598 }
2599
2600unlock:
2601 bh_unlock_sock(sk);
2602 return 0;
2603}
2604
2605static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2606{
2607 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2608 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002609 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002611 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612
2613 scid = __le16_to_cpu(rsp->scid);
2614 flags = __le16_to_cpu(rsp->flags);
2615 result = __le16_to_cpu(rsp->result);
2616
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002617 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2618 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002620 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002621 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 return 0;
2623
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002624 sk = chan->sk;
2625
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626 switch (result) {
2627 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002628 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629 break;
2630
2631 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002632 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002633 char req[64];
2634
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002635 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002636 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002637 goto done;
2638 }
2639
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002640 /* throw out any old stored conf requests */
2641 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002642 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2643 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002644 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002645 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002646 goto done;
2647 }
2648
2649 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2650 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002651 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002652 if (result != L2CAP_CONF_SUCCESS)
2653 goto done;
2654 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655 }
2656
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002657 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002658 sk->sk_err = ECONNRESET;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002659 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002660 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661 goto done;
2662 }
2663
2664 if (flags & 0x01)
2665 goto done;
2666
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002667 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002669 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002670 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002671
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002672 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002673 chan->next_tx_seq = 0;
2674 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002675 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002676 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002677 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002678
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679 l2cap_chan_ready(sk);
2680 }
2681
2682done:
2683 bh_unlock_sock(sk);
2684 return 0;
2685}
2686
2687static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2688{
2689 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2690 struct l2cap_disconn_rsp rsp;
2691 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002692 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693 struct sock *sk;
2694
2695 scid = __le16_to_cpu(req->scid);
2696 dcid = __le16_to_cpu(req->dcid);
2697
2698 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2699
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002700 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002701 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 return 0;
2703
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002704 sk = chan->sk;
2705
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002706 rsp.dcid = cpu_to_le16(chan->scid);
2707 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2709
2710 sk->sk_shutdown = SHUTDOWN_MASK;
2711
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002712 /* don't delete l2cap channel if sk is owned by user */
2713 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002714 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002715 __clear_chan_timer(chan);
2716 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002717 bh_unlock_sock(sk);
2718 return 0;
2719 }
2720
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002721 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 bh_unlock_sock(sk);
2723
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002724 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725 return 0;
2726}
2727
2728static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2729{
2730 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2731 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002732 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 struct sock *sk;
2734
2735 scid = __le16_to_cpu(rsp->scid);
2736 dcid = __le16_to_cpu(rsp->dcid);
2737
2738 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2739
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002740 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002741 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742 return 0;
2743
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002744 sk = chan->sk;
2745
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002746 /* don't delete l2cap channel if sk is owned by user */
2747 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002748 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002749 __clear_chan_timer(chan);
2750 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002751 bh_unlock_sock(sk);
2752 return 0;
2753 }
2754
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002755 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756 bh_unlock_sock(sk);
2757
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002758 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 return 0;
2760}
2761
2762static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2763{
2764 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 u16 type;
2766
2767 type = __le16_to_cpu(req->type);
2768
2769 BT_DBG("type 0x%4.4x", type);
2770
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002771 if (type == L2CAP_IT_FEAT_MASK) {
2772 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002773 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002774 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2775 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2776 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002777 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002778 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2779 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002780 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002781 l2cap_send_cmd(conn, cmd->ident,
2782 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002783 } else if (type == L2CAP_IT_FIXED_CHAN) {
2784 u8 buf[12];
2785 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2786 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2787 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2788 memcpy(buf + 4, l2cap_fixed_chan, 8);
2789 l2cap_send_cmd(conn, cmd->ident,
2790 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002791 } else {
2792 struct l2cap_info_rsp rsp;
2793 rsp.type = cpu_to_le16(type);
2794 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2795 l2cap_send_cmd(conn, cmd->ident,
2796 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2797 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798
2799 return 0;
2800}
2801
2802static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2803{
2804 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2805 u16 type, result;
2806
2807 type = __le16_to_cpu(rsp->type);
2808 result = __le16_to_cpu(rsp->result);
2809
2810 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2811
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002812 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2813 if (cmd->ident != conn->info_ident ||
2814 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2815 return 0;
2816
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002817 del_timer(&conn->info_timer);
2818
Ville Tervoadb08ed2010-08-04 09:43:33 +03002819 if (result != L2CAP_IR_SUCCESS) {
2820 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2821 conn->info_ident = 0;
2822
2823 l2cap_conn_start(conn);
2824
2825 return 0;
2826 }
2827
Marcel Holtmann984947d2009-02-06 23:35:19 +01002828 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002829 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002830
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002831 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002832 struct l2cap_info_req req;
2833 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2834
2835 conn->info_ident = l2cap_get_ident(conn);
2836
2837 l2cap_send_cmd(conn, conn->info_ident,
2838 L2CAP_INFO_REQ, sizeof(req), &req);
2839 } else {
2840 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2841 conn->info_ident = 0;
2842
2843 l2cap_conn_start(conn);
2844 }
2845 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002846 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002847 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002848
2849 l2cap_conn_start(conn);
2850 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002851
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852 return 0;
2853}
2854
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002855static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002856 u16 to_multiplier)
2857{
2858 u16 max_latency;
2859
2860 if (min > max || min < 6 || max > 3200)
2861 return -EINVAL;
2862
2863 if (to_multiplier < 10 || to_multiplier > 3200)
2864 return -EINVAL;
2865
2866 if (max >= to_multiplier * 8)
2867 return -EINVAL;
2868
2869 max_latency = (to_multiplier * 8 / max) - 1;
2870 if (latency > 499 || latency > max_latency)
2871 return -EINVAL;
2872
2873 return 0;
2874}
2875
2876static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2877 struct l2cap_cmd_hdr *cmd, u8 *data)
2878{
2879 struct hci_conn *hcon = conn->hcon;
2880 struct l2cap_conn_param_update_req *req;
2881 struct l2cap_conn_param_update_rsp rsp;
2882 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002883 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002884
2885 if (!(hcon->link_mode & HCI_LM_MASTER))
2886 return -EINVAL;
2887
2888 cmd_len = __le16_to_cpu(cmd->len);
2889 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2890 return -EPROTO;
2891
2892 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002893 min = __le16_to_cpu(req->min);
2894 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002895 latency = __le16_to_cpu(req->latency);
2896 to_multiplier = __le16_to_cpu(req->to_multiplier);
2897
2898 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2899 min, max, latency, to_multiplier);
2900
2901 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002902
2903 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2904 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002905 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2906 else
2907 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2908
2909 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2910 sizeof(rsp), &rsp);
2911
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002912 if (!err)
2913 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2914
Claudio Takahaside731152011-02-11 19:28:55 -02002915 return 0;
2916}
2917
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002918static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2919 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2920{
2921 int err = 0;
2922
2923 switch (cmd->code) {
2924 case L2CAP_COMMAND_REJ:
2925 l2cap_command_rej(conn, cmd, data);
2926 break;
2927
2928 case L2CAP_CONN_REQ:
2929 err = l2cap_connect_req(conn, cmd, data);
2930 break;
2931
2932 case L2CAP_CONN_RSP:
2933 err = l2cap_connect_rsp(conn, cmd, data);
2934 break;
2935
2936 case L2CAP_CONF_REQ:
2937 err = l2cap_config_req(conn, cmd, cmd_len, data);
2938 break;
2939
2940 case L2CAP_CONF_RSP:
2941 err = l2cap_config_rsp(conn, cmd, data);
2942 break;
2943
2944 case L2CAP_DISCONN_REQ:
2945 err = l2cap_disconnect_req(conn, cmd, data);
2946 break;
2947
2948 case L2CAP_DISCONN_RSP:
2949 err = l2cap_disconnect_rsp(conn, cmd, data);
2950 break;
2951
2952 case L2CAP_ECHO_REQ:
2953 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2954 break;
2955
2956 case L2CAP_ECHO_RSP:
2957 break;
2958
2959 case L2CAP_INFO_REQ:
2960 err = l2cap_information_req(conn, cmd, data);
2961 break;
2962
2963 case L2CAP_INFO_RSP:
2964 err = l2cap_information_rsp(conn, cmd, data);
2965 break;
2966
2967 default:
2968 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2969 err = -EINVAL;
2970 break;
2971 }
2972
2973 return err;
2974}
2975
2976static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2977 struct l2cap_cmd_hdr *cmd, u8 *data)
2978{
2979 switch (cmd->code) {
2980 case L2CAP_COMMAND_REJ:
2981 return 0;
2982
2983 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002984 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002985
2986 case L2CAP_CONN_PARAM_UPDATE_RSP:
2987 return 0;
2988
2989 default:
2990 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2991 return -EINVAL;
2992 }
2993}
2994
2995static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2996 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997{
2998 u8 *data = skb->data;
2999 int len = skb->len;
3000 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003001 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002
3003 l2cap_raw_recv(conn, skb);
3004
3005 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003006 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3008 data += L2CAP_CMD_HDR_SIZE;
3009 len -= L2CAP_CMD_HDR_SIZE;
3010
Al Viro88219a02007-07-29 00:17:25 -07003011 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012
Al Viro88219a02007-07-29 00:17:25 -07003013 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 -07003014
Al Viro88219a02007-07-29 00:17:25 -07003015 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016 BT_DBG("corrupted command");
3017 break;
3018 }
3019
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003020 if (conn->hcon->type == LE_LINK)
3021 err = l2cap_le_sig_cmd(conn, &cmd, data);
3022 else
3023 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024
3025 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003026 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003027
3028 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029
3030 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003031 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3033 }
3034
Al Viro88219a02007-07-29 00:17:25 -07003035 data += cmd_len;
3036 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037 }
3038
3039 kfree_skb(skb);
3040}
3041
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003042static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003043{
3044 u16 our_fcs, rcv_fcs;
3045 int hdr_size = L2CAP_HDR_SIZE + 2;
3046
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003047 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003048 skb_trim(skb, skb->len - 2);
3049 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3050 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3051
3052 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003053 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003054 }
3055 return 0;
3056}
3057
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003058static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003059{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003060 u16 control = 0;
3061
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003062 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003063
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003064 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003065
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003066 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003067 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003068 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003069 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003070 }
3071
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003072 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003073 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003074
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003075 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003076
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003077 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003078 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003079 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003080 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003081 }
3082}
3083
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003084static 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 -03003085{
3086 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03003087 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003088
3089 bt_cb(skb)->tx_seq = tx_seq;
3090 bt_cb(skb)->sar = sar;
3091
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003092 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003093 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003094 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003095 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003096 }
3097
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003098 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03003099 if (tx_seq_offset < 0)
3100 tx_seq_offset += 64;
3101
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003102 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003103 if (bt_cb(next_skb)->tx_seq == tx_seq)
3104 return -EINVAL;
3105
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03003106 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003107 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03003108 if (next_tx_seq_offset < 0)
3109 next_tx_seq_offset += 64;
3110
3111 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003112 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003113 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003114 }
3115
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003116 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003117 break;
3118
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003119 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003120
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003121 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003122
3123 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003124}
3125
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003126static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003127{
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003128 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003129 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003130
3131 switch (control & L2CAP_CTRL_SAR) {
3132 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003133 if (test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003134 goto drop;
3135
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003136 return chan->ops->recv(chan->data, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003137
3138 case L2CAP_SDU_START:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003139 if (test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003140 goto drop;
3141
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003142 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003143
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003144 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003145 goto disconnect;
3146
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003147 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3148 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003149 return -ENOMEM;
3150
3151 /* pull sdu_len bytes only after alloc, because of Local Busy
3152 * condition we have to be sure that this will be executed
3153 * only once, i.e., when alloc does not fail */
3154 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003155
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003156 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003157
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003158 set_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003159 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003160 break;
3161
3162 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003163 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003164 goto disconnect;
3165
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003166 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003167 goto disconnect;
3168
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003169 chan->partial_sdu_len += skb->len;
3170 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003171 goto drop;
3172
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003173 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003174
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003175 break;
3176
3177 case L2CAP_SDU_END:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003178 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003179 goto disconnect;
3180
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003181 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003182 goto disconnect;
3183
Mat Martineaufadd1922011-07-07 09:39:03 -07003184 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003185
Mat Martineaufadd1922011-07-07 09:39:03 -07003186 if (chan->partial_sdu_len > chan->imtu)
3187 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003188
Mat Martineaufadd1922011-07-07 09:39:03 -07003189 if (chan->partial_sdu_len != chan->sdu_len)
3190 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003191
Mat Martineaufadd1922011-07-07 09:39:03 -07003192 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003193
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003194 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003195 if (!_skb) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003196 return -ENOMEM;
3197 }
3198
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003199 err = chan->ops->recv(chan->data, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003200 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003201 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003202 return err;
3203 }
3204
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003205 clear_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003206
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003207 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003208 break;
3209 }
3210
3211 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003212 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003213
3214drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003215 kfree_skb(chan->sdu);
3216 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003217
3218disconnect:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003219 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003220 kfree_skb(skb);
3221 return 0;
3222}
3223
Mat Martineau26f880d2011-07-07 09:39:01 -07003224static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003225{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003226 u16 control;
3227
Mat Martineau26f880d2011-07-07 09:39:01 -07003228 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003229
Mat Martineau26f880d2011-07-07 09:39:01 -07003230 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3231
3232 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3233 control |= L2CAP_SUPER_RCV_NOT_READY;
3234 l2cap_send_sframe(chan, control);
3235
3236 set_bit(CONN_RNR_SENT, &chan->conn_state);
3237
3238 __clear_ack_timer(chan);
3239}
3240
3241static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3242{
3243 u16 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003244
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003245 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003246 goto done;
3247
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003248 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003249 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003250 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003251 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003252
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003253 __clear_retrans_timer(chan);
3254 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003255
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003256 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003257
3258done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003259 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3260 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003261
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003262 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003263}
3264
Mat Martineaue3281402011-07-07 09:39:02 -07003265void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003266{
Mat Martineaue3281402011-07-07 09:39:02 -07003267 if (chan->mode == L2CAP_MODE_ERTM) {
3268 if (busy)
3269 l2cap_ertm_enter_local_busy(chan);
3270 else
3271 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003272 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003273}
3274
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003275static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003276{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003277 struct sk_buff *_skb;
3278 int err = -EINVAL;
3279
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003280 /*
3281 * TODO: We have to notify the userland if some data is lost with the
3282 * Streaming Mode.
3283 */
3284
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003285 switch (control & L2CAP_CTRL_SAR) {
3286 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003287 if (test_bit(CONN_SAR_SDU, &chan->conn_state)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003288 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003289 break;
3290 }
3291
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003292 err = chan->ops->recv(chan->data, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003293 if (!err)
3294 return 0;
3295
3296 break;
3297
3298 case L2CAP_SDU_START:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003299 if (test_bit(CONN_SAR_SDU, &chan->conn_state)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003300 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003301 break;
3302 }
3303
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003304 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003305 skb_pull(skb, 2);
3306
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003307 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003308 err = -EMSGSIZE;
3309 break;
3310 }
3311
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003312 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3313 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003314 err = -ENOMEM;
3315 break;
3316 }
3317
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003318 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003319
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003320 set_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003321 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003322 err = 0;
3323 break;
3324
3325 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003326 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003327 break;
3328
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003329 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003330
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003331 chan->partial_sdu_len += skb->len;
3332 if (chan->partial_sdu_len > chan->sdu_len)
3333 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003334 else
3335 err = 0;
3336
3337 break;
3338
3339 case L2CAP_SDU_END:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003340 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003341 break;
3342
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003343 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003344
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003345 clear_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003346 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003347
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003348 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003349 goto drop;
3350
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003351 if (chan->partial_sdu_len == chan->sdu_len) {
3352 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003353 err = chan->ops->recv(chan->data, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003354 if (err < 0)
3355 kfree_skb(_skb);
3356 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003357 err = 0;
3358
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003359drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003360 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003361 break;
3362 }
3363
3364 kfree_skb(skb);
3365 return err;
3366}
3367
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003368static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003369{
3370 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003371 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003372
Mat Martineaue3281402011-07-07 09:39:02 -07003373 while ((skb = skb_peek(&chan->srej_q)) &&
3374 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3375 int err;
3376
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003377 if (bt_cb(skb)->tx_seq != tx_seq)
3378 break;
3379
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003380 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003381 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Mat Martineaue3281402011-07-07 09:39:02 -07003382 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
3383
3384 if (err < 0) {
3385 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3386 break;
3387 }
3388
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003389 chan->buffer_seq_srej =
3390 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003391 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003392 }
3393}
3394
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003395static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003396{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003397 struct srej_list *l, *tmp;
3398 u16 control;
3399
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003400 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003401 if (l->tx_seq == tx_seq) {
3402 list_del(&l->list);
3403 kfree(l);
3404 return;
3405 }
3406 control = L2CAP_SUPER_SELECT_REJECT;
3407 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003408 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003409 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003410 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003411 }
3412}
3413
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003414static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003415{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003416 struct srej_list *new;
3417 u16 control;
3418
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003419 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003420 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003421 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003422 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003423
3424 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003425 new->tx_seq = chan->expected_tx_seq;
3426 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003427 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003428 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003429 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003430}
3431
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003432static 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 -03003433{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003434 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003435 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003436 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003437 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003438 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003439 int err = 0;
3440
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003441 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3442 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003443
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003444 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003445 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003446 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003447 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003448 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003449 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003450 }
3451
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003452 chan->expected_ack_seq = req_seq;
3453 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003454
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003455 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003456 if (tx_seq_offset < 0)
3457 tx_seq_offset += 64;
3458
3459 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003460 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003461 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003462 goto drop;
3463 }
3464
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003465 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003466 goto drop;
3467
Mat Martineau02f1b642011-06-29 14:35:19 -07003468 if (tx_seq == chan->expected_tx_seq)
3469 goto expected;
3470
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003471 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003472 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003473
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003474 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003475 struct srej_list, list);
3476 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003477 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003478 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003479
3480 list_del(&first->list);
3481 kfree(first);
3482
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003483 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003484 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003485 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003486 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003487 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003488 }
3489 } else {
3490 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003491
3492 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003493 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003494 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003495
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003496 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003497 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003498 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003499 return 0;
3500 }
3501 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003502 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003503 }
3504 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003505 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003506 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003507 if (expected_tx_seq_offset < 0)
3508 expected_tx_seq_offset += 64;
3509
3510 /* duplicated tx_seq */
3511 if (tx_seq_offset < expected_tx_seq_offset)
3512 goto drop;
3513
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003514 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003515
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003516 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003517
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003518 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003519 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003520
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003521 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003522 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003523
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003524 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003525
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003526 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003527
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003528 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003529 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003530 return 0;
3531
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003532expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003533 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003534
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003535 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003536 bt_cb(skb)->tx_seq = tx_seq;
3537 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003538 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003539 return 0;
3540 }
3541
Mat Martineaufadd1922011-07-07 09:39:03 -07003542 err = l2cap_ertm_reassembly_sdu(chan, skb, rx_control);
3543 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Mat Martineaue3281402011-07-07 09:39:02 -07003544 if (err < 0) {
3545 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3546 return err;
3547 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003548
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003549 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003550 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003551 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003552 }
3553
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003554 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003555
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003556 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3557 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003558 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003559
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003560 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003561
3562drop:
3563 kfree_skb(skb);
3564 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003565}
3566
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003567static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003568{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003569 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003570 rx_control);
3571
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003572 chan->expected_ack_seq = __get_reqseq(rx_control);
3573 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003574
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003575 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003576 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3577 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3578 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003579 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003580 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003581
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003582 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003583 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003584 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003585 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003586 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003587
3588 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003589 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003590
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003591 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003592 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003593
3594 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003595 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003596 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003597 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003598
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003599 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3600 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003601 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003602 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003603 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003604 }
3605}
3606
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003607static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003608{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003609 u8 tx_seq = __get_reqseq(rx_control);
3610
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003611 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003612
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003613 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003614
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003615 chan->expected_ack_seq = tx_seq;
3616 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003617
3618 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003619 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003620 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003621 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003622 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003623
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003624 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3625 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003626 }
3627}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003628static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003629{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003630 u8 tx_seq = __get_reqseq(rx_control);
3631
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003632 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003633
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003634 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003635
3636 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003637 chan->expected_ack_seq = tx_seq;
3638 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003639
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003640 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003641 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003642
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003643 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003644
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003645 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003646 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003647 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003648 }
3649 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003650 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003651 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003652 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
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. Padovane0727452010-05-01 16:15:38 -03003655 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003656 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003657 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003658 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003659 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003660 }
3661 }
3662}
3663
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003664static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003665{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003666 u8 tx_seq = __get_reqseq(rx_control);
3667
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003668 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003669
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003670 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003671 chan->expected_ack_seq = tx_seq;
3672 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003673
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003674 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003675 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003676
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003677 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003678 __clear_retrans_timer(chan);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003679 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003680 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003681 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003682 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003683
3684 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003685 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003686 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003687 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003688}
3689
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003690static 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 -03003691{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003692 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003693
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003694 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003695 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003696 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003697 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003698 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003699 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003700 }
3701
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003702 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3703 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003704 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003705 break;
3706
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003707 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003708 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003709 break;
3710
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003711 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003712 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003713 break;
3714
3715 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003716 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003717 break;
3718 }
3719
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003720 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003721 return 0;
3722}
3723
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003724static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3725{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003726 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003727 u16 control;
3728 u8 req_seq;
3729 int len, next_tx_seq_offset, req_seq_offset;
3730
3731 control = get_unaligned_le16(skb->data);
3732 skb_pull(skb, 2);
3733 len = skb->len;
3734
3735 /*
3736 * We can just drop the corrupted I-frame here.
3737 * Receiver will miss it and start proper recovery
3738 * procedures and ask retransmission.
3739 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003740 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003741 goto drop;
3742
3743 if (__is_sar_start(control) && __is_iframe(control))
3744 len -= 2;
3745
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003746 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003747 len -= 2;
3748
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003749 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003750 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003751 goto drop;
3752 }
3753
3754 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003755 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003756 if (req_seq_offset < 0)
3757 req_seq_offset += 64;
3758
3759 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003760 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003761 if (next_tx_seq_offset < 0)
3762 next_tx_seq_offset += 64;
3763
3764 /* check for invalid req-seq */
3765 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003766 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003767 goto drop;
3768 }
3769
3770 if (__is_iframe(control)) {
3771 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003772 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003773 goto drop;
3774 }
3775
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003776 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003777 } else {
3778 if (len != 0) {
3779 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003780 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003781 goto drop;
3782 }
3783
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003784 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003785 }
3786
3787 return 0;
3788
3789drop:
3790 kfree_skb(skb);
3791 return 0;
3792}
3793
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3795{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003796 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003797 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003798 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003799 u8 tx_seq;
3800 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003802 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003803 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804 BT_DBG("unknown cid 0x%4.4x", cid);
3805 goto drop;
3806 }
3807
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003808 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003809
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003810 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003811
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003812 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813 goto drop;
3814
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003815 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003816 case L2CAP_MODE_BASIC:
3817 /* If socket recv buffers overflows we drop data here
3818 * which is *bad* because L2CAP has to be reliable.
3819 * But we don't have any other choice. L2CAP doesn't
3820 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003822 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003823 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003825 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003826 goto done;
3827 break;
3828
3829 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003830 if (!sock_owned_by_user(sk)) {
3831 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003832 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003833 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003834 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003835 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003836
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003837 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003838
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003839 case L2CAP_MODE_STREAMING:
3840 control = get_unaligned_le16(skb->data);
3841 skb_pull(skb, 2);
3842 len = skb->len;
3843
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003844 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003845 goto drop;
3846
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003847 if (__is_sar_start(control))
3848 len -= 2;
3849
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003850 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003851 len -= 2;
3852
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003853 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003854 goto drop;
3855
3856 tx_seq = __get_txseq(control);
3857
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003858 if (chan->expected_tx_seq == tx_seq)
3859 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003860 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003861 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003862
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003863 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003864
3865 goto done;
3866
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003867 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003868 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003869 break;
3870 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871
3872drop:
3873 kfree_skb(skb);
3874
3875done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003876 if (sk)
3877 bh_unlock_sock(sk);
3878
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879 return 0;
3880}
3881
Al Viro8e036fc2007-07-29 00:16:36 -07003882static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003884 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003885 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003886
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003887 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3888 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889 goto drop;
3890
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003891 sk = chan->sk;
3892
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003893 bh_lock_sock(sk);
3894
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895 BT_DBG("sk %p, len %d", sk, skb->len);
3896
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003897 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 goto drop;
3899
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003900 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901 goto drop;
3902
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003903 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904 goto done;
3905
3906drop:
3907 kfree_skb(skb);
3908
3909done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003910 if (sk)
3911 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912 return 0;
3913}
3914
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003915static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3916{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003917 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003918 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003919
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003920 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3921 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003922 goto drop;
3923
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003924 sk = chan->sk;
3925
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003926 bh_lock_sock(sk);
3927
3928 BT_DBG("sk %p, len %d", sk, skb->len);
3929
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003930 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003931 goto drop;
3932
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003933 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003934 goto drop;
3935
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003936 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003937 goto done;
3938
3939drop:
3940 kfree_skb(skb);
3941
3942done:
3943 if (sk)
3944 bh_unlock_sock(sk);
3945 return 0;
3946}
3947
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3949{
3950 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003951 u16 cid, len;
3952 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953
3954 skb_pull(skb, L2CAP_HDR_SIZE);
3955 cid = __le16_to_cpu(lh->cid);
3956 len = __le16_to_cpu(lh->len);
3957
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003958 if (len != skb->len) {
3959 kfree_skb(skb);
3960 return;
3961 }
3962
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3964
3965 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003966 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003967 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968 l2cap_sig_channel(conn, skb);
3969 break;
3970
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003971 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003972 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973 skb_pull(skb, 2);
3974 l2cap_conless_channel(conn, psm, skb);
3975 break;
3976
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003977 case L2CAP_CID_LE_DATA:
3978 l2cap_att_channel(conn, cid, skb);
3979 break;
3980
Anderson Brigliab501d6a2011-06-07 18:46:31 -03003981 case L2CAP_CID_SMP:
3982 if (smp_sig_channel(conn, skb))
3983 l2cap_conn_del(conn->hcon, EACCES);
3984 break;
3985
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986 default:
3987 l2cap_data_channel(conn, cid, skb);
3988 break;
3989 }
3990}
3991
3992/* ---- L2CAP interface with lower layer (HCI) ---- */
3993
3994static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3995{
3996 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003997 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998
3999 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004000 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004001
4002 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4003
4004 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004005 read_lock(&chan_list_lock);
4006 list_for_each_entry(c, &chan_list, global_l) {
4007 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004008
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004009 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010 continue;
4011
4012 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004013 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004014 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004015 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004017 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4018 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004019 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004020 lm2 |= HCI_LM_MASTER;
4021 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004023 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024
4025 return exact ? lm1 : lm2;
4026}
4027
4028static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4029{
Marcel Holtmann01394182006-07-03 10:02:46 +02004030 struct l2cap_conn *conn;
4031
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4033
Ville Tervoacd7d372011-02-10 22:38:49 -03004034 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004035 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036
4037 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004038 conn = l2cap_conn_add(hcon, status);
4039 if (conn)
4040 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004041 } else
Joe Perchese1750722011-06-29 18:18:29 -07004042 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043
4044 return 0;
4045}
4046
Marcel Holtmann2950f212009-02-12 14:02:50 +01004047static int l2cap_disconn_ind(struct hci_conn *hcon)
4048{
4049 struct l2cap_conn *conn = hcon->l2cap_data;
4050
4051 BT_DBG("hcon %p", hcon);
4052
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03004053 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004054 return 0x13;
4055
4056 return conn->disc_reason;
4057}
4058
4059static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060{
4061 BT_DBG("hcon %p reason %d", hcon, reason);
4062
Ville Tervoacd7d372011-02-10 22:38:49 -03004063 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004064 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065
Joe Perchese1750722011-06-29 18:18:29 -07004066 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004067
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068 return 0;
4069}
4070
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004071static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004072{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004073 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004074 return;
4075
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004076 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004077 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004078 __clear_chan_timer(chan);
4079 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004080 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004081 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004082 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004083 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004084 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004085 }
4086}
4087
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004088static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004090 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004091 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092
Marcel Holtmann01394182006-07-03 10:02:46 +02004093 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004095
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096 BT_DBG("conn %p", conn);
4097
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004098 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004100 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004101 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004102
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103 bh_lock_sock(sk);
4104
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004105 BT_DBG("chan->scid %d", chan->scid);
4106
4107 if (chan->scid == L2CAP_CID_LE_DATA) {
4108 if (!status && encrypt) {
4109 chan->sec_level = hcon->sec_level;
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03004110 del_timer(&conn->security_timer);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004111 l2cap_chan_ready(sk);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03004112 smp_distribute_keys(conn, 0);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004113 }
4114
4115 bh_unlock_sock(sk);
4116 continue;
4117 }
4118
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004119 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004120 bh_unlock_sock(sk);
4121 continue;
4122 }
4123
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004124 if (!status && (chan->state == BT_CONNECTED ||
4125 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004126 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004127 bh_unlock_sock(sk);
4128 continue;
4129 }
4130
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004131 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004132 if (!status) {
4133 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004134 req.scid = cpu_to_le16(chan->scid);
4135 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004136
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004137 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004138 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004139
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004140 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004141 L2CAP_CONN_REQ, sizeof(req), &req);
4142 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004143 __clear_chan_timer(chan);
4144 __set_chan_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004145 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004146 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004147 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004148 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004149
4150 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004151 if (bt_sk(sk)->defer_setup) {
4152 struct sock *parent = bt_sk(sk)->parent;
4153 res = L2CAP_CR_PEND;
4154 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004155 if (parent)
4156 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004157 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004158 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004159 res = L2CAP_CR_SUCCESS;
4160 stat = L2CAP_CS_NO_INFO;
4161 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004162 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004163 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004164 __set_chan_timer(chan, HZ / 10);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004165 res = L2CAP_CR_SEC_BLOCK;
4166 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004167 }
4168
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004169 rsp.scid = cpu_to_le16(chan->dcid);
4170 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004171 rsp.result = cpu_to_le16(res);
4172 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004173 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4174 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 }
4176
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177 bh_unlock_sock(sk);
4178 }
4179
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004180 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004181
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182 return 0;
4183}
4184
4185static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4186{
4187 struct l2cap_conn *conn = hcon->l2cap_data;
4188
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004189 if (!conn)
4190 conn = l2cap_conn_add(hcon, 0);
4191
4192 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004193 goto drop;
4194
4195 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4196
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004197 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004199 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004200 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004201 int len;
4202
4203 if (conn->rx_len) {
4204 BT_ERR("Unexpected start frame (len %d)", skb->len);
4205 kfree_skb(conn->rx_skb);
4206 conn->rx_skb = NULL;
4207 conn->rx_len = 0;
4208 l2cap_conn_unreliable(conn, ECOMM);
4209 }
4210
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004211 /* Start fragment always begin with Basic L2CAP header */
4212 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213 BT_ERR("Frame is too short (len %d)", skb->len);
4214 l2cap_conn_unreliable(conn, ECOMM);
4215 goto drop;
4216 }
4217
4218 hdr = (struct l2cap_hdr *) skb->data;
4219 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004220 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221
4222 if (len == skb->len) {
4223 /* Complete frame received */
4224 l2cap_recv_frame(conn, skb);
4225 return 0;
4226 }
4227
4228 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4229
4230 if (skb->len > len) {
4231 BT_ERR("Frame is too long (len %d, expected len %d)",
4232 skb->len, len);
4233 l2cap_conn_unreliable(conn, ECOMM);
4234 goto drop;
4235 }
4236
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004237 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004238
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004239 if (chan && chan->sk) {
4240 struct sock *sk = chan->sk;
4241
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004242 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004243 BT_ERR("Frame exceeding recv MTU (len %d, "
4244 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004245 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004246 bh_unlock_sock(sk);
4247 l2cap_conn_unreliable(conn, ECOMM);
4248 goto drop;
4249 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004250 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004251 }
4252
Linus Torvalds1da177e2005-04-16 15:20:36 -07004253 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004254 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4255 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256 goto drop;
4257
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004258 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004259 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260 conn->rx_len = len - skb->len;
4261 } else {
4262 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4263
4264 if (!conn->rx_len) {
4265 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4266 l2cap_conn_unreliable(conn, ECOMM);
4267 goto drop;
4268 }
4269
4270 if (skb->len > conn->rx_len) {
4271 BT_ERR("Fragment is too long (len %d, expected %d)",
4272 skb->len, conn->rx_len);
4273 kfree_skb(conn->rx_skb);
4274 conn->rx_skb = NULL;
4275 conn->rx_len = 0;
4276 l2cap_conn_unreliable(conn, ECOMM);
4277 goto drop;
4278 }
4279
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004280 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004281 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282 conn->rx_len -= skb->len;
4283
4284 if (!conn->rx_len) {
4285 /* Complete frame received */
4286 l2cap_recv_frame(conn, conn->rx_skb);
4287 conn->rx_skb = NULL;
4288 }
4289 }
4290
4291drop:
4292 kfree_skb(skb);
4293 return 0;
4294}
4295
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004296static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004298 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004300 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004302 list_for_each_entry(c, &chan_list, global_l) {
4303 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004304
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004305 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 +01004306 batostr(&bt_sk(sk)->src),
4307 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004308 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004309 c->scid, c->dcid, c->imtu, c->omtu,
4310 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004311}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004313 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004314
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004315 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004316}
4317
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004318static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4319{
4320 return single_open(file, l2cap_debugfs_show, inode->i_private);
4321}
4322
4323static const struct file_operations l2cap_debugfs_fops = {
4324 .open = l2cap_debugfs_open,
4325 .read = seq_read,
4326 .llseek = seq_lseek,
4327 .release = single_release,
4328};
4329
4330static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004331
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332static struct hci_proto l2cap_hci_proto = {
4333 .name = "L2CAP",
4334 .id = HCI_PROTO_L2CAP,
4335 .connect_ind = l2cap_connect_ind,
4336 .connect_cfm = l2cap_connect_cfm,
4337 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004338 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004339 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004340 .recv_acldata = l2cap_recv_acldata
4341};
4342
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004343int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344{
4345 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004346
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004347 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004348 if (err < 0)
4349 return err;
4350
Linus Torvalds1da177e2005-04-16 15:20:36 -07004351 err = hci_register_proto(&l2cap_hci_proto);
4352 if (err < 0) {
4353 BT_ERR("L2CAP protocol registration failed");
4354 bt_sock_unregister(BTPROTO_L2CAP);
4355 goto error;
4356 }
4357
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004358 if (bt_debugfs) {
4359 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4360 bt_debugfs, NULL, &l2cap_debugfs_fops);
4361 if (!l2cap_debugfs)
4362 BT_ERR("Failed to create L2CAP debug file");
4363 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004364
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365 return 0;
4366
4367error:
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004368 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369 return err;
4370}
4371
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004372void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004373{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004374 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4377 BT_ERR("L2CAP protocol unregistration failed");
4378
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004379 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380}
4381
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004382module_param(disable_ertm, bool, 0644);
4383MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");