blob: f7ada4a2cc5d9878d2d13b5c5bda89f49a87bb08 [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
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030064static struct workqueue_struct *_busy_wq;
65
Johannes Bergb5ad8b72011-06-01 08:54:45 +020066static LIST_HEAD(chan_list);
67static DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070068
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030069static void l2cap_busy_work(struct work_struct *work);
70
Linus Torvalds1da177e2005-04-16 15:20:36 -070071static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
72 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030073static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
74 void *data);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030075static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030076static void l2cap_send_disconn_req(struct l2cap_conn *conn,
77 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030079static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
80
Marcel Holtmann01394182006-07-03 10:02:46 +020081/* ---- L2CAP channels ---- */
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -030082
83static inline void chan_hold(struct l2cap_chan *c)
84{
85 atomic_inc(&c->refcnt);
86}
87
88static inline void chan_put(struct l2cap_chan *c)
89{
90 if (atomic_dec_and_test(&c->refcnt))
91 kfree(c);
92}
93
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030094static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020095{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030096 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030097
98 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030099 if (c->dcid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300100 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200101 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300102 return NULL;
103
Marcel Holtmann01394182006-07-03 10:02:46 +0200104}
105
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300106static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200107{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300108 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300109
110 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300111 if (c->scid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300112 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200113 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300114 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200115}
116
117/* Find channel with given SCID.
118 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300119static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200120{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300121 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300122
123 read_lock(&conn->chan_lock);
124 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300125 if (c)
126 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300127 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300128 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200129}
130
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300131static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200132{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300133 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300134
135 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300136 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300137 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200138 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300139 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200140}
141
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300142static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200143{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300144 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300145
146 read_lock(&conn->chan_lock);
147 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300148 if (c)
149 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300150 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300151 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200152}
153
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300154static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300155{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300156 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300157
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300158 list_for_each_entry(c, &chan_list, global_l) {
159 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300160 goto found;
161 }
162
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300163 c = NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300164found:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300165 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300166}
167
168int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
169{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300170 int err;
171
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300172 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300173
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300174 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300175 err = -EADDRINUSE;
176 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300177 }
178
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300179 if (psm) {
180 chan->psm = psm;
181 chan->sport = psm;
182 err = 0;
183 } else {
184 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300185
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300186 err = -EINVAL;
187 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300188 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300189 chan->psm = cpu_to_le16(p);
190 chan->sport = cpu_to_le16(p);
191 err = 0;
192 break;
193 }
194 }
195
196done:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300197 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300198 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300199}
200
201int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
202{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300203 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300204
205 chan->scid = scid;
206
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300207 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300208
209 return 0;
210}
211
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300212static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200213{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300214 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200215
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300216 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300217 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200218 return cid;
219 }
220
221 return 0;
222}
223
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300224static void l2cap_set_timer(struct l2cap_chan *chan, struct timer_list *timer, long timeout)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300225{
Mat Martineau774e5652011-06-29 14:35:20 -0700226 BT_DBG("chan %p state %d timeout %ld", chan->sk, chan->state, timeout);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300227
Mat Martineau942ecc92011-06-29 14:35:21 -0700228 if (!mod_timer(timer, jiffies + msecs_to_jiffies(timeout)))
Mat Martineau774e5652011-06-29 14:35:20 -0700229 chan_hold(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300230}
231
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300232static void l2cap_clear_timer(struct l2cap_chan *chan, struct timer_list *timer)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300233{
Mat Martineau774e5652011-06-29 14:35:20 -0700234 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300235
Mat Martineau774e5652011-06-29 14:35:20 -0700236 if (timer_pending(timer) && del_timer(timer))
237 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300238}
239
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300240static void l2cap_state_change(struct l2cap_chan *chan, int state)
241{
242 chan->state = state;
243 chan->ops->state_change(chan->data, state);
244}
245
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300246static void l2cap_chan_timeout(unsigned long arg)
247{
248 struct l2cap_chan *chan = (struct l2cap_chan *) arg;
249 struct sock *sk = chan->sk;
250 int reason;
251
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300252 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300253
254 bh_lock_sock(sk);
255
256 if (sock_owned_by_user(sk)) {
257 /* sk is owned by user. Try again later */
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300258 __set_chan_timer(chan, HZ / 5);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300259 bh_unlock_sock(sk);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300260 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300261 return;
262 }
263
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300264 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300265 reason = ECONNREFUSED;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300266 else if (chan->state == BT_CONNECT &&
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300267 chan->sec_level != BT_SECURITY_SDP)
268 reason = ECONNREFUSED;
269 else
270 reason = ETIMEDOUT;
271
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300272 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300273
274 bh_unlock_sock(sk);
275
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300276 chan->ops->close(chan->data);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300277 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300278}
279
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300280struct l2cap_chan *l2cap_chan_create(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200281{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300282 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200283
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300284 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
285 if (!chan)
286 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200287
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300288 chan->sk = sk;
289
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300290 write_lock_bh(&chan_list_lock);
291 list_add(&chan->global_l, &chan_list);
292 write_unlock_bh(&chan_list_lock);
293
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300294 setup_timer(&chan->chan_timer, l2cap_chan_timeout, (unsigned long) chan);
295
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300296 chan->state = BT_OPEN;
297
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300298 atomic_set(&chan->refcnt, 1);
299
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300300 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200301}
302
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300303void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300304{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300305 write_lock_bh(&chan_list_lock);
306 list_del(&chan->global_l);
307 write_unlock_bh(&chan_list_lock);
308
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300309 chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300310}
311
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300312static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200313{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300314 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300315 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200316
Marcel Holtmann2950f212009-02-12 14:02:50 +0100317 conn->disc_reason = 0x13;
318
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300319 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200320
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300321 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
Ville Tervob62f3282011-02-10 22:38:50 -0300322 if (conn->hcon->type == LE_LINK) {
323 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300324 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300325 chan->scid = L2CAP_CID_LE_DATA;
326 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300327 } else {
328 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300329 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300330 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300331 }
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300332 } else if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200333 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300334 chan->scid = L2CAP_CID_CONN_LESS;
335 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300336 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200337 } else {
338 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300339 chan->scid = L2CAP_CID_SIGNALING;
340 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300341 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200342 }
343
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300344 chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300345
346 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200347}
348
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900349/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200350 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300351static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200352{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300353 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300354 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200355 struct sock *parent = bt_sk(sk)->parent;
356
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300357 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200358
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300359 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200360
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900361 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300362 /* Delete from channel list */
363 write_lock_bh(&conn->chan_lock);
364 list_del(&chan->list);
365 write_unlock_bh(&conn->chan_lock);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300366 chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300367
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300368 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200369 hci_conn_put(conn->hcon);
370 }
371
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300372 l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200373 sock_set_flag(sk, SOCK_ZAPPED);
374
375 if (err)
376 sk->sk_err = err;
377
378 if (parent) {
379 bt_accept_unlink(sk);
380 parent->sk_data_ready(parent, 0);
381 } else
382 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300383
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300384 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
385 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300386 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300387
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300388 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300389
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300390 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300391 struct srej_list *l, *tmp;
392
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300393 __clear_retrans_timer(chan);
394 __clear_monitor_timer(chan);
395 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300396
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300397 skb_queue_purge(&chan->srej_q);
398 skb_queue_purge(&chan->busy_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300399
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300400 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300401 list_del(&l->list);
402 kfree(l);
403 }
404 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200405}
406
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300407static void l2cap_chan_cleanup_listen(struct sock *parent)
408{
409 struct sock *sk;
410
411 BT_DBG("parent %p", parent);
412
413 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300414 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300415 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300416 __clear_chan_timer(chan);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300417 lock_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300418 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300419 release_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300420 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300421 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300422}
423
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300424void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300425{
426 struct l2cap_conn *conn = chan->conn;
427 struct sock *sk = chan->sk;
428
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300429 BT_DBG("chan %p state %d socket %p", chan, chan->state, sk->sk_socket);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300430
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300431 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300432 case BT_LISTEN:
433 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300434
435 l2cap_state_change(chan, BT_CLOSED);
436 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300437 break;
438
439 case BT_CONNECTED:
440 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300441 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300442 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300443 __clear_chan_timer(chan);
444 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300445 l2cap_send_disconn_req(conn, chan, reason);
446 } else
447 l2cap_chan_del(chan, reason);
448 break;
449
450 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300451 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300452 conn->hcon->type == ACL_LINK) {
453 struct l2cap_conn_rsp rsp;
454 __u16 result;
455
456 if (bt_sk(sk)->defer_setup)
457 result = L2CAP_CR_SEC_BLOCK;
458 else
459 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300460 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300461
462 rsp.scid = cpu_to_le16(chan->dcid);
463 rsp.dcid = cpu_to_le16(chan->scid);
464 rsp.result = cpu_to_le16(result);
465 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
466 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
467 sizeof(rsp), &rsp);
468 }
469
470 l2cap_chan_del(chan, reason);
471 break;
472
473 case BT_CONNECT:
474 case BT_DISCONN:
475 l2cap_chan_del(chan, reason);
476 break;
477
478 default:
479 sock_set_flag(sk, SOCK_ZAPPED);
480 break;
481 }
482}
483
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300484static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530485{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300486 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300487 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530488 case BT_SECURITY_HIGH:
489 return HCI_AT_DEDICATED_BONDING_MITM;
490 case BT_SECURITY_MEDIUM:
491 return HCI_AT_DEDICATED_BONDING;
492 default:
493 return HCI_AT_NO_BONDING;
494 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300495 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300496 if (chan->sec_level == BT_SECURITY_LOW)
497 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530498
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300499 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530500 return HCI_AT_NO_BONDING_MITM;
501 else
502 return HCI_AT_NO_BONDING;
503 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300504 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530505 case BT_SECURITY_HIGH:
506 return HCI_AT_GENERAL_BONDING_MITM;
507 case BT_SECURITY_MEDIUM:
508 return HCI_AT_GENERAL_BONDING;
509 default:
510 return HCI_AT_NO_BONDING;
511 }
512 }
513}
514
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200515/* Service level security */
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300516static inline int l2cap_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200517{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300518 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100519 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200520
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300521 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100522
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300523 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200524}
525
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200526static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200527{
528 u8 id;
529
530 /* Get next available identificator.
531 * 1 - 128 are used by kernel.
532 * 129 - 199 are reserved.
533 * 200 - 254 are used by utilities like l2ping, etc.
534 */
535
536 spin_lock_bh(&conn->lock);
537
538 if (++conn->tx_ident > 128)
539 conn->tx_ident = 1;
540
541 id = conn->tx_ident;
542
543 spin_unlock_bh(&conn->lock);
544
545 return id;
546}
547
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300548static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200549{
550 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200551 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200552
553 BT_DBG("code 0x%2.2x", code);
554
555 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300556 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200557
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200558 if (lmp_no_flush_capable(conn->hcon->hdev))
559 flags = ACL_START_NO_FLUSH;
560 else
561 flags = ACL_START;
562
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700563 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
564
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200565 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200566}
567
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300568static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300569{
570 struct sk_buff *skb;
571 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300572 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300573 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200574 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300575
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300576 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300577 return;
578
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300579 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300580 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300581
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300582 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300583
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300584 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300585 control |= L2CAP_CTRL_FRAME_TYPE;
586
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300587 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300588 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300589
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300590 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300591 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300592
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300593 skb = bt_skb_alloc(count, GFP_ATOMIC);
594 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300595 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300596
597 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300598 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300599 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300600 put_unaligned_le16(control, skb_put(skb, 2));
601
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300602 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300603 u16 fcs = crc16(0, (u8 *)lh, count - 2);
604 put_unaligned_le16(fcs, skb_put(skb, 2));
605 }
606
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200607 if (lmp_no_flush_capable(conn->hcon->hdev))
608 flags = ACL_START_NO_FLUSH;
609 else
610 flags = ACL_START;
611
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700612 bt_cb(skb)->force_active = chan->force_active;
613
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300614 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300615}
616
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300617static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300618{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300619 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300620 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300621 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300622 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300623 control |= L2CAP_SUPER_RCV_READY;
624
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300625 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300626
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300627 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300628}
629
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300630static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300631{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300632 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300633}
634
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300635static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200636{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300637 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200638
639 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100640 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
641 return;
642
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300643 if (l2cap_check_security(chan) &&
644 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200645 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300646 req.scid = cpu_to_le16(chan->scid);
647 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200648
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300649 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300650 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200651
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300652 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
653 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200654 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200655 } else {
656 struct l2cap_info_req req;
657 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
658
659 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
660 conn->info_ident = l2cap_get_ident(conn);
661
662 mod_timer(&conn->info_timer, jiffies +
663 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
664
665 l2cap_send_cmd(conn, conn->info_ident,
666 L2CAP_INFO_REQ, sizeof(req), &req);
667 }
668}
669
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300670static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
671{
672 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300673 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300674 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
675
676 switch (mode) {
677 case L2CAP_MODE_ERTM:
678 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
679 case L2CAP_MODE_STREAMING:
680 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
681 default:
682 return 0x00;
683 }
684}
685
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300686static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300687{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300688 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300689 struct l2cap_disconn_req req;
690
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300691 if (!conn)
692 return;
693
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300694 sk = chan->sk;
695
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300696 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300697 __clear_retrans_timer(chan);
698 __clear_monitor_timer(chan);
699 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300700 }
701
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300702 req.dcid = cpu_to_le16(chan->dcid);
703 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300704 l2cap_send_cmd(conn, l2cap_get_ident(conn),
705 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300706
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300707 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300708 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300709}
710
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200712static void l2cap_conn_start(struct l2cap_conn *conn)
713{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300714 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200715
716 BT_DBG("conn %p", conn);
717
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300718 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200719
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300720 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300721 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300722
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200723 bh_lock_sock(sk);
724
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300725 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200726 bh_unlock_sock(sk);
727 continue;
728 }
729
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300730 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300731 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300732
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300733 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300734 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300735 bh_unlock_sock(sk);
736 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200737 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300738
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300739 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
740 && test_bit(CONF_STATE2_DEVICE,
741 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300742 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300743 * so release the lock */
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300744 read_unlock(&conn->chan_lock);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300745 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300746 read_lock(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300747 bh_unlock_sock(sk);
748 continue;
749 }
750
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300751 req.scid = cpu_to_le16(chan->scid);
752 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300753
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300754 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300755 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300756
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300757 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
758 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300759
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300760 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200761 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300762 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300763 rsp.scid = cpu_to_le16(chan->dcid);
764 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200765
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300766 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100767 if (bt_sk(sk)->defer_setup) {
768 struct sock *parent = bt_sk(sk)->parent;
769 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
770 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
771 parent->sk_data_ready(parent, 0);
772
773 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300774 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100775 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
776 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
777 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200778 } else {
779 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
780 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
781 }
782
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300783 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
784 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300785
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300786 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300787 rsp.result != L2CAP_CR_SUCCESS) {
788 bh_unlock_sock(sk);
789 continue;
790 }
791
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300792 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300793 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300794 l2cap_build_conf_req(chan, buf), buf);
795 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200796 }
797
798 bh_unlock_sock(sk);
799 }
800
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300801 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200802}
803
Ville Tervob62f3282011-02-10 22:38:50 -0300804/* Find socket with cid and source bdaddr.
805 * Returns closest match, locked.
806 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300807static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300808{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300809 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300810
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300811 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300812
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300813 list_for_each_entry(c, &chan_list, global_l) {
814 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300815
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300816 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300817 continue;
818
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300819 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300820 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300821 if (!bacmp(&bt_sk(sk)->src, src)) {
822 read_unlock(&chan_list_lock);
823 return c;
824 }
Ville Tervob62f3282011-02-10 22:38:50 -0300825
826 /* Closest match */
827 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300828 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300829 }
830 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300831
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300832 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300833
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300834 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300835}
836
837static void l2cap_le_conn_ready(struct l2cap_conn *conn)
838{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300839 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300840 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300841
842 BT_DBG("");
843
844 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300845 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300846 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300847 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300848 return;
849
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300850 parent = pchan->sk;
851
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300852 bh_lock_sock(parent);
853
Ville Tervob62f3282011-02-10 22:38:50 -0300854 /* Check for backlog size */
855 if (sk_acceptq_is_full(parent)) {
856 BT_DBG("backlog full %d", parent->sk_ack_backlog);
857 goto clean;
858 }
859
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300860 chan = pchan->ops->new_connection(pchan->data);
861 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300862 goto clean;
863
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300864 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300865
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300866 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300867
868 hci_conn_hold(conn->hcon);
869
Ville Tervob62f3282011-02-10 22:38:50 -0300870 bacpy(&bt_sk(sk)->src, conn->src);
871 bacpy(&bt_sk(sk)->dst, conn->dst);
872
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300873 bt_accept_enqueue(parent, sk);
874
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300875 __l2cap_chan_add(conn, chan);
876
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300877 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300878
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300879 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300880 parent->sk_data_ready(parent, 0);
881
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300882 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300883
884clean:
885 bh_unlock_sock(parent);
886}
887
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300888static void l2cap_chan_ready(struct sock *sk)
889{
890 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
891 struct sock *parent = bt_sk(sk)->parent;
892
893 BT_DBG("sk %p, parent %p", sk, parent);
894
895 chan->conf_state = 0;
896 __clear_chan_timer(chan);
897
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300898 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300899 sk->sk_state_change(sk);
900
901 if (parent)
902 parent->sk_data_ready(parent, 0);
903}
904
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200905static void l2cap_conn_ready(struct l2cap_conn *conn)
906{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300907 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200908
909 BT_DBG("conn %p", conn);
910
Ville Tervob62f3282011-02-10 22:38:50 -0300911 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
912 l2cap_le_conn_ready(conn);
913
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300914 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200915
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300916 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300917 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300918
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200919 bh_lock_sock(sk);
920
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300921 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300922 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300923 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300924
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300925 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300926 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300927 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200928 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300929
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300930 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300931 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200932
933 bh_unlock_sock(sk);
934 }
935
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300936 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200937}
938
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200939/* Notify sockets that we cannot guaranty reliability anymore */
940static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
941{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300942 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200943
944 BT_DBG("conn %p", conn);
945
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300946 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200947
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300948 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300949 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300950
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300951 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200952 sk->sk_err = err;
953 }
954
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300955 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200956}
957
958static void l2cap_info_timeout(unsigned long arg)
959{
960 struct l2cap_conn *conn = (void *) arg;
961
Marcel Holtmann984947d2009-02-06 23:35:19 +0100962 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100963 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100964
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200965 l2cap_conn_start(conn);
966}
967
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300968static void l2cap_conn_del(struct hci_conn *hcon, int err)
969{
970 struct l2cap_conn *conn = hcon->l2cap_data;
971 struct l2cap_chan *chan, *l;
972 struct sock *sk;
973
974 if (!conn)
975 return;
976
977 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
978
979 kfree_skb(conn->rx_skb);
980
981 /* Kill channels */
982 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
983 sk = chan->sk;
984 bh_lock_sock(sk);
985 l2cap_chan_del(chan, err);
986 bh_unlock_sock(sk);
987 chan->ops->close(chan->data);
988 }
989
990 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
991 del_timer_sync(&conn->info_timer);
992
993 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
994 del_timer(&conn->security_timer);
995
996 hcon->l2cap_data = NULL;
997 kfree(conn);
998}
999
1000static void security_timeout(unsigned long arg)
1001{
1002 struct l2cap_conn *conn = (void *) arg;
1003
1004 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1005}
1006
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1008{
Marcel Holtmann01394182006-07-03 10:02:46 +02001009 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010
Marcel Holtmann01394182006-07-03 10:02:46 +02001011 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 return conn;
1013
Marcel Holtmann01394182006-07-03 10:02:46 +02001014 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1015 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017
1018 hcon->l2cap_data = conn;
1019 conn->hcon = hcon;
1020
Marcel Holtmann01394182006-07-03 10:02:46 +02001021 BT_DBG("hcon %p conn %p", hcon, conn);
1022
Ville Tervoacd7d372011-02-10 22:38:49 -03001023 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1024 conn->mtu = hcon->hdev->le_mtu;
1025 else
1026 conn->mtu = hcon->hdev->acl_mtu;
1027
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 conn->src = &hcon->hdev->bdaddr;
1029 conn->dst = &hcon->dst;
1030
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001031 conn->feat_mask = 0;
1032
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001034 rwlock_init(&conn->chan_lock);
1035
1036 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001038 if (hcon->type == LE_LINK)
1039 setup_timer(&conn->security_timer, security_timeout,
1040 (unsigned long) conn);
1041 else
Ville Tervob62f3282011-02-10 22:38:50 -03001042 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +00001043 (unsigned long) conn);
1044
Marcel Holtmann2950f212009-02-12 14:02:50 +01001045 conn->disc_reason = 0x13;
1046
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 return conn;
1048}
1049
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001050static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001052 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001053 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001054 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055}
1056
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058
1059/* Find socket with psm and source bdaddr.
1060 * Returns closest match.
1061 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001062static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001064 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001066 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001067
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001068 list_for_each_entry(c, &chan_list, global_l) {
1069 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001070
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001071 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 continue;
1073
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001074 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001076 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001077 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001078 return c;
1079 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080
1081 /* Closest match */
1082 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001083 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 }
1085 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001087 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001088
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001089 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090}
1091
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001092int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001094 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 bdaddr_t *src = &bt_sk(sk)->src;
1096 bdaddr_t *dst = &bt_sk(sk)->dst;
1097 struct l2cap_conn *conn;
1098 struct hci_conn *hcon;
1099 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001100 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001101 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001103 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001104 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001106 hdev = hci_get_route(dst, src);
1107 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 return -EHOSTUNREACH;
1109
1110 hci_dev_lock_bh(hdev);
1111
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001112 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001113
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001114 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001115 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001116 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001117 else
1118 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001119 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001120
Ville Tervo30e76272011-02-22 16:10:53 -03001121 if (IS_ERR(hcon)) {
1122 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001124 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125
1126 conn = l2cap_conn_add(hcon, 0);
1127 if (!conn) {
1128 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001129 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 goto done;
1131 }
1132
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 /* Update source addr of the socket */
1134 bacpy(src, conn->src);
1135
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001136 l2cap_chan_add(conn, chan);
1137
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001138 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001139 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140
1141 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001142 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001143 __clear_chan_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001144 if (l2cap_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001145 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001146 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001147 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 }
1149
Ville Tervo30e76272011-02-22 16:10:53 -03001150 err = 0;
1151
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152done:
1153 hci_dev_unlock_bh(hdev);
1154 hci_dev_put(hdev);
1155 return err;
1156}
1157
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001158int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001159{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001160 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001161 DECLARE_WAITQUEUE(wait, current);
1162 int err = 0;
1163 int timeo = HZ/5;
1164
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001165 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001166 while ((chan->unacked_frames > 0 && chan->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001167 set_current_state(TASK_INTERRUPTIBLE);
1168
1169 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);
1180
1181 err = sock_error(sk);
1182 if (err)
1183 break;
1184 }
1185 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001186 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001187 return err;
1188}
1189
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001190static void l2cap_monitor_timeout(unsigned long arg)
1191{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001192 struct l2cap_chan *chan = (void *) arg;
1193 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001194
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001195 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001196
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001197 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001198 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001199 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001200 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001201 return;
1202 }
1203
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001204 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001205 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001206
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001207 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001208 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001209}
1210
1211static void l2cap_retrans_timeout(unsigned long arg)
1212{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001213 struct l2cap_chan *chan = (void *) arg;
1214 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001215
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001216 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001217
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001218 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001219 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001220 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001221
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001222 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001223
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001224 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001225 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001226}
1227
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001228static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001229{
1230 struct sk_buff *skb;
1231
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001232 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001233 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001234 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001235 break;
1236
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001237 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001238 kfree_skb(skb);
1239
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001240 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001241 }
1242
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001243 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001244 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001245}
1246
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001247void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001248{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001249 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001250 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001251
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001252 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001253
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001254 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001255 flags = ACL_START_NO_FLUSH;
1256 else
1257 flags = ACL_START;
1258
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -07001259 bt_cb(skb)->force_active = chan->force_active;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001260 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001261}
1262
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001263void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001264{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001265 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001266 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001267
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001268 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001269 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001270 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001271 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001272
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001273 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001274 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1275 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001276 }
1277
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001278 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001279
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001280 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001281 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001282}
1283
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001284static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001285{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001286 struct sk_buff *skb, *tx_skb;
1287 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001288
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001289 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001290 if (!skb)
1291 return;
1292
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001293 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001294 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001295 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001296
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001297 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001298 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001299
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001300 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001301
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001302 if (chan->remote_max_tx &&
1303 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001304 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001305 return;
1306 }
1307
1308 tx_skb = skb_clone(skb, GFP_ATOMIC);
1309 bt_cb(skb)->retries++;
1310 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001311 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001312
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001313 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001314 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001315
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001316 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001317 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001318
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001319 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1320
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001321 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001322 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1323 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1324 }
1325
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001326 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001327}
1328
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001329int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001330{
1331 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001332 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001333 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001334
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001335 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001336 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001337
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001338 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001339
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001340 if (chan->remote_max_tx &&
1341 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001342 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001343 break;
1344 }
1345
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001346 tx_skb = skb_clone(skb, GFP_ATOMIC);
1347
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001348 bt_cb(skb)->retries++;
1349
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001350 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001351 control &= L2CAP_CTRL_SAR;
1352
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001353 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001354 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001355
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001356 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1357 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001358 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1359
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001360
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001361 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001362 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1363 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1364 }
1365
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001366 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001367
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001368 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001369
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001370 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1371 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001372
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301373 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001374 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301375
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001376 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001377
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001378 if (skb_queue_is_last(&chan->tx_q, skb))
1379 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001380 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001381 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001382
1383 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001384 }
1385
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001386 return nsent;
1387}
1388
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001389static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001390{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001391 int ret;
1392
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001393 if (!skb_queue_empty(&chan->tx_q))
1394 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001395
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001396 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001397 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001398 return ret;
1399}
1400
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001401static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001402{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001403 u16 control = 0;
1404
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001405 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001406
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001407 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001408 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001409 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001410 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001411 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001412 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001413
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001414 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001415 return;
1416
1417 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001418 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001419}
1420
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001421static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001422{
1423 struct srej_list *tail;
1424 u16 control;
1425
1426 control = L2CAP_SUPER_SELECT_REJECT;
1427 control |= L2CAP_CTRL_FINAL;
1428
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001429 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001430 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1431
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001432 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001433}
1434
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001435static 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 -07001436{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001437 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001438 struct sk_buff **frag;
1439 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001441 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001442 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443
1444 sent += count;
1445 len -= count;
1446
1447 /* Continuation fragments (no L2CAP header) */
1448 frag = &skb_shinfo(skb)->frag_list;
1449 while (len) {
1450 count = min_t(unsigned int, conn->mtu, len);
1451
1452 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1453 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001454 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001455 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1456 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457
1458 sent += count;
1459 len -= count;
1460
1461 frag = &(*frag)->next;
1462 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463
1464 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001465}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001467struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001468{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001469 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001470 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001471 struct sk_buff *skb;
1472 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1473 struct l2cap_hdr *lh;
1474
1475 BT_DBG("sk %p len %d", sk, (int)len);
1476
1477 count = min_t(unsigned int, (conn->mtu - hlen), len);
1478 skb = bt_skb_send_alloc(sk, count + hlen,
1479 msg->msg_flags & MSG_DONTWAIT, &err);
1480 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001481 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001482
1483 /* Create L2CAP header */
1484 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001485 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001486 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001487 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001488
1489 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1490 if (unlikely(err < 0)) {
1491 kfree_skb(skb);
1492 return ERR_PTR(err);
1493 }
1494 return skb;
1495}
1496
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001497struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001498{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001499 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001500 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001501 struct sk_buff *skb;
1502 int err, count, hlen = L2CAP_HDR_SIZE;
1503 struct l2cap_hdr *lh;
1504
1505 BT_DBG("sk %p len %d", sk, (int)len);
1506
1507 count = min_t(unsigned int, (conn->mtu - hlen), len);
1508 skb = bt_skb_send_alloc(sk, count + hlen,
1509 msg->msg_flags & MSG_DONTWAIT, &err);
1510 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001511 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001512
1513 /* Create L2CAP header */
1514 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001515 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001516 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1517
1518 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1519 if (unlikely(err < 0)) {
1520 kfree_skb(skb);
1521 return ERR_PTR(err);
1522 }
1523 return skb;
1524}
1525
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001526struct 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 -03001527{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001528 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001529 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001530 struct sk_buff *skb;
1531 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1532 struct l2cap_hdr *lh;
1533
1534 BT_DBG("sk %p len %d", sk, (int)len);
1535
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001536 if (!conn)
1537 return ERR_PTR(-ENOTCONN);
1538
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001539 if (sdulen)
1540 hlen += 2;
1541
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001542 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001543 hlen += 2;
1544
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001545 count = min_t(unsigned int, (conn->mtu - hlen), len);
1546 skb = bt_skb_send_alloc(sk, count + hlen,
1547 msg->msg_flags & MSG_DONTWAIT, &err);
1548 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001549 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001550
1551 /* Create L2CAP header */
1552 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001553 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001554 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1555 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001556 if (sdulen)
1557 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001558
1559 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1560 if (unlikely(err < 0)) {
1561 kfree_skb(skb);
1562 return ERR_PTR(err);
1563 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001564
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001565 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001566 put_unaligned_le16(0, skb_put(skb, 2));
1567
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001568 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001569 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570}
1571
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001572int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001573{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001574 struct sk_buff *skb;
1575 struct sk_buff_head sar_queue;
1576 u16 control;
1577 size_t size = 0;
1578
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001579 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001580 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001581 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001582 if (IS_ERR(skb))
1583 return PTR_ERR(skb);
1584
1585 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001586 len -= chan->remote_mps;
1587 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001588
1589 while (len > 0) {
1590 size_t buflen;
1591
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001592 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001593 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001594 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001595 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001596 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001597 buflen = len;
1598 }
1599
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001600 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001601 if (IS_ERR(skb)) {
1602 skb_queue_purge(&sar_queue);
1603 return PTR_ERR(skb);
1604 }
1605
1606 __skb_queue_tail(&sar_queue, skb);
1607 len -= buflen;
1608 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001609 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001610 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1611 if (chan->tx_send_head == NULL)
1612 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001613
1614 return size;
1615}
1616
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001617int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1618{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001619 struct sk_buff *skb;
1620 u16 control;
1621 int err;
1622
1623 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001624 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001625 skb = l2cap_create_connless_pdu(chan, msg, len);
1626 if (IS_ERR(skb))
1627 return PTR_ERR(skb);
1628
1629 l2cap_do_send(chan, skb);
1630 return len;
1631 }
1632
1633 switch (chan->mode) {
1634 case L2CAP_MODE_BASIC:
1635 /* Check outgoing MTU */
1636 if (len > chan->omtu)
1637 return -EMSGSIZE;
1638
1639 /* Create a basic PDU */
1640 skb = l2cap_create_basic_pdu(chan, msg, len);
1641 if (IS_ERR(skb))
1642 return PTR_ERR(skb);
1643
1644 l2cap_do_send(chan, skb);
1645 err = len;
1646 break;
1647
1648 case L2CAP_MODE_ERTM:
1649 case L2CAP_MODE_STREAMING:
1650 /* Entire SDU fits into one PDU */
1651 if (len <= chan->remote_mps) {
1652 control = L2CAP_SDU_UNSEGMENTED;
1653 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1654 0);
1655 if (IS_ERR(skb))
1656 return PTR_ERR(skb);
1657
1658 __skb_queue_tail(&chan->tx_q, skb);
1659
1660 if (chan->tx_send_head == NULL)
1661 chan->tx_send_head = skb;
1662
1663 } else {
1664 /* Segment SDU into multiples PDUs */
1665 err = l2cap_sar_segment_sdu(chan, msg, len);
1666 if (err < 0)
1667 return err;
1668 }
1669
1670 if (chan->mode == L2CAP_MODE_STREAMING) {
1671 l2cap_streaming_send(chan);
1672 err = len;
1673 break;
1674 }
1675
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001676 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1677 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001678 err = len;
1679 break;
1680 }
1681
1682 err = l2cap_ertm_send(chan);
1683 if (err >= 0)
1684 err = len;
1685
1686 break;
1687
1688 default:
1689 BT_DBG("bad state %1.1x", chan->mode);
1690 err = -EBADFD;
1691 }
1692
1693 return err;
1694}
1695
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696/* Copy frame to all raw sockets on that connection */
1697static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1698{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001700 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701
1702 BT_DBG("conn %p", conn);
1703
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001704 read_lock(&conn->chan_lock);
1705 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001706 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001707 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 continue;
1709
1710 /* Don't send frame to the socket it came from */
1711 if (skb->sk == sk)
1712 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001713 nskb = skb_clone(skb, GFP_ATOMIC);
1714 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 continue;
1716
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001717 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 kfree_skb(nskb);
1719 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001720 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721}
1722
1723/* ---- L2CAP signalling commands ---- */
1724static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1725 u8 code, u8 ident, u16 dlen, void *data)
1726{
1727 struct sk_buff *skb, **frag;
1728 struct l2cap_cmd_hdr *cmd;
1729 struct l2cap_hdr *lh;
1730 int len, count;
1731
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001732 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1733 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734
1735 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1736 count = min_t(unsigned int, conn->mtu, len);
1737
1738 skb = bt_skb_alloc(count, GFP_ATOMIC);
1739 if (!skb)
1740 return NULL;
1741
1742 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001743 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001744
1745 if (conn->hcon->type == LE_LINK)
1746 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1747 else
1748 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749
1750 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1751 cmd->code = code;
1752 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001753 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754
1755 if (dlen) {
1756 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1757 memcpy(skb_put(skb, count), data, count);
1758 data += count;
1759 }
1760
1761 len -= skb->len;
1762
1763 /* Continuation fragments (no L2CAP header) */
1764 frag = &skb_shinfo(skb)->frag_list;
1765 while (len) {
1766 count = min_t(unsigned int, conn->mtu, len);
1767
1768 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1769 if (!*frag)
1770 goto fail;
1771
1772 memcpy(skb_put(*frag, count), data, count);
1773
1774 len -= count;
1775 data += count;
1776
1777 frag = &(*frag)->next;
1778 }
1779
1780 return skb;
1781
1782fail:
1783 kfree_skb(skb);
1784 return NULL;
1785}
1786
1787static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1788{
1789 struct l2cap_conf_opt *opt = *ptr;
1790 int len;
1791
1792 len = L2CAP_CONF_OPT_SIZE + opt->len;
1793 *ptr += len;
1794
1795 *type = opt->type;
1796 *olen = opt->len;
1797
1798 switch (opt->len) {
1799 case 1:
1800 *val = *((u8 *) opt->val);
1801 break;
1802
1803 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001804 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 break;
1806
1807 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001808 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 break;
1810
1811 default:
1812 *val = (unsigned long) opt->val;
1813 break;
1814 }
1815
1816 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1817 return len;
1818}
1819
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1821{
1822 struct l2cap_conf_opt *opt = *ptr;
1823
1824 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1825
1826 opt->type = type;
1827 opt->len = len;
1828
1829 switch (len) {
1830 case 1:
1831 *((u8 *) opt->val) = val;
1832 break;
1833
1834 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001835 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 break;
1837
1838 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001839 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 break;
1841
1842 default:
1843 memcpy(opt->val, (void *) val, len);
1844 break;
1845 }
1846
1847 *ptr += L2CAP_CONF_OPT_SIZE + len;
1848}
1849
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001850static void l2cap_ack_timeout(unsigned long arg)
1851{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001852 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001853
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001854 bh_lock_sock(chan->sk);
1855 l2cap_send_ack(chan);
1856 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001857}
1858
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001859static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001860{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001861 struct sock *sk = chan->sk;
1862
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001863 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001864 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001865 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001866 chan->num_acked = 0;
1867 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001868
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001869 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1870 (unsigned long) chan);
1871 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1872 (unsigned long) chan);
1873 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001874
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001875 skb_queue_head_init(&chan->srej_q);
1876 skb_queue_head_init(&chan->busy_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. Padovan311bb892011-03-25 20:41:00 -03001880 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001881
1882 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001883}
1884
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001885static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1886{
1887 switch (mode) {
1888 case L2CAP_MODE_STREAMING:
1889 case L2CAP_MODE_ERTM:
1890 if (l2cap_mode_supported(mode, remote_feat_mask))
1891 return mode;
1892 /* fall through */
1893 default:
1894 return L2CAP_MODE_BASIC;
1895 }
1896}
1897
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001898static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001901 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 void *ptr = req->data;
1903
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001904 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001906 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001907 goto done;
1908
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001909 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001910 case L2CAP_MODE_STREAMING:
1911 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001912 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001913 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001914
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001915 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001916 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001917 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001918 break;
1919 }
1920
1921done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001922 if (chan->imtu != L2CAP_DEFAULT_MTU)
1923 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001924
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001925 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001926 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001927 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1928 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001929 break;
1930
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001931 rfc.mode = L2CAP_MODE_BASIC;
1932 rfc.txwin_size = 0;
1933 rfc.max_transmit = 0;
1934 rfc.retrans_timeout = 0;
1935 rfc.monitor_timeout = 0;
1936 rfc.max_pdu_size = 0;
1937
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001938 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1939 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001940 break;
1941
1942 case L2CAP_MODE_ERTM:
1943 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001944 rfc.txwin_size = chan->tx_win;
1945 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001946 rfc.retrans_timeout = 0;
1947 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001948 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001949 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1950 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001951
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001952 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1953 (unsigned long) &rfc);
1954
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001955 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001956 break;
1957
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001958 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001959 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001960 chan->fcs = L2CAP_FCS_NONE;
1961 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001962 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001963 break;
1964
1965 case L2CAP_MODE_STREAMING:
1966 rfc.mode = L2CAP_MODE_STREAMING;
1967 rfc.txwin_size = 0;
1968 rfc.max_transmit = 0;
1969 rfc.retrans_timeout = 0;
1970 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001971 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001972 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1973 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001974
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001975 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1976 (unsigned long) &rfc);
1977
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001978 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001979 break;
1980
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001981 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001982 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001983 chan->fcs = L2CAP_FCS_NONE;
1984 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001985 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001986 break;
1987 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001989 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001990 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991
1992 return ptr - data;
1993}
1994
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001995static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001997 struct l2cap_conf_rsp *rsp = data;
1998 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001999 void *req = chan->conf_req;
2000 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002001 int type, hint, olen;
2002 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002003 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002004 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002005 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002007 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002008
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002009 while (len >= L2CAP_CONF_OPT_SIZE) {
2010 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002012 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002013 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002014
2015 switch (type) {
2016 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002017 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002018 break;
2019
2020 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002021 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002022 break;
2023
2024 case L2CAP_CONF_QOS:
2025 break;
2026
Marcel Holtmann6464f352007-10-20 13:39:51 +02002027 case L2CAP_CONF_RFC:
2028 if (olen == sizeof(rfc))
2029 memcpy(&rfc, (void *) val, olen);
2030 break;
2031
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002032 case L2CAP_CONF_FCS:
2033 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002034 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002035
2036 break;
2037
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002038 default:
2039 if (hint)
2040 break;
2041
2042 result = L2CAP_CONF_UNKNOWN;
2043 *((u8 *) ptr++) = type;
2044 break;
2045 }
2046 }
2047
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002048 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002049 goto done;
2050
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002051 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002052 case L2CAP_MODE_STREAMING:
2053 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002054 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002055 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002056 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002057 break;
2058 }
2059
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002060 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002061 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002062
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002063 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002064 }
2065
2066done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002067 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002068 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002069 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002070
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002071 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002072 return -ECONNREFUSED;
2073
2074 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2075 sizeof(rfc), (unsigned long) &rfc);
2076 }
2077
2078
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002079 if (result == L2CAP_CONF_SUCCESS) {
2080 /* Configure output options and let the other side know
2081 * which ones we don't like. */
2082
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002083 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2084 result = L2CAP_CONF_UNACCEPT;
2085 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002086 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002087 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002088 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002089 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002090
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002091 switch (rfc.mode) {
2092 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002093 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002094 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002095 break;
2096
2097 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002098 chan->remote_tx_win = rfc.txwin_size;
2099 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002100
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002101 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2102 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002103
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002104 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002105
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002106 rfc.retrans_timeout =
2107 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2108 rfc.monitor_timeout =
2109 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002110
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002111 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002112
2113 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2114 sizeof(rfc), (unsigned long) &rfc);
2115
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002116 break;
2117
2118 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002119 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2120 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002121
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002122 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002123
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002124 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002125
2126 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2127 sizeof(rfc), (unsigned long) &rfc);
2128
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002129 break;
2130
2131 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002132 result = L2CAP_CONF_UNACCEPT;
2133
2134 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002135 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002136 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002137
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002138 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002139 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002140 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002141 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002142 rsp->result = cpu_to_le16(result);
2143 rsp->flags = cpu_to_le16(0x0000);
2144
2145 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146}
2147
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002148static 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 -03002149{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002150 struct l2cap_conf_req *req = data;
2151 void *ptr = req->data;
2152 int type, olen;
2153 unsigned long val;
2154 struct l2cap_conf_rfc rfc;
2155
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002156 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002157
2158 while (len >= L2CAP_CONF_OPT_SIZE) {
2159 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2160
2161 switch (type) {
2162 case L2CAP_CONF_MTU:
2163 if (val < L2CAP_DEFAULT_MIN_MTU) {
2164 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002165 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002166 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002167 chan->imtu = val;
2168 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002169 break;
2170
2171 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002172 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002173 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002174 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002175 break;
2176
2177 case L2CAP_CONF_RFC:
2178 if (olen == sizeof(rfc))
2179 memcpy(&rfc, (void *)val, olen);
2180
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002181 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002182 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002183 return -ECONNREFUSED;
2184
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002185 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002186
2187 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2188 sizeof(rfc), (unsigned long) &rfc);
2189 break;
2190 }
2191 }
2192
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002193 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002194 return -ECONNREFUSED;
2195
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002196 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002197
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002198 if (*result == L2CAP_CONF_SUCCESS) {
2199 switch (rfc.mode) {
2200 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002201 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2202 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2203 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002204 break;
2205 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002206 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002207 }
2208 }
2209
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002210 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002211 req->flags = cpu_to_le16(0x0000);
2212
2213 return ptr - data;
2214}
2215
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002216static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217{
2218 struct l2cap_conf_rsp *rsp = data;
2219 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002221 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002223 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002224 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002225 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226
2227 return ptr - data;
2228}
2229
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002230void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002231{
2232 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002233 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002234 u8 buf[128];
2235
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002236 rsp.scid = cpu_to_le16(chan->dcid);
2237 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002238 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2239 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2240 l2cap_send_cmd(conn, chan->ident,
2241 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2242
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002243 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002244 return;
2245
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002246 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2247 l2cap_build_conf_req(chan, buf), buf);
2248 chan->num_conf_req++;
2249}
2250
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002251static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002252{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002253 int type, olen;
2254 unsigned long val;
2255 struct l2cap_conf_rfc rfc;
2256
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002257 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002258
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002259 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002260 return;
2261
2262 while (len >= L2CAP_CONF_OPT_SIZE) {
2263 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2264
2265 switch (type) {
2266 case L2CAP_CONF_RFC:
2267 if (olen == sizeof(rfc))
2268 memcpy(&rfc, (void *)val, olen);
2269 goto done;
2270 }
2271 }
2272
2273done:
2274 switch (rfc.mode) {
2275 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002276 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2277 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2278 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002279 break;
2280 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002281 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002282 }
2283}
2284
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002285static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2286{
2287 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2288
2289 if (rej->reason != 0x0000)
2290 return 0;
2291
2292 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2293 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002294 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002295
2296 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002297 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002298
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002299 l2cap_conn_start(conn);
2300 }
2301
2302 return 0;
2303}
2304
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2306{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2308 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002309 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002310 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002311 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312
2313 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002314 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315
2316 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2317
2318 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002319 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2320 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 result = L2CAP_CR_BAD_PSM;
2322 goto sendresp;
2323 }
2324
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002325 parent = pchan->sk;
2326
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002327 bh_lock_sock(parent);
2328
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002329 /* Check if the ACL is secure enough (if not SDP) */
2330 if (psm != cpu_to_le16(0x0001) &&
2331 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002332 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002333 result = L2CAP_CR_SEC_BLOCK;
2334 goto response;
2335 }
2336
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 result = L2CAP_CR_NO_MEM;
2338
2339 /* Check for backlog size */
2340 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002341 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342 goto response;
2343 }
2344
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002345 chan = pchan->ops->new_connection(pchan->data);
2346 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 goto response;
2348
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002349 sk = chan->sk;
2350
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002351 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352
2353 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002354 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2355 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002357 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 goto response;
2359 }
2360
2361 hci_conn_hold(conn->hcon);
2362
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 bacpy(&bt_sk(sk)->src, conn->src);
2364 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002365 chan->psm = psm;
2366 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002368 bt_accept_enqueue(parent, sk);
2369
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002370 __l2cap_chan_add(conn, chan);
2371
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002372 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002374 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002376 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377
Marcel Holtmann984947d2009-02-06 23:35:19 +01002378 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002379 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002380 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002381 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002382 result = L2CAP_CR_PEND;
2383 status = L2CAP_CS_AUTHOR_PEND;
2384 parent->sk_data_ready(parent, 0);
2385 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002386 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002387 result = L2CAP_CR_SUCCESS;
2388 status = L2CAP_CS_NO_INFO;
2389 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002390 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002391 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002392 result = L2CAP_CR_PEND;
2393 status = L2CAP_CS_AUTHEN_PEND;
2394 }
2395 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002396 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002397 result = L2CAP_CR_PEND;
2398 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 }
2400
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002401 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402
2403response:
2404 bh_unlock_sock(parent);
2405
2406sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002407 rsp.scid = cpu_to_le16(scid);
2408 rsp.dcid = cpu_to_le16(dcid);
2409 rsp.result = cpu_to_le16(result);
2410 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002412
2413 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2414 struct l2cap_info_req info;
2415 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2416
2417 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2418 conn->info_ident = l2cap_get_ident(conn);
2419
2420 mod_timer(&conn->info_timer, jiffies +
2421 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2422
2423 l2cap_send_cmd(conn, conn->info_ident,
2424 L2CAP_INFO_REQ, sizeof(info), &info);
2425 }
2426
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002427 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002428 result == L2CAP_CR_SUCCESS) {
2429 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002430 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002431 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002432 l2cap_build_conf_req(chan, buf), buf);
2433 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002434 }
2435
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 return 0;
2437}
2438
2439static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2440{
2441 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2442 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002443 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444 struct sock *sk;
2445 u8 req[128];
2446
2447 scid = __le16_to_cpu(rsp->scid);
2448 dcid = __le16_to_cpu(rsp->dcid);
2449 result = __le16_to_cpu(rsp->result);
2450 status = __le16_to_cpu(rsp->status);
2451
2452 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2453
2454 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002455 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002456 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002457 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002459 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002460 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002461 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462 }
2463
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002464 sk = chan->sk;
2465
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466 switch (result) {
2467 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002468 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002469 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002470 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002471 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002472
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002473 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002474 break;
2475
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002477 l2cap_build_conf_req(chan, req), req);
2478 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 break;
2480
2481 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002482 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483 break;
2484
2485 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002486 /* don't delete l2cap channel if sk is owned by user */
2487 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002488 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002489 __clear_chan_timer(chan);
2490 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002491 break;
2492 }
2493
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002494 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495 break;
2496 }
2497
2498 bh_unlock_sock(sk);
2499 return 0;
2500}
2501
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002502static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002503{
2504 /* FCS is enabled only in ERTM or streaming mode, if one or both
2505 * sides request it.
2506 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002507 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002508 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002509 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002510 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002511}
2512
Al Viro88219a02007-07-29 00:17:25 -07002513static 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 -07002514{
2515 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2516 u16 dcid, flags;
2517 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002518 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002520 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521
2522 dcid = __le16_to_cpu(req->dcid);
2523 flags = __le16_to_cpu(req->flags);
2524
2525 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2526
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002527 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002528 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529 return -ENOENT;
2530
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002531 sk = chan->sk;
2532
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002533 if (chan->state != BT_CONFIG) {
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002534 struct l2cap_cmd_rej rej;
2535
2536 rej.reason = cpu_to_le16(0x0002);
2537 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2538 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002539 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002540 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002541
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002542 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002543 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002544 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002545 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002546 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002547 L2CAP_CONF_REJECT, flags), rsp);
2548 goto unlock;
2549 }
2550
2551 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002552 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2553 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554
2555 if (flags & 0x0001) {
2556 /* Incomplete config. Send empty response. */
2557 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002558 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002559 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 goto unlock;
2561 }
2562
2563 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002564 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002565 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002566 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002568 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002569
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002570 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002571 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002572
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002573 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002574 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002575
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002576 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002577 goto unlock;
2578
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002579 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002580 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002581
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002582 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002583
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002584 chan->next_tx_seq = 0;
2585 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002586 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002587 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002588 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002589
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002591 goto unlock;
2592 }
2593
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002594 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002595 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002597 l2cap_build_conf_req(chan, buf), buf);
2598 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599 }
2600
2601unlock:
2602 bh_unlock_sock(sk);
2603 return 0;
2604}
2605
2606static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2607{
2608 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2609 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002610 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002612 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613
2614 scid = __le16_to_cpu(rsp->scid);
2615 flags = __le16_to_cpu(rsp->flags);
2616 result = __le16_to_cpu(rsp->result);
2617
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002618 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2619 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002621 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002622 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623 return 0;
2624
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002625 sk = chan->sk;
2626
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 switch (result) {
2628 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002629 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630 break;
2631
2632 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002633 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002634 char req[64];
2635
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002636 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002637 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002638 goto done;
2639 }
2640
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002641 /* throw out any old stored conf requests */
2642 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002643 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2644 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002645 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002646 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002647 goto done;
2648 }
2649
2650 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2651 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002652 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002653 if (result != L2CAP_CONF_SUCCESS)
2654 goto done;
2655 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 }
2657
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002658 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002659 sk->sk_err = ECONNRESET;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002660 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002661 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 goto done;
2663 }
2664
2665 if (flags & 0x01)
2666 goto done;
2667
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002668 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002670 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002671 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002672
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002673 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002674 chan->next_tx_seq = 0;
2675 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002676 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002677 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002678 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002679
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 l2cap_chan_ready(sk);
2681 }
2682
2683done:
2684 bh_unlock_sock(sk);
2685 return 0;
2686}
2687
2688static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2689{
2690 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2691 struct l2cap_disconn_rsp rsp;
2692 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002693 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694 struct sock *sk;
2695
2696 scid = __le16_to_cpu(req->scid);
2697 dcid = __le16_to_cpu(req->dcid);
2698
2699 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2700
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002701 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002702 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 return 0;
2704
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002705 sk = chan->sk;
2706
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002707 rsp.dcid = cpu_to_le16(chan->scid);
2708 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2710
2711 sk->sk_shutdown = SHUTDOWN_MASK;
2712
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002713 /* don't delete l2cap channel if sk is owned by user */
2714 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002715 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002716 __clear_chan_timer(chan);
2717 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002718 bh_unlock_sock(sk);
2719 return 0;
2720 }
2721
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002722 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723 bh_unlock_sock(sk);
2724
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002725 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 return 0;
2727}
2728
2729static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2730{
2731 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2732 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002733 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734 struct sock *sk;
2735
2736 scid = __le16_to_cpu(rsp->scid);
2737 dcid = __le16_to_cpu(rsp->dcid);
2738
2739 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2740
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002741 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002742 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743 return 0;
2744
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002745 sk = chan->sk;
2746
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002747 /* don't delete l2cap channel if sk is owned by user */
2748 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002749 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002750 __clear_chan_timer(chan);
2751 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002752 bh_unlock_sock(sk);
2753 return 0;
2754 }
2755
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002756 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757 bh_unlock_sock(sk);
2758
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002759 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760 return 0;
2761}
2762
2763static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2764{
2765 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 u16 type;
2767
2768 type = __le16_to_cpu(req->type);
2769
2770 BT_DBG("type 0x%4.4x", type);
2771
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002772 if (type == L2CAP_IT_FEAT_MASK) {
2773 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002774 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002775 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2776 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2777 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002778 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002779 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2780 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002781 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002782 l2cap_send_cmd(conn, cmd->ident,
2783 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002784 } else if (type == L2CAP_IT_FIXED_CHAN) {
2785 u8 buf[12];
2786 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2787 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2788 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2789 memcpy(buf + 4, l2cap_fixed_chan, 8);
2790 l2cap_send_cmd(conn, cmd->ident,
2791 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002792 } else {
2793 struct l2cap_info_rsp rsp;
2794 rsp.type = cpu_to_le16(type);
2795 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2796 l2cap_send_cmd(conn, cmd->ident,
2797 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2798 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799
2800 return 0;
2801}
2802
2803static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2804{
2805 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2806 u16 type, result;
2807
2808 type = __le16_to_cpu(rsp->type);
2809 result = __le16_to_cpu(rsp->result);
2810
2811 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2812
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002813 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2814 if (cmd->ident != conn->info_ident ||
2815 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2816 return 0;
2817
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002818 del_timer(&conn->info_timer);
2819
Ville Tervoadb08ed2010-08-04 09:43:33 +03002820 if (result != L2CAP_IR_SUCCESS) {
2821 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2822 conn->info_ident = 0;
2823
2824 l2cap_conn_start(conn);
2825
2826 return 0;
2827 }
2828
Marcel Holtmann984947d2009-02-06 23:35:19 +01002829 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002830 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002831
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002832 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002833 struct l2cap_info_req req;
2834 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2835
2836 conn->info_ident = l2cap_get_ident(conn);
2837
2838 l2cap_send_cmd(conn, conn->info_ident,
2839 L2CAP_INFO_REQ, sizeof(req), &req);
2840 } else {
2841 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2842 conn->info_ident = 0;
2843
2844 l2cap_conn_start(conn);
2845 }
2846 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002847 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002848 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002849
2850 l2cap_conn_start(conn);
2851 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002852
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853 return 0;
2854}
2855
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002856static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002857 u16 to_multiplier)
2858{
2859 u16 max_latency;
2860
2861 if (min > max || min < 6 || max > 3200)
2862 return -EINVAL;
2863
2864 if (to_multiplier < 10 || to_multiplier > 3200)
2865 return -EINVAL;
2866
2867 if (max >= to_multiplier * 8)
2868 return -EINVAL;
2869
2870 max_latency = (to_multiplier * 8 / max) - 1;
2871 if (latency > 499 || latency > max_latency)
2872 return -EINVAL;
2873
2874 return 0;
2875}
2876
2877static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2878 struct l2cap_cmd_hdr *cmd, u8 *data)
2879{
2880 struct hci_conn *hcon = conn->hcon;
2881 struct l2cap_conn_param_update_req *req;
2882 struct l2cap_conn_param_update_rsp rsp;
2883 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002884 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002885
2886 if (!(hcon->link_mode & HCI_LM_MASTER))
2887 return -EINVAL;
2888
2889 cmd_len = __le16_to_cpu(cmd->len);
2890 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2891 return -EPROTO;
2892
2893 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002894 min = __le16_to_cpu(req->min);
2895 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002896 latency = __le16_to_cpu(req->latency);
2897 to_multiplier = __le16_to_cpu(req->to_multiplier);
2898
2899 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2900 min, max, latency, to_multiplier);
2901
2902 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002903
2904 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2905 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002906 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2907 else
2908 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2909
2910 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2911 sizeof(rsp), &rsp);
2912
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002913 if (!err)
2914 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2915
Claudio Takahaside731152011-02-11 19:28:55 -02002916 return 0;
2917}
2918
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002919static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2920 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2921{
2922 int err = 0;
2923
2924 switch (cmd->code) {
2925 case L2CAP_COMMAND_REJ:
2926 l2cap_command_rej(conn, cmd, data);
2927 break;
2928
2929 case L2CAP_CONN_REQ:
2930 err = l2cap_connect_req(conn, cmd, data);
2931 break;
2932
2933 case L2CAP_CONN_RSP:
2934 err = l2cap_connect_rsp(conn, cmd, data);
2935 break;
2936
2937 case L2CAP_CONF_REQ:
2938 err = l2cap_config_req(conn, cmd, cmd_len, data);
2939 break;
2940
2941 case L2CAP_CONF_RSP:
2942 err = l2cap_config_rsp(conn, cmd, data);
2943 break;
2944
2945 case L2CAP_DISCONN_REQ:
2946 err = l2cap_disconnect_req(conn, cmd, data);
2947 break;
2948
2949 case L2CAP_DISCONN_RSP:
2950 err = l2cap_disconnect_rsp(conn, cmd, data);
2951 break;
2952
2953 case L2CAP_ECHO_REQ:
2954 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2955 break;
2956
2957 case L2CAP_ECHO_RSP:
2958 break;
2959
2960 case L2CAP_INFO_REQ:
2961 err = l2cap_information_req(conn, cmd, data);
2962 break;
2963
2964 case L2CAP_INFO_RSP:
2965 err = l2cap_information_rsp(conn, cmd, data);
2966 break;
2967
2968 default:
2969 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2970 err = -EINVAL;
2971 break;
2972 }
2973
2974 return err;
2975}
2976
2977static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2978 struct l2cap_cmd_hdr *cmd, u8 *data)
2979{
2980 switch (cmd->code) {
2981 case L2CAP_COMMAND_REJ:
2982 return 0;
2983
2984 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002985 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002986
2987 case L2CAP_CONN_PARAM_UPDATE_RSP:
2988 return 0;
2989
2990 default:
2991 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2992 return -EINVAL;
2993 }
2994}
2995
2996static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2997 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998{
2999 u8 *data = skb->data;
3000 int len = skb->len;
3001 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003002 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003
3004 l2cap_raw_recv(conn, skb);
3005
3006 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003007 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3009 data += L2CAP_CMD_HDR_SIZE;
3010 len -= L2CAP_CMD_HDR_SIZE;
3011
Al Viro88219a02007-07-29 00:17:25 -07003012 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013
Al Viro88219a02007-07-29 00:17:25 -07003014 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 -07003015
Al Viro88219a02007-07-29 00:17:25 -07003016 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 BT_DBG("corrupted command");
3018 break;
3019 }
3020
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003021 if (conn->hcon->type == LE_LINK)
3022 err = l2cap_le_sig_cmd(conn, &cmd, data);
3023 else
3024 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025
3026 if (err) {
3027 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003028
3029 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030
3031 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003032 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3034 }
3035
Al Viro88219a02007-07-29 00:17:25 -07003036 data += cmd_len;
3037 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038 }
3039
3040 kfree_skb(skb);
3041}
3042
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003043static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003044{
3045 u16 our_fcs, rcv_fcs;
3046 int hdr_size = L2CAP_HDR_SIZE + 2;
3047
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003048 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003049 skb_trim(skb, skb->len - 2);
3050 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3051 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3052
3053 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003054 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003055 }
3056 return 0;
3057}
3058
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003059static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003060{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003061 u16 control = 0;
3062
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003063 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003064
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003065 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003066
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003067 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003068 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003069 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003070 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003071 }
3072
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003073 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003074 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003075
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003076 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003077
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003078 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003079 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003080 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003081 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003082 }
3083}
3084
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003085static 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 -03003086{
3087 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003088 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003089
3090 bt_cb(skb)->tx_seq = tx_seq;
3091 bt_cb(skb)->sar = sar;
3092
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003093 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003094 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003095 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003096 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003097 }
3098
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003099 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003100 if (tx_seq_offset < 0)
3101 tx_seq_offset += 64;
3102
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003103 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003104 if (bt_cb(next_skb)->tx_seq == tx_seq)
3105 return -EINVAL;
3106
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003107 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003108 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003109 if (next_tx_seq_offset < 0)
3110 next_tx_seq_offset += 64;
3111
3112 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003113 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003114 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003115 }
3116
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003117 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003118 break;
3119
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003120 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003121
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003122 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003123
3124 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003125}
3126
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003127static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003128{
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003129 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003130 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003131
3132 switch (control & L2CAP_CTRL_SAR) {
3133 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003134 if (test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003135 goto drop;
3136
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003137 return chan->ops->recv(chan->data, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003138
3139 case L2CAP_SDU_START:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003140 if (test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003141 goto drop;
3142
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003143 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003144
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003145 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003146 goto disconnect;
3147
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003148 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3149 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003150 return -ENOMEM;
3151
3152 /* pull sdu_len bytes only after alloc, because of Local Busy
3153 * condition we have to be sure that this will be executed
3154 * only once, i.e., when alloc does not fail */
3155 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003156
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003157 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003158
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003159 set_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003160 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003161 break;
3162
3163 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003164 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003165 goto disconnect;
3166
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003167 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003168 goto disconnect;
3169
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003170 chan->partial_sdu_len += skb->len;
3171 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003172 goto drop;
3173
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003174 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003175
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003176 break;
3177
3178 case L2CAP_SDU_END:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003179 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003180 goto disconnect;
3181
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003182 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003183 goto disconnect;
3184
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003185 if (!test_bit(CONN_SAR_RETRY, &chan->conn_state)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003186 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003187
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003188 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003189 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003190
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003191 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003192 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003193
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003194 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003195 }
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. Padovane2ab4352011-06-10 21:28:49 -03003199 set_bit(CONN_SAR_RETRY, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003200 return -ENOMEM;
3201 }
3202
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003203 err = chan->ops->recv(chan->data, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003204 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003205 kfree_skb(_skb);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003206 set_bit(CONN_SAR_RETRY, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003207 return err;
3208 }
3209
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003210 clear_bit(CONN_SAR_RETRY, &chan->conn_state);
3211 clear_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003212
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003213 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003214 break;
3215 }
3216
3217 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003218 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003219
3220drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003221 kfree_skb(chan->sdu);
3222 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003223
3224disconnect:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003225 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003226 kfree_skb(skb);
3227 return 0;
3228}
3229
Mat Martineau26f880d2011-07-07 09:39:01 -07003230static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003231{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003232 u16 control;
3233
Mat Martineau26f880d2011-07-07 09:39:01 -07003234 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003235
Mat Martineau26f880d2011-07-07 09:39:01 -07003236 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3237
3238 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3239 control |= L2CAP_SUPER_RCV_NOT_READY;
3240 l2cap_send_sframe(chan, control);
3241
3242 set_bit(CONN_RNR_SENT, &chan->conn_state);
3243
3244 __clear_ack_timer(chan);
3245}
3246
3247static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3248{
3249 u16 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003250
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003251 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003252 goto done;
3253
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003254 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003255 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003256 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003257 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003258
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003259 __clear_retrans_timer(chan);
3260 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003261
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003262 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003263
3264done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003265 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3266 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003267
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003268 BT_DBG("chan %p, Exit local busy", chan);
Mat Martineau26f880d2011-07-07 09:39:01 -07003269}
3270
3271static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
3272{
3273 struct sk_buff *skb;
3274 u16 control;
3275 int err;
3276
3277 while ((skb = skb_dequeue(&chan->busy_q))) {
3278 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
3279 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
3280 if (err < 0) {
3281 skb_queue_head(&chan->busy_q, skb);
3282 return -EBUSY;
3283 }
3284
3285 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
3286 }
3287
3288 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003289
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003290 return 0;
3291}
3292
3293static void l2cap_busy_work(struct work_struct *work)
3294{
3295 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003296 struct l2cap_chan *chan =
3297 container_of(work, struct l2cap_chan, busy_work);
3298 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003299 int n_tries = 0, timeo = HZ/5, err;
3300 struct sk_buff *skb;
3301
3302 lock_sock(sk);
3303
3304 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003305 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003306 set_current_state(TASK_INTERRUPTIBLE);
3307
3308 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3309 err = -EBUSY;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003310 l2cap_send_disconn_req(chan->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003311 break;
3312 }
3313
3314 if (!timeo)
3315 timeo = HZ/5;
3316
3317 if (signal_pending(current)) {
3318 err = sock_intr_errno(timeo);
3319 break;
3320 }
3321
3322 release_sock(sk);
3323 timeo = schedule_timeout(timeo);
3324 lock_sock(sk);
3325
3326 err = sock_error(sk);
3327 if (err)
3328 break;
3329
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003330 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003331 break;
3332 }
3333
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003334 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003335 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003336
3337 release_sock(sk);
3338}
3339
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003340static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003341{
Mat Martineau26f880d2011-07-07 09:39:01 -07003342 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003343
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003344 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003345 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003346 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003347 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003348
3349
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003350 }
3351
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003352 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003353 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003354 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003355 return err;
3356 }
3357
Mat Martineau26f880d2011-07-07 09:39:01 -07003358 l2cap_ertm_enter_local_busy(chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003359
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003360 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003361 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003362
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003363 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003364
3365 return err;
3366}
3367
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003368static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003369{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003370 struct sk_buff *_skb;
3371 int err = -EINVAL;
3372
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003373 /*
3374 * TODO: We have to notify the userland if some data is lost with the
3375 * Streaming Mode.
3376 */
3377
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003378 switch (control & L2CAP_CTRL_SAR) {
3379 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003380 if (test_bit(CONN_SAR_SDU, &chan->conn_state)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003381 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003382 break;
3383 }
3384
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003385 err = chan->ops->recv(chan->data, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003386 if (!err)
3387 return 0;
3388
3389 break;
3390
3391 case L2CAP_SDU_START:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003392 if (test_bit(CONN_SAR_SDU, &chan->conn_state)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003393 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003394 break;
3395 }
3396
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003397 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003398 skb_pull(skb, 2);
3399
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003400 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003401 err = -EMSGSIZE;
3402 break;
3403 }
3404
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003405 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3406 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003407 err = -ENOMEM;
3408 break;
3409 }
3410
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003411 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003412
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003413 set_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003414 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003415 err = 0;
3416 break;
3417
3418 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003419 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003420 break;
3421
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003422 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003423
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003424 chan->partial_sdu_len += skb->len;
3425 if (chan->partial_sdu_len > chan->sdu_len)
3426 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003427 else
3428 err = 0;
3429
3430 break;
3431
3432 case L2CAP_SDU_END:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003433 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003434 break;
3435
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003436 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003437
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003438 clear_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003439 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003440
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003441 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003442 goto drop;
3443
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003444 if (chan->partial_sdu_len == chan->sdu_len) {
3445 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003446 err = chan->ops->recv(chan->data, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003447 if (err < 0)
3448 kfree_skb(_skb);
3449 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003450 err = 0;
3451
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003452drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003453 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003454 break;
3455 }
3456
3457 kfree_skb(skb);
3458 return err;
3459}
3460
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003461static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003462{
3463 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003464 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003465
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003466 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003467 if (bt_cb(skb)->tx_seq != tx_seq)
3468 break;
3469
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003470 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003471 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003472 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003473 chan->buffer_seq_srej =
3474 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003475 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003476 }
3477}
3478
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003479static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003480{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003481 struct srej_list *l, *tmp;
3482 u16 control;
3483
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003484 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003485 if (l->tx_seq == tx_seq) {
3486 list_del(&l->list);
3487 kfree(l);
3488 return;
3489 }
3490 control = L2CAP_SUPER_SELECT_REJECT;
3491 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003492 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003493 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003494 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003495 }
3496}
3497
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003498static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003499{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003500 struct srej_list *new;
3501 u16 control;
3502
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003503 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003504 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003505 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003506 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003507
3508 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003509 new->tx_seq = chan->expected_tx_seq;
3510 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003511 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003512 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003513 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003514}
3515
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003516static 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 -03003517{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003518 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003519 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003520 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003521 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003522 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003523 int err = 0;
3524
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003525 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3526 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003527
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003528 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003529 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003530 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003531 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003532 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003533 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003534 }
3535
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003536 chan->expected_ack_seq = req_seq;
3537 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003538
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003539 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003540 if (tx_seq_offset < 0)
3541 tx_seq_offset += 64;
3542
3543 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003544 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003545 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003546 goto drop;
3547 }
3548
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003549 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003550 goto drop;
3551
Mat Martineau02f1b642011-06-29 14:35:19 -07003552 if (tx_seq == chan->expected_tx_seq)
3553 goto expected;
3554
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003555 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003556 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003557
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003558 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003559 struct srej_list, list);
3560 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003561 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003562 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003563
3564 list_del(&first->list);
3565 kfree(first);
3566
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003567 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003568 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003569 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003570 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003571 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003572 }
3573 } else {
3574 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003575
3576 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003577 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003578 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003579
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003580 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003581 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003582 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003583 return 0;
3584 }
3585 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003586 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003587 }
3588 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003589 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003590 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003591 if (expected_tx_seq_offset < 0)
3592 expected_tx_seq_offset += 64;
3593
3594 /* duplicated tx_seq */
3595 if (tx_seq_offset < expected_tx_seq_offset)
3596 goto drop;
3597
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003598 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003599
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003600 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003601
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003602 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003603 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003604
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003605 __skb_queue_head_init(&chan->srej_q);
3606 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003607 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003608
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003609 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003610
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003611 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003612
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003613 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003614 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003615 return 0;
3616
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003617expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003618 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003619
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003620 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003621 bt_cb(skb)->tx_seq = tx_seq;
3622 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003623 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003624 return 0;
3625 }
3626
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003627 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003628 if (err < 0)
3629 return 0;
3630
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003631 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003632 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003633 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003634 }
3635
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003636 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003637
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003638 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3639 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003640 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003641
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003642 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003643
3644drop:
3645 kfree_skb(skb);
3646 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003647}
3648
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003649static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003650{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003651 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003652 rx_control);
3653
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003654 chan->expected_ack_seq = __get_reqseq(rx_control);
3655 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003656
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003657 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003658 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3659 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3660 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003661 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003662 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003663
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003664 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003665 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003666 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003667 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003668 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003669
3670 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003671 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003672
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003673 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003674 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003675
3676 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003677 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003678 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003679 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003680
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003681 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3682 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003683 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003684 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003685 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003686 }
3687}
3688
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003689static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003690{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003691 u8 tx_seq = __get_reqseq(rx_control);
3692
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003693 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003694
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003695 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003696
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003697 chan->expected_ack_seq = tx_seq;
3698 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003699
3700 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003701 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003702 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003703 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003704 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003705
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003706 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3707 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003708 }
3709}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003710static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003711{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003712 u8 tx_seq = __get_reqseq(rx_control);
3713
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003714 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003715
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003716 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003717
3718 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003719 chan->expected_ack_seq = tx_seq;
3720 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003721
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003722 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003723 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003724
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003725 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003726
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003727 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003728 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003729 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003730 }
3731 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003732 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003733 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003734 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003735 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003736 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003737 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003738 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003739 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003740 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003741 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003742 }
3743 }
3744}
3745
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003746static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003747{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003748 u8 tx_seq = __get_reqseq(rx_control);
3749
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003750 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003751
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003752 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003753 chan->expected_ack_seq = tx_seq;
3754 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003755
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003756 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003757 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003758
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003759 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003760 __clear_retrans_timer(chan);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003761 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003762 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003763 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003764 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003765
3766 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003767 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003768 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003769 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003770}
3771
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003772static 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 -03003773{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003774 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003775
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003776 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003777 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003778 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003779 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003780 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003781 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003782 }
3783
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003784 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3785 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003786 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003787 break;
3788
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003789 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003790 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003791 break;
3792
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003793 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003794 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003795 break;
3796
3797 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003798 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003799 break;
3800 }
3801
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003802 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003803 return 0;
3804}
3805
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003806static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3807{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003808 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003809 u16 control;
3810 u8 req_seq;
3811 int len, next_tx_seq_offset, req_seq_offset;
3812
3813 control = get_unaligned_le16(skb->data);
3814 skb_pull(skb, 2);
3815 len = skb->len;
3816
3817 /*
3818 * We can just drop the corrupted I-frame here.
3819 * Receiver will miss it and start proper recovery
3820 * procedures and ask retransmission.
3821 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003822 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003823 goto drop;
3824
3825 if (__is_sar_start(control) && __is_iframe(control))
3826 len -= 2;
3827
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003828 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003829 len -= 2;
3830
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003831 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003832 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003833 goto drop;
3834 }
3835
3836 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003837 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003838 if (req_seq_offset < 0)
3839 req_seq_offset += 64;
3840
3841 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003842 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003843 if (next_tx_seq_offset < 0)
3844 next_tx_seq_offset += 64;
3845
3846 /* check for invalid req-seq */
3847 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003848 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003849 goto drop;
3850 }
3851
3852 if (__is_iframe(control)) {
3853 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003854 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003855 goto drop;
3856 }
3857
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003858 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003859 } else {
3860 if (len != 0) {
3861 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003862 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003863 goto drop;
3864 }
3865
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003866 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003867 }
3868
3869 return 0;
3870
3871drop:
3872 kfree_skb(skb);
3873 return 0;
3874}
3875
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3877{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003878 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003879 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003880 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003881 u8 tx_seq;
3882 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003884 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003885 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003886 BT_DBG("unknown cid 0x%4.4x", cid);
3887 goto drop;
3888 }
3889
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003890 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003891
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003892 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003894 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895 goto drop;
3896
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003897 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003898 case L2CAP_MODE_BASIC:
3899 /* If socket recv buffers overflows we drop data here
3900 * which is *bad* because L2CAP has to be reliable.
3901 * But we don't have any other choice. L2CAP doesn't
3902 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003904 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003905 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003906
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003907 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003908 goto done;
3909 break;
3910
3911 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003912 if (!sock_owned_by_user(sk)) {
3913 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003914 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003915 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003916 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003917 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003918
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003919 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003920
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003921 case L2CAP_MODE_STREAMING:
3922 control = get_unaligned_le16(skb->data);
3923 skb_pull(skb, 2);
3924 len = skb->len;
3925
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003926 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003927 goto drop;
3928
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003929 if (__is_sar_start(control))
3930 len -= 2;
3931
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003932 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003933 len -= 2;
3934
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003935 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003936 goto drop;
3937
3938 tx_seq = __get_txseq(control);
3939
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003940 if (chan->expected_tx_seq == tx_seq)
3941 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003942 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003943 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003944
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003945 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003946
3947 goto done;
3948
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003949 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003950 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003951 break;
3952 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953
3954drop:
3955 kfree_skb(skb);
3956
3957done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003958 if (sk)
3959 bh_unlock_sock(sk);
3960
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961 return 0;
3962}
3963
Al Viro8e036fc2007-07-29 00:16:36 -07003964static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003966 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003967 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003969 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3970 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003971 goto drop;
3972
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003973 sk = chan->sk;
3974
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003975 bh_lock_sock(sk);
3976
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977 BT_DBG("sk %p, len %d", sk, skb->len);
3978
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003979 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980 goto drop;
3981
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003982 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983 goto drop;
3984
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003985 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986 goto done;
3987
3988drop:
3989 kfree_skb(skb);
3990
3991done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003992 if (sk)
3993 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994 return 0;
3995}
3996
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003997static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3998{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003999 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004000 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004001
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004002 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4003 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004004 goto drop;
4005
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004006 sk = chan->sk;
4007
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004008 bh_lock_sock(sk);
4009
4010 BT_DBG("sk %p, len %d", sk, skb->len);
4011
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004012 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004013 goto drop;
4014
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004015 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004016 goto drop;
4017
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004018 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004019 goto done;
4020
4021drop:
4022 kfree_skb(skb);
4023
4024done:
4025 if (sk)
4026 bh_unlock_sock(sk);
4027 return 0;
4028}
4029
Linus Torvalds1da177e2005-04-16 15:20:36 -07004030static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4031{
4032 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004033 u16 cid, len;
4034 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035
4036 skb_pull(skb, L2CAP_HDR_SIZE);
4037 cid = __le16_to_cpu(lh->cid);
4038 len = __le16_to_cpu(lh->len);
4039
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004040 if (len != skb->len) {
4041 kfree_skb(skb);
4042 return;
4043 }
4044
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4046
4047 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004048 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004049 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004050 l2cap_sig_channel(conn, skb);
4051 break;
4052
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004053 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004054 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055 skb_pull(skb, 2);
4056 l2cap_conless_channel(conn, psm, skb);
4057 break;
4058
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004059 case L2CAP_CID_LE_DATA:
4060 l2cap_att_channel(conn, cid, skb);
4061 break;
4062
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004063 case L2CAP_CID_SMP:
4064 if (smp_sig_channel(conn, skb))
4065 l2cap_conn_del(conn->hcon, EACCES);
4066 break;
4067
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068 default:
4069 l2cap_data_channel(conn, cid, skb);
4070 break;
4071 }
4072}
4073
4074/* ---- L2CAP interface with lower layer (HCI) ---- */
4075
4076static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4077{
4078 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004079 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080
4081 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004082 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083
4084 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4085
4086 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004087 read_lock(&chan_list_lock);
4088 list_for_each_entry(c, &chan_list, global_l) {
4089 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004090
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004091 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092 continue;
4093
4094 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004095 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004096 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004097 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004099 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4100 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004101 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004102 lm2 |= HCI_LM_MASTER;
4103 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004105 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106
4107 return exact ? lm1 : lm2;
4108}
4109
4110static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4111{
Marcel Holtmann01394182006-07-03 10:02:46 +02004112 struct l2cap_conn *conn;
4113
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4115
Ville Tervoacd7d372011-02-10 22:38:49 -03004116 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004117 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118
4119 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120 conn = l2cap_conn_add(hcon, status);
4121 if (conn)
4122 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004123 } else
Joe Perchese1750722011-06-29 18:18:29 -07004124 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125
4126 return 0;
4127}
4128
Marcel Holtmann2950f212009-02-12 14:02:50 +01004129static int l2cap_disconn_ind(struct hci_conn *hcon)
4130{
4131 struct l2cap_conn *conn = hcon->l2cap_data;
4132
4133 BT_DBG("hcon %p", hcon);
4134
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03004135 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004136 return 0x13;
4137
4138 return conn->disc_reason;
4139}
4140
4141static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142{
4143 BT_DBG("hcon %p reason %d", hcon, reason);
4144
Ville Tervoacd7d372011-02-10 22:38:49 -03004145 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004146 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147
Joe Perchese1750722011-06-29 18:18:29 -07004148 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004149
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150 return 0;
4151}
4152
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004153static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004154{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004155 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004156 return;
4157
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004158 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004159 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004160 __clear_chan_timer(chan);
4161 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004162 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004163 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004164 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004165 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004166 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004167 }
4168}
4169
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004170static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004172 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004173 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004174
Marcel Holtmann01394182006-07-03 10:02:46 +02004175 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004177
Linus Torvalds1da177e2005-04-16 15:20:36 -07004178 BT_DBG("conn %p", conn);
4179
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004180 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004181
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004182 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004183 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004184
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185 bh_lock_sock(sk);
4186
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004187 BT_DBG("chan->scid %d", chan->scid);
4188
4189 if (chan->scid == L2CAP_CID_LE_DATA) {
4190 if (!status && encrypt) {
4191 chan->sec_level = hcon->sec_level;
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03004192 del_timer(&conn->security_timer);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004193 l2cap_chan_ready(sk);
4194 }
4195
4196 bh_unlock_sock(sk);
4197 continue;
4198 }
4199
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004200 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004201 bh_unlock_sock(sk);
4202 continue;
4203 }
4204
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004205 if (!status && (chan->state == BT_CONNECTED ||
4206 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004207 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004208 bh_unlock_sock(sk);
4209 continue;
4210 }
4211
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004212 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004213 if (!status) {
4214 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004215 req.scid = cpu_to_le16(chan->scid);
4216 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004217
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004218 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004219 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004220
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004221 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004222 L2CAP_CONN_REQ, sizeof(req), &req);
4223 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004224 __clear_chan_timer(chan);
4225 __set_chan_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004226 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004227 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004228 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004229 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004230
4231 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004232 if (bt_sk(sk)->defer_setup) {
4233 struct sock *parent = bt_sk(sk)->parent;
4234 res = L2CAP_CR_PEND;
4235 stat = L2CAP_CS_AUTHOR_PEND;
4236 parent->sk_data_ready(parent, 0);
4237 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004238 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004239 res = L2CAP_CR_SUCCESS;
4240 stat = L2CAP_CS_NO_INFO;
4241 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004242 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004243 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004244 __set_chan_timer(chan, HZ / 10);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004245 res = L2CAP_CR_SEC_BLOCK;
4246 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004247 }
4248
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004249 rsp.scid = cpu_to_le16(chan->dcid);
4250 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004251 rsp.result = cpu_to_le16(res);
4252 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004253 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4254 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004255 }
4256
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257 bh_unlock_sock(sk);
4258 }
4259
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004260 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004261
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262 return 0;
4263}
4264
4265static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4266{
4267 struct l2cap_conn *conn = hcon->l2cap_data;
4268
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004269 if (!conn)
4270 conn = l2cap_conn_add(hcon, 0);
4271
4272 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273 goto drop;
4274
4275 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4276
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004277 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004279 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004280 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004281 int len;
4282
4283 if (conn->rx_len) {
4284 BT_ERR("Unexpected start frame (len %d)", skb->len);
4285 kfree_skb(conn->rx_skb);
4286 conn->rx_skb = NULL;
4287 conn->rx_len = 0;
4288 l2cap_conn_unreliable(conn, ECOMM);
4289 }
4290
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004291 /* Start fragment always begin with Basic L2CAP header */
4292 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293 BT_ERR("Frame is too short (len %d)", skb->len);
4294 l2cap_conn_unreliable(conn, ECOMM);
4295 goto drop;
4296 }
4297
4298 hdr = (struct l2cap_hdr *) skb->data;
4299 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004300 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301
4302 if (len == skb->len) {
4303 /* Complete frame received */
4304 l2cap_recv_frame(conn, skb);
4305 return 0;
4306 }
4307
4308 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4309
4310 if (skb->len > len) {
4311 BT_ERR("Frame is too long (len %d, expected len %d)",
4312 skb->len, len);
4313 l2cap_conn_unreliable(conn, ECOMM);
4314 goto drop;
4315 }
4316
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004317 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004318
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004319 if (chan && chan->sk) {
4320 struct sock *sk = chan->sk;
4321
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004322 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004323 BT_ERR("Frame exceeding recv MTU (len %d, "
4324 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004325 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004326 bh_unlock_sock(sk);
4327 l2cap_conn_unreliable(conn, ECOMM);
4328 goto drop;
4329 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004330 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004331 }
4332
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004334 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4335 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336 goto drop;
4337
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004338 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004339 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004340 conn->rx_len = len - skb->len;
4341 } else {
4342 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4343
4344 if (!conn->rx_len) {
4345 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4346 l2cap_conn_unreliable(conn, ECOMM);
4347 goto drop;
4348 }
4349
4350 if (skb->len > conn->rx_len) {
4351 BT_ERR("Fragment is too long (len %d, expected %d)",
4352 skb->len, conn->rx_len);
4353 kfree_skb(conn->rx_skb);
4354 conn->rx_skb = NULL;
4355 conn->rx_len = 0;
4356 l2cap_conn_unreliable(conn, ECOMM);
4357 goto drop;
4358 }
4359
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004360 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004361 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004362 conn->rx_len -= skb->len;
4363
4364 if (!conn->rx_len) {
4365 /* Complete frame received */
4366 l2cap_recv_frame(conn, conn->rx_skb);
4367 conn->rx_skb = NULL;
4368 }
4369 }
4370
4371drop:
4372 kfree_skb(skb);
4373 return 0;
4374}
4375
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004376static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004378 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004379
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004380 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004381
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004382 list_for_each_entry(c, &chan_list, global_l) {
4383 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004385 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 +01004386 batostr(&bt_sk(sk)->src),
4387 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004388 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004389 c->scid, c->dcid, c->imtu, c->omtu,
4390 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004391}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004393 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004394
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004395 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396}
4397
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004398static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4399{
4400 return single_open(file, l2cap_debugfs_show, inode->i_private);
4401}
4402
4403static const struct file_operations l2cap_debugfs_fops = {
4404 .open = l2cap_debugfs_open,
4405 .read = seq_read,
4406 .llseek = seq_lseek,
4407 .release = single_release,
4408};
4409
4410static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004411
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412static struct hci_proto l2cap_hci_proto = {
4413 .name = "L2CAP",
4414 .id = HCI_PROTO_L2CAP,
4415 .connect_ind = l2cap_connect_ind,
4416 .connect_cfm = l2cap_connect_cfm,
4417 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004418 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004419 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420 .recv_acldata = l2cap_recv_acldata
4421};
4422
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004423int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424{
4425 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004426
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004427 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428 if (err < 0)
4429 return err;
4430
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004431 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004432 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004433 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434 goto error;
4435 }
4436
4437 err = hci_register_proto(&l2cap_hci_proto);
4438 if (err < 0) {
4439 BT_ERR("L2CAP protocol registration failed");
4440 bt_sock_unregister(BTPROTO_L2CAP);
4441 goto error;
4442 }
4443
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004444 if (bt_debugfs) {
4445 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4446 bt_debugfs, NULL, &l2cap_debugfs_fops);
4447 if (!l2cap_debugfs)
4448 BT_ERR("Failed to create L2CAP debug file");
4449 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004450
Linus Torvalds1da177e2005-04-16 15:20:36 -07004451 return 0;
4452
4453error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004454 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004455 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456 return err;
4457}
4458
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004459void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004460{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004461 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004462
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004463 flush_workqueue(_busy_wq);
4464 destroy_workqueue(_busy_wq);
4465
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4467 BT_ERR("L2CAP protocol unregistration failed");
4468
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004469 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470}
4471
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004472module_param(disable_ertm, bool, 0644);
4473MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");