blob: e699837c3b8c86fa2fbba86ce7f56fbd6260a2d7 [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
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300910 if (conn->hcon->out && conn->hcon->type == LE_LINK)
911 smp_conn_security(conn, conn->hcon->pending_sec_level);
912
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300913 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200914
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300915 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300916 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300917
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200918 bh_lock_sock(sk);
919
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300920 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300921 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300922 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300923
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300924 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300925 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300926 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200927 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300928
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300929 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300930 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200931
932 bh_unlock_sock(sk);
933 }
934
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300935 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200936}
937
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200938/* Notify sockets that we cannot guaranty reliability anymore */
939static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
940{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300941 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200942
943 BT_DBG("conn %p", conn);
944
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300945 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200946
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300947 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300948 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300949
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300950 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200951 sk->sk_err = err;
952 }
953
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300954 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200955}
956
957static void l2cap_info_timeout(unsigned long arg)
958{
959 struct l2cap_conn *conn = (void *) arg;
960
Marcel Holtmann984947d2009-02-06 23:35:19 +0100961 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100962 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100963
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200964 l2cap_conn_start(conn);
965}
966
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300967static void l2cap_conn_del(struct hci_conn *hcon, int err)
968{
969 struct l2cap_conn *conn = hcon->l2cap_data;
970 struct l2cap_chan *chan, *l;
971 struct sock *sk;
972
973 if (!conn)
974 return;
975
976 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
977
978 kfree_skb(conn->rx_skb);
979
980 /* Kill channels */
981 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
982 sk = chan->sk;
983 bh_lock_sock(sk);
984 l2cap_chan_del(chan, err);
985 bh_unlock_sock(sk);
986 chan->ops->close(chan->data);
987 }
988
989 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
990 del_timer_sync(&conn->info_timer);
991
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300992 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) {
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300993 del_timer(&conn->security_timer);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300994 hci_conn_put(hcon);
995 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300996
997 hcon->l2cap_data = NULL;
998 kfree(conn);
999}
1000
1001static void security_timeout(unsigned long arg)
1002{
1003 struct l2cap_conn *conn = (void *) arg;
1004
1005 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1006}
1007
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1009{
Marcel Holtmann01394182006-07-03 10:02:46 +02001010 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011
Marcel Holtmann01394182006-07-03 10:02:46 +02001012 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 return conn;
1014
Marcel Holtmann01394182006-07-03 10:02:46 +02001015 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1016 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018
1019 hcon->l2cap_data = conn;
1020 conn->hcon = hcon;
1021
Marcel Holtmann01394182006-07-03 10:02:46 +02001022 BT_DBG("hcon %p conn %p", hcon, conn);
1023
Ville Tervoacd7d372011-02-10 22:38:49 -03001024 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1025 conn->mtu = hcon->hdev->le_mtu;
1026 else
1027 conn->mtu = hcon->hdev->acl_mtu;
1028
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 conn->src = &hcon->hdev->bdaddr;
1030 conn->dst = &hcon->dst;
1031
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001032 conn->feat_mask = 0;
1033
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001035 rwlock_init(&conn->chan_lock);
1036
1037 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001039 if (hcon->type == LE_LINK)
1040 setup_timer(&conn->security_timer, security_timeout,
1041 (unsigned long) conn);
1042 else
Ville Tervob62f3282011-02-10 22:38:50 -03001043 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +00001044 (unsigned long) conn);
1045
Marcel Holtmann2950f212009-02-12 14:02:50 +01001046 conn->disc_reason = 0x13;
1047
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 return conn;
1049}
1050
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001051static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001053 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001054 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001055 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056}
1057
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059
1060/* Find socket with psm and source bdaddr.
1061 * Returns closest match.
1062 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001063static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001065 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001067 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001068
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001069 list_for_each_entry(c, &chan_list, global_l) {
1070 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001071
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001072 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 continue;
1074
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001075 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001077 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001078 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001079 return c;
1080 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081
1082 /* Closest match */
1083 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001084 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 }
1086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001088 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001089
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001090 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091}
1092
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001093int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001095 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 bdaddr_t *src = &bt_sk(sk)->src;
1097 bdaddr_t *dst = &bt_sk(sk)->dst;
1098 struct l2cap_conn *conn;
1099 struct hci_conn *hcon;
1100 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001101 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001102 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001104 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001105 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001107 hdev = hci_get_route(dst, src);
1108 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 return -EHOSTUNREACH;
1110
1111 hci_dev_lock_bh(hdev);
1112
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001113 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001114
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001115 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001116 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001117 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001118 else
1119 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001120 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001121
Ville Tervo30e76272011-02-22 16:10:53 -03001122 if (IS_ERR(hcon)) {
1123 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001125 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126
1127 conn = l2cap_conn_add(hcon, 0);
1128 if (!conn) {
1129 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001130 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 goto done;
1132 }
1133
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 /* Update source addr of the socket */
1135 bacpy(src, conn->src);
1136
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001137 l2cap_chan_add(conn, chan);
1138
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001139 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001140 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141
1142 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001143 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001144 __clear_chan_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001145 if (l2cap_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001146 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001147 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001148 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 }
1150
Ville Tervo30e76272011-02-22 16:10:53 -03001151 err = 0;
1152
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153done:
1154 hci_dev_unlock_bh(hdev);
1155 hci_dev_put(hdev);
1156 return err;
1157}
1158
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001159int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001160{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001161 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001162 DECLARE_WAITQUEUE(wait, current);
1163 int err = 0;
1164 int timeo = HZ/5;
1165
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001166 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001167 set_current_state(TASK_INTERRUPTIBLE);
1168 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001169 if (!timeo)
1170 timeo = HZ/5;
1171
1172 if (signal_pending(current)) {
1173 err = sock_intr_errno(timeo);
1174 break;
1175 }
1176
1177 release_sock(sk);
1178 timeo = schedule_timeout(timeo);
1179 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001180 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001181
1182 err = sock_error(sk);
1183 if (err)
1184 break;
1185 }
1186 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001187 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001188 return err;
1189}
1190
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001191static void l2cap_monitor_timeout(unsigned long arg)
1192{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001193 struct l2cap_chan *chan = (void *) arg;
1194 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001195
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001196 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001197
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001198 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001199 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001200 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001201 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001202 return;
1203 }
1204
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001205 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001206 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001207
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001208 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001209 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001210}
1211
1212static void l2cap_retrans_timeout(unsigned long arg)
1213{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001214 struct l2cap_chan *chan = (void *) arg;
1215 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001216
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001217 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001218
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001219 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001220 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001221 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001222
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001223 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001224
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001225 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001226 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001227}
1228
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001229static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001230{
1231 struct sk_buff *skb;
1232
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001233 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001234 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001235 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001236 break;
1237
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001238 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001239 kfree_skb(skb);
1240
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001241 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001242 }
1243
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001244 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001245 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001246}
1247
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001248void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001249{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001250 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001251 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001252
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001253 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001254
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001255 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001256 flags = ACL_START_NO_FLUSH;
1257 else
1258 flags = ACL_START;
1259
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -07001260 bt_cb(skb)->force_active = chan->force_active;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001261 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001262}
1263
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001264void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001265{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001266 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001267 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001268
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001269 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001270 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001271 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001272 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001273
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001274 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001275 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1276 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001277 }
1278
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001279 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001280
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001281 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001282 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001283}
1284
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001285static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001286{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001287 struct sk_buff *skb, *tx_skb;
1288 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001289
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001290 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001291 if (!skb)
1292 return;
1293
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001294 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001295 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001296 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001297
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001298 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001299 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001300
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001301 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001302
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001303 if (chan->remote_max_tx &&
1304 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001305 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001306 return;
1307 }
1308
1309 tx_skb = skb_clone(skb, GFP_ATOMIC);
1310 bt_cb(skb)->retries++;
1311 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001312 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001313
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001314 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001315 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001316
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001317 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001318 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001319
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001320 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1321
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001322 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001323 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1324 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1325 }
1326
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001327 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001328}
1329
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001330int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001331{
1332 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001333 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001334 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001335
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001336 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001337 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001338
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001339 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001340
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001341 if (chan->remote_max_tx &&
1342 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001343 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001344 break;
1345 }
1346
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001347 tx_skb = skb_clone(skb, GFP_ATOMIC);
1348
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001349 bt_cb(skb)->retries++;
1350
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001351 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001352 control &= L2CAP_CTRL_SAR;
1353
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001354 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001355 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001356
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001357 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1358 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001359 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1360
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001361
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001362 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001363 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1364 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1365 }
1366
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001367 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001368
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001369 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001370
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001371 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1372 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001373
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301374 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001375 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301376
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001377 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001378
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001379 if (skb_queue_is_last(&chan->tx_q, skb))
1380 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001381 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001382 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001383
1384 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001385 }
1386
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001387 return nsent;
1388}
1389
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001390static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001391{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001392 int ret;
1393
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001394 if (!skb_queue_empty(&chan->tx_q))
1395 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001396
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001397 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001398 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001399 return ret;
1400}
1401
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001402static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001403{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001404 u16 control = 0;
1405
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001406 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001407
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001408 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001409 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001410 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001411 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001412 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001413 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001414
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001415 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001416 return;
1417
1418 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001419 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001420}
1421
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001422static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001423{
1424 struct srej_list *tail;
1425 u16 control;
1426
1427 control = L2CAP_SUPER_SELECT_REJECT;
1428 control |= L2CAP_CTRL_FINAL;
1429
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001430 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001431 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1432
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001433 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001434}
1435
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001436static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001438 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001439 struct sk_buff **frag;
1440 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001442 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001443 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
1445 sent += count;
1446 len -= count;
1447
1448 /* Continuation fragments (no L2CAP header) */
1449 frag = &skb_shinfo(skb)->frag_list;
1450 while (len) {
1451 count = min_t(unsigned int, conn->mtu, len);
1452
1453 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1454 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001455 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001456 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1457 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458
1459 sent += count;
1460 len -= count;
1461
1462 frag = &(*frag)->next;
1463 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
1465 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001466}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001468struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001469{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001470 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001471 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001472 struct sk_buff *skb;
1473 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1474 struct l2cap_hdr *lh;
1475
1476 BT_DBG("sk %p len %d", sk, (int)len);
1477
1478 count = min_t(unsigned int, (conn->mtu - hlen), len);
1479 skb = bt_skb_send_alloc(sk, count + hlen,
1480 msg->msg_flags & MSG_DONTWAIT, &err);
1481 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001482 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001483
1484 /* Create L2CAP header */
1485 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001486 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001487 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001488 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001489
1490 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1491 if (unlikely(err < 0)) {
1492 kfree_skb(skb);
1493 return ERR_PTR(err);
1494 }
1495 return skb;
1496}
1497
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001498struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001499{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001500 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001501 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001502 struct sk_buff *skb;
1503 int err, count, hlen = L2CAP_HDR_SIZE;
1504 struct l2cap_hdr *lh;
1505
1506 BT_DBG("sk %p len %d", sk, (int)len);
1507
1508 count = min_t(unsigned int, (conn->mtu - hlen), len);
1509 skb = bt_skb_send_alloc(sk, count + hlen,
1510 msg->msg_flags & MSG_DONTWAIT, &err);
1511 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001512 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001513
1514 /* Create L2CAP header */
1515 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001516 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001517 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1518
1519 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1520 if (unlikely(err < 0)) {
1521 kfree_skb(skb);
1522 return ERR_PTR(err);
1523 }
1524 return skb;
1525}
1526
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001527struct 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 -03001528{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001529 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001530 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001531 struct sk_buff *skb;
1532 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1533 struct l2cap_hdr *lh;
1534
1535 BT_DBG("sk %p len %d", sk, (int)len);
1536
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001537 if (!conn)
1538 return ERR_PTR(-ENOTCONN);
1539
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001540 if (sdulen)
1541 hlen += 2;
1542
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001543 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001544 hlen += 2;
1545
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001546 count = min_t(unsigned int, (conn->mtu - hlen), len);
1547 skb = bt_skb_send_alloc(sk, count + hlen,
1548 msg->msg_flags & MSG_DONTWAIT, &err);
1549 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001550 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001551
1552 /* Create L2CAP header */
1553 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001554 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001555 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1556 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001557 if (sdulen)
1558 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001559
1560 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1561 if (unlikely(err < 0)) {
1562 kfree_skb(skb);
1563 return ERR_PTR(err);
1564 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001565
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001566 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001567 put_unaligned_le16(0, skb_put(skb, 2));
1568
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001569 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001570 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571}
1572
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001573int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001574{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001575 struct sk_buff *skb;
1576 struct sk_buff_head sar_queue;
1577 u16 control;
1578 size_t size = 0;
1579
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001580 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001581 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001582 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001583 if (IS_ERR(skb))
1584 return PTR_ERR(skb);
1585
1586 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001587 len -= chan->remote_mps;
1588 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001589
1590 while (len > 0) {
1591 size_t buflen;
1592
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001593 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001594 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001595 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001596 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001597 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001598 buflen = len;
1599 }
1600
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001601 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001602 if (IS_ERR(skb)) {
1603 skb_queue_purge(&sar_queue);
1604 return PTR_ERR(skb);
1605 }
1606
1607 __skb_queue_tail(&sar_queue, skb);
1608 len -= buflen;
1609 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001610 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001611 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1612 if (chan->tx_send_head == NULL)
1613 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001614
1615 return size;
1616}
1617
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001618int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1619{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001620 struct sk_buff *skb;
1621 u16 control;
1622 int err;
1623
1624 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001625 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001626 skb = l2cap_create_connless_pdu(chan, msg, len);
1627 if (IS_ERR(skb))
1628 return PTR_ERR(skb);
1629
1630 l2cap_do_send(chan, skb);
1631 return len;
1632 }
1633
1634 switch (chan->mode) {
1635 case L2CAP_MODE_BASIC:
1636 /* Check outgoing MTU */
1637 if (len > chan->omtu)
1638 return -EMSGSIZE;
1639
1640 /* Create a basic PDU */
1641 skb = l2cap_create_basic_pdu(chan, msg, len);
1642 if (IS_ERR(skb))
1643 return PTR_ERR(skb);
1644
1645 l2cap_do_send(chan, skb);
1646 err = len;
1647 break;
1648
1649 case L2CAP_MODE_ERTM:
1650 case L2CAP_MODE_STREAMING:
1651 /* Entire SDU fits into one PDU */
1652 if (len <= chan->remote_mps) {
1653 control = L2CAP_SDU_UNSEGMENTED;
1654 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1655 0);
1656 if (IS_ERR(skb))
1657 return PTR_ERR(skb);
1658
1659 __skb_queue_tail(&chan->tx_q, skb);
1660
1661 if (chan->tx_send_head == NULL)
1662 chan->tx_send_head = skb;
1663
1664 } else {
1665 /* Segment SDU into multiples PDUs */
1666 err = l2cap_sar_segment_sdu(chan, msg, len);
1667 if (err < 0)
1668 return err;
1669 }
1670
1671 if (chan->mode == L2CAP_MODE_STREAMING) {
1672 l2cap_streaming_send(chan);
1673 err = len;
1674 break;
1675 }
1676
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001677 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1678 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001679 err = len;
1680 break;
1681 }
1682
1683 err = l2cap_ertm_send(chan);
1684 if (err >= 0)
1685 err = len;
1686
1687 break;
1688
1689 default:
1690 BT_DBG("bad state %1.1x", chan->mode);
1691 err = -EBADFD;
1692 }
1693
1694 return err;
1695}
1696
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697/* Copy frame to all raw sockets on that connection */
1698static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1699{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001701 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702
1703 BT_DBG("conn %p", conn);
1704
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001705 read_lock(&conn->chan_lock);
1706 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001707 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001708 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 continue;
1710
1711 /* Don't send frame to the socket it came from */
1712 if (skb->sk == sk)
1713 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001714 nskb = skb_clone(skb, GFP_ATOMIC);
1715 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 continue;
1717
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001718 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 kfree_skb(nskb);
1720 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001721 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722}
1723
1724/* ---- L2CAP signalling commands ---- */
1725static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1726 u8 code, u8 ident, u16 dlen, void *data)
1727{
1728 struct sk_buff *skb, **frag;
1729 struct l2cap_cmd_hdr *cmd;
1730 struct l2cap_hdr *lh;
1731 int len, count;
1732
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001733 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1734 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735
1736 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1737 count = min_t(unsigned int, conn->mtu, len);
1738
1739 skb = bt_skb_alloc(count, GFP_ATOMIC);
1740 if (!skb)
1741 return NULL;
1742
1743 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001744 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001745
1746 if (conn->hcon->type == LE_LINK)
1747 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1748 else
1749 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750
1751 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1752 cmd->code = code;
1753 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001754 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755
1756 if (dlen) {
1757 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1758 memcpy(skb_put(skb, count), data, count);
1759 data += count;
1760 }
1761
1762 len -= skb->len;
1763
1764 /* Continuation fragments (no L2CAP header) */
1765 frag = &skb_shinfo(skb)->frag_list;
1766 while (len) {
1767 count = min_t(unsigned int, conn->mtu, len);
1768
1769 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1770 if (!*frag)
1771 goto fail;
1772
1773 memcpy(skb_put(*frag, count), data, count);
1774
1775 len -= count;
1776 data += count;
1777
1778 frag = &(*frag)->next;
1779 }
1780
1781 return skb;
1782
1783fail:
1784 kfree_skb(skb);
1785 return NULL;
1786}
1787
1788static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1789{
1790 struct l2cap_conf_opt *opt = *ptr;
1791 int len;
1792
1793 len = L2CAP_CONF_OPT_SIZE + opt->len;
1794 *ptr += len;
1795
1796 *type = opt->type;
1797 *olen = opt->len;
1798
1799 switch (opt->len) {
1800 case 1:
1801 *val = *((u8 *) opt->val);
1802 break;
1803
1804 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001805 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 break;
1807
1808 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001809 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 break;
1811
1812 default:
1813 *val = (unsigned long) opt->val;
1814 break;
1815 }
1816
1817 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1818 return len;
1819}
1820
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1822{
1823 struct l2cap_conf_opt *opt = *ptr;
1824
1825 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1826
1827 opt->type = type;
1828 opt->len = len;
1829
1830 switch (len) {
1831 case 1:
1832 *((u8 *) opt->val) = val;
1833 break;
1834
1835 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001836 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 break;
1838
1839 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001840 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 break;
1842
1843 default:
1844 memcpy(opt->val, (void *) val, len);
1845 break;
1846 }
1847
1848 *ptr += L2CAP_CONF_OPT_SIZE + len;
1849}
1850
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001851static void l2cap_ack_timeout(unsigned long arg)
1852{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001853 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001854
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001855 bh_lock_sock(chan->sk);
1856 l2cap_send_ack(chan);
1857 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001858}
1859
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001860static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001861{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001862 struct sock *sk = chan->sk;
1863
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001864 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001865 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001866 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001867 chan->num_acked = 0;
1868 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001869
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001870 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1871 (unsigned long) chan);
1872 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1873 (unsigned long) chan);
1874 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001875
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001876 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001877
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001878 INIT_LIST_HEAD(&chan->srej_l);
1879
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001880
1881 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001882}
1883
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001884static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1885{
1886 switch (mode) {
1887 case L2CAP_MODE_STREAMING:
1888 case L2CAP_MODE_ERTM:
1889 if (l2cap_mode_supported(mode, remote_feat_mask))
1890 return mode;
1891 /* fall through */
1892 default:
1893 return L2CAP_MODE_BASIC;
1894 }
1895}
1896
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001897static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001900 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 void *ptr = req->data;
1902
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001903 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001905 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001906 goto done;
1907
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001908 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001909 case L2CAP_MODE_STREAMING:
1910 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001911 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001912 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001913
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001914 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001915 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001916 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001917 break;
1918 }
1919
1920done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001921 if (chan->imtu != L2CAP_DEFAULT_MTU)
1922 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001923
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001924 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001925 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001926 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1927 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001928 break;
1929
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001930 rfc.mode = L2CAP_MODE_BASIC;
1931 rfc.txwin_size = 0;
1932 rfc.max_transmit = 0;
1933 rfc.retrans_timeout = 0;
1934 rfc.monitor_timeout = 0;
1935 rfc.max_pdu_size = 0;
1936
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001937 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1938 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001939 break;
1940
1941 case L2CAP_MODE_ERTM:
1942 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001943 rfc.txwin_size = chan->tx_win;
1944 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001945 rfc.retrans_timeout = 0;
1946 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001947 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001948 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1949 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001950
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001951 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1952 (unsigned long) &rfc);
1953
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001954 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001955 break;
1956
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001957 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001958 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001959 chan->fcs = L2CAP_FCS_NONE;
1960 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001961 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001962 break;
1963
1964 case L2CAP_MODE_STREAMING:
1965 rfc.mode = L2CAP_MODE_STREAMING;
1966 rfc.txwin_size = 0;
1967 rfc.max_transmit = 0;
1968 rfc.retrans_timeout = 0;
1969 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001970 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001971 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1972 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001973
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001974 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1975 (unsigned long) &rfc);
1976
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001977 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001978 break;
1979
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001980 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001981 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001982 chan->fcs = L2CAP_FCS_NONE;
1983 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001984 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001985 break;
1986 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001988 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001989 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990
1991 return ptr - data;
1992}
1993
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001994static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001996 struct l2cap_conf_rsp *rsp = data;
1997 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001998 void *req = chan->conf_req;
1999 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002000 int type, hint, olen;
2001 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002002 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002003 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002004 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002006 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002007
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002008 while (len >= L2CAP_CONF_OPT_SIZE) {
2009 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002011 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002012 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002013
2014 switch (type) {
2015 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002016 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002017 break;
2018
2019 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002020 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002021 break;
2022
2023 case L2CAP_CONF_QOS:
2024 break;
2025
Marcel Holtmann6464f352007-10-20 13:39:51 +02002026 case L2CAP_CONF_RFC:
2027 if (olen == sizeof(rfc))
2028 memcpy(&rfc, (void *) val, olen);
2029 break;
2030
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002031 case L2CAP_CONF_FCS:
2032 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002033 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002034
2035 break;
2036
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002037 default:
2038 if (hint)
2039 break;
2040
2041 result = L2CAP_CONF_UNKNOWN;
2042 *((u8 *) ptr++) = type;
2043 break;
2044 }
2045 }
2046
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002047 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002048 goto done;
2049
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002050 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002051 case L2CAP_MODE_STREAMING:
2052 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002053 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002054 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002055 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002056 break;
2057 }
2058
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002059 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002060 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002061
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002062 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002063 }
2064
2065done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002066 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002067 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002068 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002069
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002070 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002071 return -ECONNREFUSED;
2072
2073 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2074 sizeof(rfc), (unsigned long) &rfc);
2075 }
2076
2077
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002078 if (result == L2CAP_CONF_SUCCESS) {
2079 /* Configure output options and let the other side know
2080 * which ones we don't like. */
2081
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002082 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2083 result = L2CAP_CONF_UNACCEPT;
2084 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002085 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002086 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002087 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002088 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002089
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002090 switch (rfc.mode) {
2091 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002092 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002093 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002094 break;
2095
2096 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002097 chan->remote_tx_win = rfc.txwin_size;
2098 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002099
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002100 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2101 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002102
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002103 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002104
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002105 rfc.retrans_timeout =
2106 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2107 rfc.monitor_timeout =
2108 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002109
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002110 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002111
2112 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2113 sizeof(rfc), (unsigned long) &rfc);
2114
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002115 break;
2116
2117 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002118 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2119 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002120
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002121 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002122
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002123 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002124
2125 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2126 sizeof(rfc), (unsigned long) &rfc);
2127
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002128 break;
2129
2130 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002131 result = L2CAP_CONF_UNACCEPT;
2132
2133 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002134 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002135 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002136
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002137 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002138 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002139 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002140 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002141 rsp->result = cpu_to_le16(result);
2142 rsp->flags = cpu_to_le16(0x0000);
2143
2144 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145}
2146
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002147static 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 -03002148{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002149 struct l2cap_conf_req *req = data;
2150 void *ptr = req->data;
2151 int type, olen;
2152 unsigned long val;
2153 struct l2cap_conf_rfc rfc;
2154
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002155 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002156
2157 while (len >= L2CAP_CONF_OPT_SIZE) {
2158 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2159
2160 switch (type) {
2161 case L2CAP_CONF_MTU:
2162 if (val < L2CAP_DEFAULT_MIN_MTU) {
2163 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002164 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002165 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002166 chan->imtu = val;
2167 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002168 break;
2169
2170 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002171 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002172 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002173 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002174 break;
2175
2176 case L2CAP_CONF_RFC:
2177 if (olen == sizeof(rfc))
2178 memcpy(&rfc, (void *)val, olen);
2179
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002180 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002181 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002182 return -ECONNREFUSED;
2183
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002184 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002185
2186 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2187 sizeof(rfc), (unsigned long) &rfc);
2188 break;
2189 }
2190 }
2191
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002192 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002193 return -ECONNREFUSED;
2194
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002195 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002196
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002197 if (*result == L2CAP_CONF_SUCCESS) {
2198 switch (rfc.mode) {
2199 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002200 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2201 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2202 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002203 break;
2204 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002205 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002206 }
2207 }
2208
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002209 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002210 req->flags = cpu_to_le16(0x0000);
2211
2212 return ptr - data;
2213}
2214
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002215static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216{
2217 struct l2cap_conf_rsp *rsp = data;
2218 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002220 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002222 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002223 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002224 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225
2226 return ptr - data;
2227}
2228
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002229void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002230{
2231 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002232 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002233 u8 buf[128];
2234
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002235 rsp.scid = cpu_to_le16(chan->dcid);
2236 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002237 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2238 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2239 l2cap_send_cmd(conn, chan->ident,
2240 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2241
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002242 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002243 return;
2244
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002245 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2246 l2cap_build_conf_req(chan, buf), buf);
2247 chan->num_conf_req++;
2248}
2249
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002250static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002251{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002252 int type, olen;
2253 unsigned long val;
2254 struct l2cap_conf_rfc rfc;
2255
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002256 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002257
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002258 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002259 return;
2260
2261 while (len >= L2CAP_CONF_OPT_SIZE) {
2262 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2263
2264 switch (type) {
2265 case L2CAP_CONF_RFC:
2266 if (olen == sizeof(rfc))
2267 memcpy(&rfc, (void *)val, olen);
2268 goto done;
2269 }
2270 }
2271
2272done:
2273 switch (rfc.mode) {
2274 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002275 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2276 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2277 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002278 break;
2279 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002280 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002281 }
2282}
2283
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002284static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2285{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002286 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002287
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002288 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002289 return 0;
2290
2291 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2292 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002293 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002294
2295 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002296 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002297
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002298 l2cap_conn_start(conn);
2299 }
2300
2301 return 0;
2302}
2303
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2305{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2307 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002308 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002309 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002310 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311
2312 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002313 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314
2315 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2316
2317 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002318 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2319 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 result = L2CAP_CR_BAD_PSM;
2321 goto sendresp;
2322 }
2323
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002324 parent = pchan->sk;
2325
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002326 bh_lock_sock(parent);
2327
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002328 /* Check if the ACL is secure enough (if not SDP) */
2329 if (psm != cpu_to_le16(0x0001) &&
2330 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002331 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002332 result = L2CAP_CR_SEC_BLOCK;
2333 goto response;
2334 }
2335
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336 result = L2CAP_CR_NO_MEM;
2337
2338 /* Check for backlog size */
2339 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002340 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 goto response;
2342 }
2343
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002344 chan = pchan->ops->new_connection(pchan->data);
2345 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 goto response;
2347
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002348 sk = chan->sk;
2349
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002350 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351
2352 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002353 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2354 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002356 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 goto response;
2358 }
2359
2360 hci_conn_hold(conn->hcon);
2361
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362 bacpy(&bt_sk(sk)->src, conn->src);
2363 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002364 chan->psm = psm;
2365 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002367 bt_accept_enqueue(parent, sk);
2368
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002369 __l2cap_chan_add(conn, chan);
2370
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002371 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002373 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002375 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376
Marcel Holtmann984947d2009-02-06 23:35:19 +01002377 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002378 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002379 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002380 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002381 result = L2CAP_CR_PEND;
2382 status = L2CAP_CS_AUTHOR_PEND;
2383 parent->sk_data_ready(parent, 0);
2384 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002385 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002386 result = L2CAP_CR_SUCCESS;
2387 status = L2CAP_CS_NO_INFO;
2388 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002389 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002390 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002391 result = L2CAP_CR_PEND;
2392 status = L2CAP_CS_AUTHEN_PEND;
2393 }
2394 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002395 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002396 result = L2CAP_CR_PEND;
2397 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 }
2399
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002400 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401
2402response:
2403 bh_unlock_sock(parent);
2404
2405sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002406 rsp.scid = cpu_to_le16(scid);
2407 rsp.dcid = cpu_to_le16(dcid);
2408 rsp.result = cpu_to_le16(result);
2409 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002411
2412 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2413 struct l2cap_info_req info;
2414 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2415
2416 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2417 conn->info_ident = l2cap_get_ident(conn);
2418
2419 mod_timer(&conn->info_timer, jiffies +
2420 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2421
2422 l2cap_send_cmd(conn, conn->info_ident,
2423 L2CAP_INFO_REQ, sizeof(info), &info);
2424 }
2425
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002426 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002427 result == L2CAP_CR_SUCCESS) {
2428 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002429 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002430 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002431 l2cap_build_conf_req(chan, buf), buf);
2432 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002433 }
2434
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 return 0;
2436}
2437
2438static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2439{
2440 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2441 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002442 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 struct sock *sk;
2444 u8 req[128];
2445
2446 scid = __le16_to_cpu(rsp->scid);
2447 dcid = __le16_to_cpu(rsp->dcid);
2448 result = __le16_to_cpu(rsp->result);
2449 status = __le16_to_cpu(rsp->status);
2450
2451 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2452
2453 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002454 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002455 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002456 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002458 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002459 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002460 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461 }
2462
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002463 sk = chan->sk;
2464
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465 switch (result) {
2466 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002467 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002468 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002469 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002470 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002471
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002472 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002473 break;
2474
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002476 l2cap_build_conf_req(chan, req), req);
2477 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 break;
2479
2480 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002481 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482 break;
2483
2484 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002485 /* don't delete l2cap channel if sk is owned by user */
2486 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002487 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002488 __clear_chan_timer(chan);
2489 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002490 break;
2491 }
2492
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002493 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494 break;
2495 }
2496
2497 bh_unlock_sock(sk);
2498 return 0;
2499}
2500
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002501static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002502{
2503 /* FCS is enabled only in ERTM or streaming mode, if one or both
2504 * sides request it.
2505 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002506 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002507 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002508 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002509 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002510}
2511
Al Viro88219a02007-07-29 00:17:25 -07002512static 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 -07002513{
2514 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2515 u16 dcid, flags;
2516 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002517 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002519 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520
2521 dcid = __le16_to_cpu(req->dcid);
2522 flags = __le16_to_cpu(req->flags);
2523
2524 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2525
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002526 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002527 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528 return -ENOENT;
2529
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002530 sk = chan->sk;
2531
David S. Miller033b1142011-07-21 13:38:42 -07002532 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002533 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002534
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002535 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2536 rej.scid = cpu_to_le16(chan->scid);
2537 rej.dcid = cpu_to_le16(chan->dcid);
2538
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002539 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2540 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002541 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002542 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002543
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002544 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002545 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002546 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002547 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002548 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002549 L2CAP_CONF_REJECT, flags), rsp);
2550 goto unlock;
2551 }
2552
2553 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002554 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2555 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556
2557 if (flags & 0x0001) {
2558 /* Incomplete config. Send empty response. */
2559 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002560 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002561 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562 goto unlock;
2563 }
2564
2565 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002566 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002567 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002568 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002569 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002570 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002572 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002573 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002574
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002575 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002576 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002577
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002578 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002579 goto unlock;
2580
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002581 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002582 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002583
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002584 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002585
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002586 chan->next_tx_seq = 0;
2587 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002588 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002589 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002590 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002591
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002593 goto unlock;
2594 }
2595
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002596 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002597 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002599 l2cap_build_conf_req(chan, buf), buf);
2600 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 }
2602
2603unlock:
2604 bh_unlock_sock(sk);
2605 return 0;
2606}
2607
2608static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2609{
2610 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2611 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002612 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002614 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615
2616 scid = __le16_to_cpu(rsp->scid);
2617 flags = __le16_to_cpu(rsp->flags);
2618 result = __le16_to_cpu(rsp->result);
2619
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002620 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2621 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002623 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002624 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625 return 0;
2626
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002627 sk = chan->sk;
2628
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629 switch (result) {
2630 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002631 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 break;
2633
2634 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002635 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002636 char req[64];
2637
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002638 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002639 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002640 goto done;
2641 }
2642
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002643 /* throw out any old stored conf requests */
2644 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002645 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2646 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002647 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002648 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002649 goto done;
2650 }
2651
2652 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2653 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002654 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002655 if (result != L2CAP_CONF_SUCCESS)
2656 goto done;
2657 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658 }
2659
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002660 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002661 sk->sk_err = ECONNRESET;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002662 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002663 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664 goto done;
2665 }
2666
2667 if (flags & 0x01)
2668 goto done;
2669
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002670 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002672 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002673 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002674
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002675 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002676 chan->next_tx_seq = 0;
2677 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002678 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002679 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002680 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002681
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682 l2cap_chan_ready(sk);
2683 }
2684
2685done:
2686 bh_unlock_sock(sk);
2687 return 0;
2688}
2689
2690static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2691{
2692 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2693 struct l2cap_disconn_rsp rsp;
2694 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002695 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696 struct sock *sk;
2697
2698 scid = __le16_to_cpu(req->scid);
2699 dcid = __le16_to_cpu(req->dcid);
2700
2701 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2702
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002703 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002704 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705 return 0;
2706
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002707 sk = chan->sk;
2708
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002709 rsp.dcid = cpu_to_le16(chan->scid);
2710 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2712
2713 sk->sk_shutdown = SHUTDOWN_MASK;
2714
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002715 /* don't delete l2cap channel if sk is owned by user */
2716 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002717 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002718 __clear_chan_timer(chan);
2719 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002720 bh_unlock_sock(sk);
2721 return 0;
2722 }
2723
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002724 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725 bh_unlock_sock(sk);
2726
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002727 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 return 0;
2729}
2730
2731static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2732{
2733 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2734 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002735 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736 struct sock *sk;
2737
2738 scid = __le16_to_cpu(rsp->scid);
2739 dcid = __le16_to_cpu(rsp->dcid);
2740
2741 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2742
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002743 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002744 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 return 0;
2746
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002747 sk = chan->sk;
2748
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002749 /* don't delete l2cap channel if sk is owned by user */
2750 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002751 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002752 __clear_chan_timer(chan);
2753 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002754 bh_unlock_sock(sk);
2755 return 0;
2756 }
2757
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002758 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 bh_unlock_sock(sk);
2760
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002761 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 return 0;
2763}
2764
2765static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2766{
2767 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768 u16 type;
2769
2770 type = __le16_to_cpu(req->type);
2771
2772 BT_DBG("type 0x%4.4x", type);
2773
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002774 if (type == L2CAP_IT_FEAT_MASK) {
2775 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002776 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002777 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2778 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2779 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002780 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002781 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2782 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002783 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002784 l2cap_send_cmd(conn, cmd->ident,
2785 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002786 } else if (type == L2CAP_IT_FIXED_CHAN) {
2787 u8 buf[12];
2788 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2789 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2790 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2791 memcpy(buf + 4, l2cap_fixed_chan, 8);
2792 l2cap_send_cmd(conn, cmd->ident,
2793 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002794 } else {
2795 struct l2cap_info_rsp rsp;
2796 rsp.type = cpu_to_le16(type);
2797 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2798 l2cap_send_cmd(conn, cmd->ident,
2799 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2800 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801
2802 return 0;
2803}
2804
2805static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2806{
2807 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2808 u16 type, result;
2809
2810 type = __le16_to_cpu(rsp->type);
2811 result = __le16_to_cpu(rsp->result);
2812
2813 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2814
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002815 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2816 if (cmd->ident != conn->info_ident ||
2817 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2818 return 0;
2819
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002820 del_timer(&conn->info_timer);
2821
Ville Tervoadb08ed2010-08-04 09:43:33 +03002822 if (result != L2CAP_IR_SUCCESS) {
2823 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2824 conn->info_ident = 0;
2825
2826 l2cap_conn_start(conn);
2827
2828 return 0;
2829 }
2830
Marcel Holtmann984947d2009-02-06 23:35:19 +01002831 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002832 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002833
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002834 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002835 struct l2cap_info_req req;
2836 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2837
2838 conn->info_ident = l2cap_get_ident(conn);
2839
2840 l2cap_send_cmd(conn, conn->info_ident,
2841 L2CAP_INFO_REQ, sizeof(req), &req);
2842 } else {
2843 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2844 conn->info_ident = 0;
2845
2846 l2cap_conn_start(conn);
2847 }
2848 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002849 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002850 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002851
2852 l2cap_conn_start(conn);
2853 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002854
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855 return 0;
2856}
2857
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002858static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002859 u16 to_multiplier)
2860{
2861 u16 max_latency;
2862
2863 if (min > max || min < 6 || max > 3200)
2864 return -EINVAL;
2865
2866 if (to_multiplier < 10 || to_multiplier > 3200)
2867 return -EINVAL;
2868
2869 if (max >= to_multiplier * 8)
2870 return -EINVAL;
2871
2872 max_latency = (to_multiplier * 8 / max) - 1;
2873 if (latency > 499 || latency > max_latency)
2874 return -EINVAL;
2875
2876 return 0;
2877}
2878
2879static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2880 struct l2cap_cmd_hdr *cmd, u8 *data)
2881{
2882 struct hci_conn *hcon = conn->hcon;
2883 struct l2cap_conn_param_update_req *req;
2884 struct l2cap_conn_param_update_rsp rsp;
2885 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002886 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002887
2888 if (!(hcon->link_mode & HCI_LM_MASTER))
2889 return -EINVAL;
2890
2891 cmd_len = __le16_to_cpu(cmd->len);
2892 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2893 return -EPROTO;
2894
2895 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002896 min = __le16_to_cpu(req->min);
2897 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002898 latency = __le16_to_cpu(req->latency);
2899 to_multiplier = __le16_to_cpu(req->to_multiplier);
2900
2901 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2902 min, max, latency, to_multiplier);
2903
2904 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002905
2906 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2907 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002908 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2909 else
2910 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2911
2912 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2913 sizeof(rsp), &rsp);
2914
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002915 if (!err)
2916 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2917
Claudio Takahaside731152011-02-11 19:28:55 -02002918 return 0;
2919}
2920
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002921static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2922 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2923{
2924 int err = 0;
2925
2926 switch (cmd->code) {
2927 case L2CAP_COMMAND_REJ:
2928 l2cap_command_rej(conn, cmd, data);
2929 break;
2930
2931 case L2CAP_CONN_REQ:
2932 err = l2cap_connect_req(conn, cmd, data);
2933 break;
2934
2935 case L2CAP_CONN_RSP:
2936 err = l2cap_connect_rsp(conn, cmd, data);
2937 break;
2938
2939 case L2CAP_CONF_REQ:
2940 err = l2cap_config_req(conn, cmd, cmd_len, data);
2941 break;
2942
2943 case L2CAP_CONF_RSP:
2944 err = l2cap_config_rsp(conn, cmd, data);
2945 break;
2946
2947 case L2CAP_DISCONN_REQ:
2948 err = l2cap_disconnect_req(conn, cmd, data);
2949 break;
2950
2951 case L2CAP_DISCONN_RSP:
2952 err = l2cap_disconnect_rsp(conn, cmd, data);
2953 break;
2954
2955 case L2CAP_ECHO_REQ:
2956 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2957 break;
2958
2959 case L2CAP_ECHO_RSP:
2960 break;
2961
2962 case L2CAP_INFO_REQ:
2963 err = l2cap_information_req(conn, cmd, data);
2964 break;
2965
2966 case L2CAP_INFO_RSP:
2967 err = l2cap_information_rsp(conn, cmd, data);
2968 break;
2969
2970 default:
2971 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2972 err = -EINVAL;
2973 break;
2974 }
2975
2976 return err;
2977}
2978
2979static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2980 struct l2cap_cmd_hdr *cmd, u8 *data)
2981{
2982 switch (cmd->code) {
2983 case L2CAP_COMMAND_REJ:
2984 return 0;
2985
2986 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002987 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002988
2989 case L2CAP_CONN_PARAM_UPDATE_RSP:
2990 return 0;
2991
2992 default:
2993 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2994 return -EINVAL;
2995 }
2996}
2997
2998static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2999 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000{
3001 u8 *data = skb->data;
3002 int len = skb->len;
3003 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003004 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005
3006 l2cap_raw_recv(conn, skb);
3007
3008 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003009 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3011 data += L2CAP_CMD_HDR_SIZE;
3012 len -= L2CAP_CMD_HDR_SIZE;
3013
Al Viro88219a02007-07-29 00:17:25 -07003014 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015
Al Viro88219a02007-07-29 00:17:25 -07003016 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 -07003017
Al Viro88219a02007-07-29 00:17:25 -07003018 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019 BT_DBG("corrupted command");
3020 break;
3021 }
3022
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003023 if (conn->hcon->type == LE_LINK)
3024 err = l2cap_le_sig_cmd(conn, &cmd, data);
3025 else
3026 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027
3028 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003029 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003030
3031 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032
3033 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003034 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3036 }
3037
Al Viro88219a02007-07-29 00:17:25 -07003038 data += cmd_len;
3039 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003040 }
3041
3042 kfree_skb(skb);
3043}
3044
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003045static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003046{
3047 u16 our_fcs, rcv_fcs;
3048 int hdr_size = L2CAP_HDR_SIZE + 2;
3049
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003050 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003051 skb_trim(skb, skb->len - 2);
3052 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3053 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3054
3055 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003056 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003057 }
3058 return 0;
3059}
3060
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003061static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003062{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003063 u16 control = 0;
3064
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003065 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003066
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003067 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003068
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003069 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003070 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003071 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003072 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003073 }
3074
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003075 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003076 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003077
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003078 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003079
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003080 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003081 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003082 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003083 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003084 }
3085}
3086
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003087static 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 -03003088{
3089 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03003090 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003091
3092 bt_cb(skb)->tx_seq = tx_seq;
3093 bt_cb(skb)->sar = sar;
3094
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003095 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003096 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003097 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003098 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003099 }
3100
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003101 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03003102 if (tx_seq_offset < 0)
3103 tx_seq_offset += 64;
3104
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003105 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003106 if (bt_cb(next_skb)->tx_seq == tx_seq)
3107 return -EINVAL;
3108
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03003109 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003110 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03003111 if (next_tx_seq_offset < 0)
3112 next_tx_seq_offset += 64;
3113
3114 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003115 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003116 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003117 }
3118
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003119 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003120 break;
3121
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003122 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003123
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003124 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003125
3126 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003127}
3128
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003129static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003130{
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003131 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003132 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003133
3134 switch (control & L2CAP_CTRL_SAR) {
3135 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003136 if (test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003137 goto drop;
3138
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003139 return chan->ops->recv(chan->data, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003140
3141 case L2CAP_SDU_START:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003142 if (test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003143 goto drop;
3144
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003145 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003146
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003147 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003148 goto disconnect;
3149
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003150 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3151 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003152 return -ENOMEM;
3153
3154 /* pull sdu_len bytes only after alloc, because of Local Busy
3155 * condition we have to be sure that this will be executed
3156 * only once, i.e., when alloc does not fail */
3157 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003158
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003159 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003160
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003161 set_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003162 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003163 break;
3164
3165 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003166 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003167 goto disconnect;
3168
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003169 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003170 goto disconnect;
3171
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003172 chan->partial_sdu_len += skb->len;
3173 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003174 goto drop;
3175
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003176 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003177
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003178 break;
3179
3180 case L2CAP_SDU_END:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003181 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003182 goto disconnect;
3183
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003184 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003185 goto disconnect;
3186
Mat Martineaufadd1922011-07-07 09:39:03 -07003187 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003188
Mat Martineaufadd1922011-07-07 09:39:03 -07003189 if (chan->partial_sdu_len > chan->imtu)
3190 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003191
Mat Martineaufadd1922011-07-07 09:39:03 -07003192 if (chan->partial_sdu_len != chan->sdu_len)
3193 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003194
Mat Martineaufadd1922011-07-07 09:39:03 -07003195 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003196
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003197 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003198 if (!_skb) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003199 return -ENOMEM;
3200 }
3201
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003202 err = chan->ops->recv(chan->data, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003203 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003204 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003205 return err;
3206 }
3207
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003208 clear_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003209
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003210 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003211 break;
3212 }
3213
3214 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003215 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003216
3217drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003218 kfree_skb(chan->sdu);
3219 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003220
3221disconnect:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003222 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003223 kfree_skb(skb);
3224 return 0;
3225}
3226
Mat Martineau26f880d2011-07-07 09:39:01 -07003227static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003228{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003229 u16 control;
3230
Mat Martineau26f880d2011-07-07 09:39:01 -07003231 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003232
Mat Martineau26f880d2011-07-07 09:39:01 -07003233 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3234
3235 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3236 control |= L2CAP_SUPER_RCV_NOT_READY;
3237 l2cap_send_sframe(chan, control);
3238
3239 set_bit(CONN_RNR_SENT, &chan->conn_state);
3240
3241 __clear_ack_timer(chan);
3242}
3243
3244static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3245{
3246 u16 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003247
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003248 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003249 goto done;
3250
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003251 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003252 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003253 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003254 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003255
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003256 __clear_retrans_timer(chan);
3257 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003258
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003259 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003260
3261done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003262 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3263 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003264
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003265 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003266}
3267
Mat Martineaue3281402011-07-07 09:39:02 -07003268void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003269{
Mat Martineaue3281402011-07-07 09:39:02 -07003270 if (chan->mode == L2CAP_MODE_ERTM) {
3271 if (busy)
3272 l2cap_ertm_enter_local_busy(chan);
3273 else
3274 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003275 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003276}
3277
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003278static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003279{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003280 struct sk_buff *_skb;
3281 int err = -EINVAL;
3282
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003283 /*
3284 * TODO: We have to notify the userland if some data is lost with the
3285 * Streaming Mode.
3286 */
3287
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003288 switch (control & L2CAP_CTRL_SAR) {
3289 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003290 if (test_bit(CONN_SAR_SDU, &chan->conn_state)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003291 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003292 break;
3293 }
3294
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003295 err = chan->ops->recv(chan->data, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003296 if (!err)
3297 return 0;
3298
3299 break;
3300
3301 case L2CAP_SDU_START:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003302 if (test_bit(CONN_SAR_SDU, &chan->conn_state)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003303 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003304 break;
3305 }
3306
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003307 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003308 skb_pull(skb, 2);
3309
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003310 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003311 err = -EMSGSIZE;
3312 break;
3313 }
3314
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003315 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3316 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003317 err = -ENOMEM;
3318 break;
3319 }
3320
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003321 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003322
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003323 set_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003324 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003325 err = 0;
3326 break;
3327
3328 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003329 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003330 break;
3331
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003332 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003333
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003334 chan->partial_sdu_len += skb->len;
3335 if (chan->partial_sdu_len > chan->sdu_len)
3336 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003337 else
3338 err = 0;
3339
3340 break;
3341
3342 case L2CAP_SDU_END:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003343 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003344 break;
3345
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003346 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003347
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003348 clear_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003349 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003350
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003351 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003352 goto drop;
3353
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003354 if (chan->partial_sdu_len == chan->sdu_len) {
3355 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003356 err = chan->ops->recv(chan->data, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003357 if (err < 0)
3358 kfree_skb(_skb);
3359 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003360 err = 0;
3361
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003362drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003363 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003364 break;
3365 }
3366
3367 kfree_skb(skb);
3368 return err;
3369}
3370
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003371static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003372{
3373 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003374 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003375
Mat Martineaue3281402011-07-07 09:39:02 -07003376 while ((skb = skb_peek(&chan->srej_q)) &&
3377 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3378 int err;
3379
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003380 if (bt_cb(skb)->tx_seq != tx_seq)
3381 break;
3382
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003383 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003384 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Mat Martineaue3281402011-07-07 09:39:02 -07003385 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
3386
3387 if (err < 0) {
3388 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3389 break;
3390 }
3391
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003392 chan->buffer_seq_srej =
3393 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003394 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003395 }
3396}
3397
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003398static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003399{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003400 struct srej_list *l, *tmp;
3401 u16 control;
3402
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003403 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003404 if (l->tx_seq == tx_seq) {
3405 list_del(&l->list);
3406 kfree(l);
3407 return;
3408 }
3409 control = L2CAP_SUPER_SELECT_REJECT;
3410 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003411 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003412 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003413 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003414 }
3415}
3416
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003417static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003418{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003419 struct srej_list *new;
3420 u16 control;
3421
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003422 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003423 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003424 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003425 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003426
3427 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003428 new->tx_seq = chan->expected_tx_seq;
3429 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003430 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003431 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003432 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003433}
3434
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003435static 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 -03003436{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003437 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003438 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003439 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003440 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003441 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003442 int err = 0;
3443
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003444 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3445 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003446
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003447 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003448 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003449 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003450 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003451 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003452 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003453 }
3454
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003455 chan->expected_ack_seq = req_seq;
3456 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003457
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003458 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003459 if (tx_seq_offset < 0)
3460 tx_seq_offset += 64;
3461
3462 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003463 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003464 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003465 goto drop;
3466 }
3467
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003468 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003469 goto drop;
3470
Mat Martineau02f1b642011-06-29 14:35:19 -07003471 if (tx_seq == chan->expected_tx_seq)
3472 goto expected;
3473
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003474 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003475 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003476
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003477 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003478 struct srej_list, list);
3479 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003480 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003481 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003482
3483 list_del(&first->list);
3484 kfree(first);
3485
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003486 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003487 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003488 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003489 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003490 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003491 }
3492 } else {
3493 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003494
3495 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003496 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003497 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003498
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003499 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003500 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003501 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003502 return 0;
3503 }
3504 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003505 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003506 }
3507 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003508 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003509 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003510 if (expected_tx_seq_offset < 0)
3511 expected_tx_seq_offset += 64;
3512
3513 /* duplicated tx_seq */
3514 if (tx_seq_offset < expected_tx_seq_offset)
3515 goto drop;
3516
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003517 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003518
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003519 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003520
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003521 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003522 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003523
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003524 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003525 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003526
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003527 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003528
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003529 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003530
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003531 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003532 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003533 return 0;
3534
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003535expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003536 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003537
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003538 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003539 bt_cb(skb)->tx_seq = tx_seq;
3540 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003541 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003542 return 0;
3543 }
3544
Mat Martineaufadd1922011-07-07 09:39:03 -07003545 err = l2cap_ertm_reassembly_sdu(chan, skb, rx_control);
3546 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Mat Martineaue3281402011-07-07 09:39:02 -07003547 if (err < 0) {
3548 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3549 return err;
3550 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003551
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003552 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003553 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003554 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003555 }
3556
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003557 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003558
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003559 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3560 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003561 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003562
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003563 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003564
3565drop:
3566 kfree_skb(skb);
3567 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003568}
3569
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003570static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003571{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003572 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003573 rx_control);
3574
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003575 chan->expected_ack_seq = __get_reqseq(rx_control);
3576 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003577
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003578 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003579 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3580 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3581 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003582 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003583 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003584
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003585 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003586 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003587 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003588 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003589 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003590
3591 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003592 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003593
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003594 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003595 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003596
3597 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003598 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003599 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003600 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003601
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003602 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3603 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003604 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003605 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003606 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003607 }
3608}
3609
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003610static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003611{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003612 u8 tx_seq = __get_reqseq(rx_control);
3613
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003614 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003615
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003616 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003617
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003618 chan->expected_ack_seq = tx_seq;
3619 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003620
3621 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003622 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003623 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003624 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003625 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003626
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003627 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3628 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003629 }
3630}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003631static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003632{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003633 u8 tx_seq = __get_reqseq(rx_control);
3634
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003635 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003636
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003637 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003638
3639 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003640 chan->expected_ack_seq = tx_seq;
3641 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003642
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003643 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003644 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003645
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003646 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003647
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003648 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003649 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003650 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003651 }
3652 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003653 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003654 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003655 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003656 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003657 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003658 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003659 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003660 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003661 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003662 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003663 }
3664 }
3665}
3666
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003667static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003668{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003669 u8 tx_seq = __get_reqseq(rx_control);
3670
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003671 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003672
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003673 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003674 chan->expected_ack_seq = tx_seq;
3675 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003676
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003677 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003678 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003679
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003680 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003681 __clear_retrans_timer(chan);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003682 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003683 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003684 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003685 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003686
3687 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003688 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003689 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003690 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003691}
3692
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003693static 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 -03003694{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003695 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003696
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003697 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003698 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003699 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003700 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003701 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003702 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003703 }
3704
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003705 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3706 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003707 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003708 break;
3709
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003710 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003711 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003712 break;
3713
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003714 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003715 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003716 break;
3717
3718 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003719 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003720 break;
3721 }
3722
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003723 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003724 return 0;
3725}
3726
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003727static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3728{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003729 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003730 u16 control;
3731 u8 req_seq;
3732 int len, next_tx_seq_offset, req_seq_offset;
3733
3734 control = get_unaligned_le16(skb->data);
3735 skb_pull(skb, 2);
3736 len = skb->len;
3737
3738 /*
3739 * We can just drop the corrupted I-frame here.
3740 * Receiver will miss it and start proper recovery
3741 * procedures and ask retransmission.
3742 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003743 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003744 goto drop;
3745
3746 if (__is_sar_start(control) && __is_iframe(control))
3747 len -= 2;
3748
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003749 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003750 len -= 2;
3751
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003752 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003753 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003754 goto drop;
3755 }
3756
3757 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003758 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003759 if (req_seq_offset < 0)
3760 req_seq_offset += 64;
3761
3762 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003763 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003764 if (next_tx_seq_offset < 0)
3765 next_tx_seq_offset += 64;
3766
3767 /* check for invalid req-seq */
3768 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003769 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003770 goto drop;
3771 }
3772
3773 if (__is_iframe(control)) {
3774 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003775 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003776 goto drop;
3777 }
3778
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003779 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003780 } else {
3781 if (len != 0) {
3782 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003783 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003784 goto drop;
3785 }
3786
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003787 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003788 }
3789
3790 return 0;
3791
3792drop:
3793 kfree_skb(skb);
3794 return 0;
3795}
3796
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3798{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003799 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003800 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003801 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003802 u8 tx_seq;
3803 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003805 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003806 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807 BT_DBG("unknown cid 0x%4.4x", cid);
3808 goto drop;
3809 }
3810
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003811 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003812
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003813 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003815 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816 goto drop;
3817
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003818 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003819 case L2CAP_MODE_BASIC:
3820 /* If socket recv buffers overflows we drop data here
3821 * which is *bad* because L2CAP has to be reliable.
3822 * But we don't have any other choice. L2CAP doesn't
3823 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003825 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003826 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003828 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003829 goto done;
3830 break;
3831
3832 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003833 if (!sock_owned_by_user(sk)) {
3834 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003835 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003836 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003837 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003838 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003839
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003840 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003841
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003842 case L2CAP_MODE_STREAMING:
3843 control = get_unaligned_le16(skb->data);
3844 skb_pull(skb, 2);
3845 len = skb->len;
3846
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003847 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003848 goto drop;
3849
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003850 if (__is_sar_start(control))
3851 len -= 2;
3852
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003853 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003854 len -= 2;
3855
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003856 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003857 goto drop;
3858
3859 tx_seq = __get_txseq(control);
3860
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003861 if (chan->expected_tx_seq == tx_seq)
3862 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003863 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003864 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003865
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003866 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003867
3868 goto done;
3869
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003870 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003871 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003872 break;
3873 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874
3875drop:
3876 kfree_skb(skb);
3877
3878done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003879 if (sk)
3880 bh_unlock_sock(sk);
3881
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882 return 0;
3883}
3884
Al Viro8e036fc2007-07-29 00:16:36 -07003885static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003886{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003887 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003888 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003890 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3891 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892 goto drop;
3893
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003894 sk = chan->sk;
3895
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003896 bh_lock_sock(sk);
3897
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 BT_DBG("sk %p, len %d", sk, skb->len);
3899
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003900 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901 goto drop;
3902
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003903 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904 goto drop;
3905
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003906 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907 goto done;
3908
3909drop:
3910 kfree_skb(skb);
3911
3912done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003913 if (sk)
3914 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915 return 0;
3916}
3917
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003918static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3919{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003920 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003921 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003922
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003923 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3924 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003925 goto drop;
3926
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003927 sk = chan->sk;
3928
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003929 bh_lock_sock(sk);
3930
3931 BT_DBG("sk %p, len %d", sk, skb->len);
3932
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003933 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003934 goto drop;
3935
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003936 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003937 goto drop;
3938
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003939 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003940 goto done;
3941
3942drop:
3943 kfree_skb(skb);
3944
3945done:
3946 if (sk)
3947 bh_unlock_sock(sk);
3948 return 0;
3949}
3950
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3952{
3953 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003954 u16 cid, len;
3955 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956
3957 skb_pull(skb, L2CAP_HDR_SIZE);
3958 cid = __le16_to_cpu(lh->cid);
3959 len = __le16_to_cpu(lh->len);
3960
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003961 if (len != skb->len) {
3962 kfree_skb(skb);
3963 return;
3964 }
3965
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3967
3968 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003969 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003970 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003971 l2cap_sig_channel(conn, skb);
3972 break;
3973
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003974 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003975 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003976 skb_pull(skb, 2);
3977 l2cap_conless_channel(conn, psm, skb);
3978 break;
3979
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003980 case L2CAP_CID_LE_DATA:
3981 l2cap_att_channel(conn, cid, skb);
3982 break;
3983
Anderson Brigliab501d6a2011-06-07 18:46:31 -03003984 case L2CAP_CID_SMP:
3985 if (smp_sig_channel(conn, skb))
3986 l2cap_conn_del(conn->hcon, EACCES);
3987 break;
3988
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989 default:
3990 l2cap_data_channel(conn, cid, skb);
3991 break;
3992 }
3993}
3994
3995/* ---- L2CAP interface with lower layer (HCI) ---- */
3996
3997static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3998{
3999 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004000 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004001
4002 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004003 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004004
4005 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4006
4007 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004008 read_lock(&chan_list_lock);
4009 list_for_each_entry(c, &chan_list, global_l) {
4010 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004011
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004012 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013 continue;
4014
4015 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004016 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004017 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004018 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004020 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4021 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004022 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004023 lm2 |= HCI_LM_MASTER;
4024 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004026 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027
4028 return exact ? lm1 : lm2;
4029}
4030
4031static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4032{
Marcel Holtmann01394182006-07-03 10:02:46 +02004033 struct l2cap_conn *conn;
4034
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4036
Ville Tervoacd7d372011-02-10 22:38:49 -03004037 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004038 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039
4040 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041 conn = l2cap_conn_add(hcon, status);
4042 if (conn)
4043 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004044 } else
Joe Perchese1750722011-06-29 18:18:29 -07004045 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046
4047 return 0;
4048}
4049
Marcel Holtmann2950f212009-02-12 14:02:50 +01004050static int l2cap_disconn_ind(struct hci_conn *hcon)
4051{
4052 struct l2cap_conn *conn = hcon->l2cap_data;
4053
4054 BT_DBG("hcon %p", hcon);
4055
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03004056 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004057 return 0x13;
4058
4059 return conn->disc_reason;
4060}
4061
4062static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063{
4064 BT_DBG("hcon %p reason %d", hcon, reason);
4065
Ville Tervoacd7d372011-02-10 22:38:49 -03004066 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004067 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068
Joe Perchese1750722011-06-29 18:18:29 -07004069 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004070
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071 return 0;
4072}
4073
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004074static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004075{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004076 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004077 return;
4078
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004079 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004080 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004081 __clear_chan_timer(chan);
4082 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004083 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004084 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004085 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004086 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004087 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004088 }
4089}
4090
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004091static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004093 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004094 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095
Marcel Holtmann01394182006-07-03 10:02:46 +02004096 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004098
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099 BT_DBG("conn %p", conn);
4100
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004101 if (hcon->type == LE_LINK) {
4102 smp_distribute_keys(conn, 0);
4103 del_timer(&conn->security_timer);
4104 }
4105
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004106 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004108 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004109 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004110
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111 bh_lock_sock(sk);
4112
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004113 BT_DBG("chan->scid %d", chan->scid);
4114
4115 if (chan->scid == L2CAP_CID_LE_DATA) {
4116 if (!status && encrypt) {
4117 chan->sec_level = hcon->sec_level;
4118 l2cap_chan_ready(sk);
4119 }
4120
4121 bh_unlock_sock(sk);
4122 continue;
4123 }
4124
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004125 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004126 bh_unlock_sock(sk);
4127 continue;
4128 }
4129
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004130 if (!status && (chan->state == BT_CONNECTED ||
4131 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004132 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004133 bh_unlock_sock(sk);
4134 continue;
4135 }
4136
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004137 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004138 if (!status) {
4139 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004140 req.scid = cpu_to_le16(chan->scid);
4141 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004142
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004143 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004144 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004145
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004146 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004147 L2CAP_CONN_REQ, sizeof(req), &req);
4148 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004149 __clear_chan_timer(chan);
4150 __set_chan_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004151 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004152 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004153 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004154 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004155
4156 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004157 if (bt_sk(sk)->defer_setup) {
4158 struct sock *parent = bt_sk(sk)->parent;
4159 res = L2CAP_CR_PEND;
4160 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004161 if (parent)
4162 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004163 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004164 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004165 res = L2CAP_CR_SUCCESS;
4166 stat = L2CAP_CS_NO_INFO;
4167 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004168 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004169 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004170 __set_chan_timer(chan, HZ / 10);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004171 res = L2CAP_CR_SEC_BLOCK;
4172 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004173 }
4174
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004175 rsp.scid = cpu_to_le16(chan->dcid);
4176 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004177 rsp.result = cpu_to_le16(res);
4178 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004179 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4180 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004181 }
4182
Linus Torvalds1da177e2005-04-16 15:20:36 -07004183 bh_unlock_sock(sk);
4184 }
4185
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004186 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004187
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188 return 0;
4189}
4190
4191static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4192{
4193 struct l2cap_conn *conn = hcon->l2cap_data;
4194
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004195 if (!conn)
4196 conn = l2cap_conn_add(hcon, 0);
4197
4198 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199 goto drop;
4200
4201 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4202
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004203 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004205 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004206 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207 int len;
4208
4209 if (conn->rx_len) {
4210 BT_ERR("Unexpected start frame (len %d)", skb->len);
4211 kfree_skb(conn->rx_skb);
4212 conn->rx_skb = NULL;
4213 conn->rx_len = 0;
4214 l2cap_conn_unreliable(conn, ECOMM);
4215 }
4216
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004217 /* Start fragment always begin with Basic L2CAP header */
4218 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004219 BT_ERR("Frame is too short (len %d)", skb->len);
4220 l2cap_conn_unreliable(conn, ECOMM);
4221 goto drop;
4222 }
4223
4224 hdr = (struct l2cap_hdr *) skb->data;
4225 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004226 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227
4228 if (len == skb->len) {
4229 /* Complete frame received */
4230 l2cap_recv_frame(conn, skb);
4231 return 0;
4232 }
4233
4234 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4235
4236 if (skb->len > len) {
4237 BT_ERR("Frame is too long (len %d, expected len %d)",
4238 skb->len, len);
4239 l2cap_conn_unreliable(conn, ECOMM);
4240 goto drop;
4241 }
4242
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004243 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004244
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004245 if (chan && chan->sk) {
4246 struct sock *sk = chan->sk;
4247
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004248 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004249 BT_ERR("Frame exceeding recv MTU (len %d, "
4250 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004251 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004252 bh_unlock_sock(sk);
4253 l2cap_conn_unreliable(conn, ECOMM);
4254 goto drop;
4255 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004256 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004257 }
4258
Linus Torvalds1da177e2005-04-16 15:20:36 -07004259 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004260 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4261 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262 goto drop;
4263
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004264 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004265 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266 conn->rx_len = len - skb->len;
4267 } else {
4268 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4269
4270 if (!conn->rx_len) {
4271 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4272 l2cap_conn_unreliable(conn, ECOMM);
4273 goto drop;
4274 }
4275
4276 if (skb->len > conn->rx_len) {
4277 BT_ERR("Fragment is too long (len %d, expected %d)",
4278 skb->len, conn->rx_len);
4279 kfree_skb(conn->rx_skb);
4280 conn->rx_skb = NULL;
4281 conn->rx_len = 0;
4282 l2cap_conn_unreliable(conn, ECOMM);
4283 goto drop;
4284 }
4285
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004286 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004287 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288 conn->rx_len -= skb->len;
4289
4290 if (!conn->rx_len) {
4291 /* Complete frame received */
4292 l2cap_recv_frame(conn, conn->rx_skb);
4293 conn->rx_skb = NULL;
4294 }
4295 }
4296
4297drop:
4298 kfree_skb(skb);
4299 return 0;
4300}
4301
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004302static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004304 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004306 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004308 list_for_each_entry(c, &chan_list, global_l) {
4309 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004311 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 +01004312 batostr(&bt_sk(sk)->src),
4313 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004314 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004315 c->scid, c->dcid, c->imtu, c->omtu,
4316 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004317}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004319 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004320
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004321 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322}
4323
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004324static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4325{
4326 return single_open(file, l2cap_debugfs_show, inode->i_private);
4327}
4328
4329static const struct file_operations l2cap_debugfs_fops = {
4330 .open = l2cap_debugfs_open,
4331 .read = seq_read,
4332 .llseek = seq_lseek,
4333 .release = single_release,
4334};
4335
4336static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338static struct hci_proto l2cap_hci_proto = {
4339 .name = "L2CAP",
4340 .id = HCI_PROTO_L2CAP,
4341 .connect_ind = l2cap_connect_ind,
4342 .connect_cfm = l2cap_connect_cfm,
4343 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004344 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004345 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346 .recv_acldata = l2cap_recv_acldata
4347};
4348
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004349int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350{
4351 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004352
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004353 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354 if (err < 0)
4355 return err;
4356
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357 err = hci_register_proto(&l2cap_hci_proto);
4358 if (err < 0) {
4359 BT_ERR("L2CAP protocol registration failed");
4360 bt_sock_unregister(BTPROTO_L2CAP);
4361 goto error;
4362 }
4363
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004364 if (bt_debugfs) {
4365 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4366 bt_debugfs, NULL, &l2cap_debugfs_fops);
4367 if (!l2cap_debugfs)
4368 BT_ERR("Failed to create L2CAP debug file");
4369 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004370
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371 return 0;
4372
4373error:
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004374 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375 return err;
4376}
4377
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004378void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004379{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004380 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004381
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4383 BT_ERR("L2CAP protocol unregistration failed");
4384
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004385 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004386}
4387
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004388module_param(disable_ertm, bool, 0644);
4389MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");