blob: ea9c7d06104617c3df9eb234b090eda1b4d5437b [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);
Mat Martineaue3281402011-07-07 09:39:02 -07003353 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003354
3355 return err;
3356}
3357
Mat Martineaue3281402011-07-07 09:39:02 -07003358void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
3359{
3360 if (chan->mode == L2CAP_MODE_ERTM) {
3361 if (busy)
3362 l2cap_ertm_enter_local_busy(chan);
3363 else
3364 l2cap_ertm_exit_local_busy(chan);
3365 }
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
Mat Martineaue3281402011-07-07 09:39:02 -07003466 while ((skb = skb_peek(&chan->srej_q)) &&
3467 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3468 int err;
3469
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003470 if (bt_cb(skb)->tx_seq != tx_seq)
3471 break;
3472
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003473 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003474 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Mat Martineaue3281402011-07-07 09:39:02 -07003475 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
3476
3477 if (err < 0) {
3478 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3479 break;
3480 }
3481
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003482 chan->buffer_seq_srej =
3483 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003484 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003485 }
3486}
3487
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003488static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003489{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003490 struct srej_list *l, *tmp;
3491 u16 control;
3492
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003493 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003494 if (l->tx_seq == tx_seq) {
3495 list_del(&l->list);
3496 kfree(l);
3497 return;
3498 }
3499 control = L2CAP_SUPER_SELECT_REJECT;
3500 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003501 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003502 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003503 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003504 }
3505}
3506
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003507static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003508{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003509 struct srej_list *new;
3510 u16 control;
3511
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003512 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003513 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003514 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003515 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003516
3517 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003518 new->tx_seq = chan->expected_tx_seq;
3519 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003520 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003521 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003522 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003523}
3524
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003525static 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 -03003526{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003527 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003528 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003529 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003530 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003531 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003532 int err = 0;
3533
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003534 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3535 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003536
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003537 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003538 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003539 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003540 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003541 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003542 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003543 }
3544
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003545 chan->expected_ack_seq = req_seq;
3546 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003547
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003548 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003549 if (tx_seq_offset < 0)
3550 tx_seq_offset += 64;
3551
3552 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003553 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003554 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003555 goto drop;
3556 }
3557
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003558 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003559 goto drop;
3560
Mat Martineau02f1b642011-06-29 14:35:19 -07003561 if (tx_seq == chan->expected_tx_seq)
3562 goto expected;
3563
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003564 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003565 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003566
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003567 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003568 struct srej_list, list);
3569 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003570 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003571 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003572
3573 list_del(&first->list);
3574 kfree(first);
3575
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003576 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003577 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003578 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003579 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003580 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003581 }
3582 } else {
3583 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003584
3585 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003586 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003587 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003588
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003589 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003590 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003591 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003592 return 0;
3593 }
3594 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003595 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003596 }
3597 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003598 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003599 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003600 if (expected_tx_seq_offset < 0)
3601 expected_tx_seq_offset += 64;
3602
3603 /* duplicated tx_seq */
3604 if (tx_seq_offset < expected_tx_seq_offset)
3605 goto drop;
3606
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003607 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003608
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003609 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003610
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003611 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003612 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003613
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003614 __skb_queue_head_init(&chan->srej_q);
3615 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003616 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003617
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003618 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003619
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003620 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003621
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003622 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003623 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003624 return 0;
3625
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003626expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003627 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003628
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003629 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003630 bt_cb(skb)->tx_seq = tx_seq;
3631 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003632 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003633 return 0;
3634 }
3635
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003636 err = l2cap_push_rx_skb(chan, skb, rx_control);
Mat Martineaue3281402011-07-07 09:39:02 -07003637 if (err < 0) {
3638 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3639 return err;
3640 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003641
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003642 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003643 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003644 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003645 }
3646
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003647 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003648
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003649 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3650 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003651 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003652
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003653 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003654
3655drop:
3656 kfree_skb(skb);
3657 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003658}
3659
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003660static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003661{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003662 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003663 rx_control);
3664
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003665 chan->expected_ack_seq = __get_reqseq(rx_control);
3666 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003667
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003668 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003669 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3670 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3671 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003672 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003673 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003674
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003675 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003676 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003677 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003678 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003679 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003680
3681 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003682 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003683
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003684 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003685 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003686
3687 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003688 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003689 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003690 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003691
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003692 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3693 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003694 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003695 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003696 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003697 }
3698}
3699
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003700static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003701{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003702 u8 tx_seq = __get_reqseq(rx_control);
3703
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003704 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003705
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003706 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003707
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003708 chan->expected_ack_seq = tx_seq;
3709 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003710
3711 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003712 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003713 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003714 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003715 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003716
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003717 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3718 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003719 }
3720}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003721static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003722{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003723 u8 tx_seq = __get_reqseq(rx_control);
3724
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003725 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003726
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003727 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003728
3729 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003730 chan->expected_ack_seq = tx_seq;
3731 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003732
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003733 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003734 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003735
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003736 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003737
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003738 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003739 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003740 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003741 }
3742 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003743 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003744 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003745 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003746 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003747 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003748 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003749 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003750 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003751 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003752 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003753 }
3754 }
3755}
3756
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003757static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003758{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003759 u8 tx_seq = __get_reqseq(rx_control);
3760
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003761 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003762
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003763 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003764 chan->expected_ack_seq = tx_seq;
3765 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003766
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003767 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003768 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003769
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003770 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003771 __clear_retrans_timer(chan);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003772 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003773 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003774 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003775 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003776
3777 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003778 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003779 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003780 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003781}
3782
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003783static 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 -03003784{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003785 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003786
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003787 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003788 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003789 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003790 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003791 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003792 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003793 }
3794
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003795 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3796 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003797 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003798 break;
3799
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003800 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003801 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003802 break;
3803
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003804 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003805 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003806 break;
3807
3808 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003809 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003810 break;
3811 }
3812
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003813 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003814 return 0;
3815}
3816
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003817static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3818{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003819 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003820 u16 control;
3821 u8 req_seq;
3822 int len, next_tx_seq_offset, req_seq_offset;
3823
3824 control = get_unaligned_le16(skb->data);
3825 skb_pull(skb, 2);
3826 len = skb->len;
3827
3828 /*
3829 * We can just drop the corrupted I-frame here.
3830 * Receiver will miss it and start proper recovery
3831 * procedures and ask retransmission.
3832 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003833 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003834 goto drop;
3835
3836 if (__is_sar_start(control) && __is_iframe(control))
3837 len -= 2;
3838
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003839 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003840 len -= 2;
3841
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003842 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003843 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003844 goto drop;
3845 }
3846
3847 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003848 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003849 if (req_seq_offset < 0)
3850 req_seq_offset += 64;
3851
3852 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003853 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003854 if (next_tx_seq_offset < 0)
3855 next_tx_seq_offset += 64;
3856
3857 /* check for invalid req-seq */
3858 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003859 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003860 goto drop;
3861 }
3862
3863 if (__is_iframe(control)) {
3864 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003865 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003866 goto drop;
3867 }
3868
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003869 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003870 } else {
3871 if (len != 0) {
3872 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003873 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003874 goto drop;
3875 }
3876
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003877 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003878 }
3879
3880 return 0;
3881
3882drop:
3883 kfree_skb(skb);
3884 return 0;
3885}
3886
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3888{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003889 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003890 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003891 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003892 u8 tx_seq;
3893 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003895 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003896 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897 BT_DBG("unknown cid 0x%4.4x", cid);
3898 goto drop;
3899 }
3900
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003901 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003902
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003903 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003905 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003906 goto drop;
3907
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003908 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003909 case L2CAP_MODE_BASIC:
3910 /* If socket recv buffers overflows we drop data here
3911 * which is *bad* because L2CAP has to be reliable.
3912 * But we don't have any other choice. L2CAP doesn't
3913 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003915 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003916 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003918 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003919 goto done;
3920 break;
3921
3922 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003923 if (!sock_owned_by_user(sk)) {
3924 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003925 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003926 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003927 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003928 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003929
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003930 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003931
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003932 case L2CAP_MODE_STREAMING:
3933 control = get_unaligned_le16(skb->data);
3934 skb_pull(skb, 2);
3935 len = skb->len;
3936
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003937 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003938 goto drop;
3939
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003940 if (__is_sar_start(control))
3941 len -= 2;
3942
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003943 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003944 len -= 2;
3945
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003946 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003947 goto drop;
3948
3949 tx_seq = __get_txseq(control);
3950
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003951 if (chan->expected_tx_seq == tx_seq)
3952 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003953 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003954 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003955
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003956 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003957
3958 goto done;
3959
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003960 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003961 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003962 break;
3963 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964
3965drop:
3966 kfree_skb(skb);
3967
3968done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003969 if (sk)
3970 bh_unlock_sock(sk);
3971
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972 return 0;
3973}
3974
Al Viro8e036fc2007-07-29 00:16:36 -07003975static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003976{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003977 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003978 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003979
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003980 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3981 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982 goto drop;
3983
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003984 sk = chan->sk;
3985
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003986 bh_lock_sock(sk);
3987
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988 BT_DBG("sk %p, len %d", sk, skb->len);
3989
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003990 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991 goto drop;
3992
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003993 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994 goto drop;
3995
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003996 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003997 goto done;
3998
3999drop:
4000 kfree_skb(skb);
4001
4002done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004003 if (sk)
4004 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004005 return 0;
4006}
4007
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004008static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
4009{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004010 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004011 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004012
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004013 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4014 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004015 goto drop;
4016
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004017 sk = chan->sk;
4018
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004019 bh_lock_sock(sk);
4020
4021 BT_DBG("sk %p, len %d", sk, skb->len);
4022
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004023 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004024 goto drop;
4025
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004026 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004027 goto drop;
4028
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004029 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004030 goto done;
4031
4032drop:
4033 kfree_skb(skb);
4034
4035done:
4036 if (sk)
4037 bh_unlock_sock(sk);
4038 return 0;
4039}
4040
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4042{
4043 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004044 u16 cid, len;
4045 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046
4047 skb_pull(skb, L2CAP_HDR_SIZE);
4048 cid = __le16_to_cpu(lh->cid);
4049 len = __le16_to_cpu(lh->len);
4050
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004051 if (len != skb->len) {
4052 kfree_skb(skb);
4053 return;
4054 }
4055
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4057
4058 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004059 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004060 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061 l2cap_sig_channel(conn, skb);
4062 break;
4063
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004064 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004065 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066 skb_pull(skb, 2);
4067 l2cap_conless_channel(conn, psm, skb);
4068 break;
4069
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004070 case L2CAP_CID_LE_DATA:
4071 l2cap_att_channel(conn, cid, skb);
4072 break;
4073
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004074 case L2CAP_CID_SMP:
4075 if (smp_sig_channel(conn, skb))
4076 l2cap_conn_del(conn->hcon, EACCES);
4077 break;
4078
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079 default:
4080 l2cap_data_channel(conn, cid, skb);
4081 break;
4082 }
4083}
4084
4085/* ---- L2CAP interface with lower layer (HCI) ---- */
4086
4087static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4088{
4089 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004090 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091
4092 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004093 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094
4095 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4096
4097 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004098 read_lock(&chan_list_lock);
4099 list_for_each_entry(c, &chan_list, global_l) {
4100 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004101
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004102 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103 continue;
4104
4105 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004106 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004107 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004108 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004109 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004110 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4111 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004112 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004113 lm2 |= HCI_LM_MASTER;
4114 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004116 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117
4118 return exact ? lm1 : lm2;
4119}
4120
4121static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4122{
Marcel Holtmann01394182006-07-03 10:02:46 +02004123 struct l2cap_conn *conn;
4124
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4126
Ville Tervoacd7d372011-02-10 22:38:49 -03004127 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004128 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129
4130 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131 conn = l2cap_conn_add(hcon, status);
4132 if (conn)
4133 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004134 } else
Joe Perchese1750722011-06-29 18:18:29 -07004135 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004136
4137 return 0;
4138}
4139
Marcel Holtmann2950f212009-02-12 14:02:50 +01004140static int l2cap_disconn_ind(struct hci_conn *hcon)
4141{
4142 struct l2cap_conn *conn = hcon->l2cap_data;
4143
4144 BT_DBG("hcon %p", hcon);
4145
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03004146 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004147 return 0x13;
4148
4149 return conn->disc_reason;
4150}
4151
4152static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153{
4154 BT_DBG("hcon %p reason %d", hcon, reason);
4155
Ville Tervoacd7d372011-02-10 22:38:49 -03004156 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004157 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158
Joe Perchese1750722011-06-29 18:18:29 -07004159 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004160
Linus Torvalds1da177e2005-04-16 15:20:36 -07004161 return 0;
4162}
4163
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004164static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004165{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004166 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004167 return;
4168
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004169 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004170 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004171 __clear_chan_timer(chan);
4172 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004173 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004174 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004175 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004176 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004177 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004178 }
4179}
4180
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004181static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004183 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004184 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185
Marcel Holtmann01394182006-07-03 10:02:46 +02004186 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004187 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004188
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189 BT_DBG("conn %p", conn);
4190
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004191 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004193 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004194 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004195
Linus Torvalds1da177e2005-04-16 15:20:36 -07004196 bh_lock_sock(sk);
4197
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004198 BT_DBG("chan->scid %d", chan->scid);
4199
4200 if (chan->scid == L2CAP_CID_LE_DATA) {
4201 if (!status && encrypt) {
4202 chan->sec_level = hcon->sec_level;
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03004203 del_timer(&conn->security_timer);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004204 l2cap_chan_ready(sk);
4205 }
4206
4207 bh_unlock_sock(sk);
4208 continue;
4209 }
4210
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004211 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004212 bh_unlock_sock(sk);
4213 continue;
4214 }
4215
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004216 if (!status && (chan->state == BT_CONNECTED ||
4217 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004218 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004219 bh_unlock_sock(sk);
4220 continue;
4221 }
4222
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004223 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004224 if (!status) {
4225 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004226 req.scid = cpu_to_le16(chan->scid);
4227 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004228
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004229 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004230 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004231
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004232 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004233 L2CAP_CONN_REQ, sizeof(req), &req);
4234 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004235 __clear_chan_timer(chan);
4236 __set_chan_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004237 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004238 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004239 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004240 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004241
4242 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004243 if (bt_sk(sk)->defer_setup) {
4244 struct sock *parent = bt_sk(sk)->parent;
4245 res = L2CAP_CR_PEND;
4246 stat = L2CAP_CS_AUTHOR_PEND;
4247 parent->sk_data_ready(parent, 0);
4248 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004249 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004250 res = L2CAP_CR_SUCCESS;
4251 stat = L2CAP_CS_NO_INFO;
4252 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004253 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004254 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004255 __set_chan_timer(chan, HZ / 10);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004256 res = L2CAP_CR_SEC_BLOCK;
4257 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004258 }
4259
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004260 rsp.scid = cpu_to_le16(chan->dcid);
4261 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004262 rsp.result = cpu_to_le16(res);
4263 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004264 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4265 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266 }
4267
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268 bh_unlock_sock(sk);
4269 }
4270
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004271 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004272
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273 return 0;
4274}
4275
4276static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4277{
4278 struct l2cap_conn *conn = hcon->l2cap_data;
4279
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004280 if (!conn)
4281 conn = l2cap_conn_add(hcon, 0);
4282
4283 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004284 goto drop;
4285
4286 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4287
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004288 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004290 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004291 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004292 int len;
4293
4294 if (conn->rx_len) {
4295 BT_ERR("Unexpected start frame (len %d)", skb->len);
4296 kfree_skb(conn->rx_skb);
4297 conn->rx_skb = NULL;
4298 conn->rx_len = 0;
4299 l2cap_conn_unreliable(conn, ECOMM);
4300 }
4301
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004302 /* Start fragment always begin with Basic L2CAP header */
4303 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004304 BT_ERR("Frame is too short (len %d)", skb->len);
4305 l2cap_conn_unreliable(conn, ECOMM);
4306 goto drop;
4307 }
4308
4309 hdr = (struct l2cap_hdr *) skb->data;
4310 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004311 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312
4313 if (len == skb->len) {
4314 /* Complete frame received */
4315 l2cap_recv_frame(conn, skb);
4316 return 0;
4317 }
4318
4319 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4320
4321 if (skb->len > len) {
4322 BT_ERR("Frame is too long (len %d, expected len %d)",
4323 skb->len, len);
4324 l2cap_conn_unreliable(conn, ECOMM);
4325 goto drop;
4326 }
4327
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004328 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004329
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004330 if (chan && chan->sk) {
4331 struct sock *sk = chan->sk;
4332
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004333 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004334 BT_ERR("Frame exceeding recv MTU (len %d, "
4335 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004336 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004337 bh_unlock_sock(sk);
4338 l2cap_conn_unreliable(conn, ECOMM);
4339 goto drop;
4340 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004341 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004342 }
4343
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004345 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4346 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347 goto drop;
4348
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004349 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004350 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004351 conn->rx_len = len - skb->len;
4352 } else {
4353 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4354
4355 if (!conn->rx_len) {
4356 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4357 l2cap_conn_unreliable(conn, ECOMM);
4358 goto drop;
4359 }
4360
4361 if (skb->len > conn->rx_len) {
4362 BT_ERR("Fragment is too long (len %d, expected %d)",
4363 skb->len, conn->rx_len);
4364 kfree_skb(conn->rx_skb);
4365 conn->rx_skb = NULL;
4366 conn->rx_len = 0;
4367 l2cap_conn_unreliable(conn, ECOMM);
4368 goto drop;
4369 }
4370
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004371 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004372 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004373 conn->rx_len -= skb->len;
4374
4375 if (!conn->rx_len) {
4376 /* Complete frame received */
4377 l2cap_recv_frame(conn, conn->rx_skb);
4378 conn->rx_skb = NULL;
4379 }
4380 }
4381
4382drop:
4383 kfree_skb(skb);
4384 return 0;
4385}
4386
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004387static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004388{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004389 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004390
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004391 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004393 list_for_each_entry(c, &chan_list, global_l) {
4394 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004395
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004396 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 +01004397 batostr(&bt_sk(sk)->src),
4398 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004399 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004400 c->scid, c->dcid, c->imtu, c->omtu,
4401 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004402}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004404 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004405
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004406 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004407}
4408
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004409static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4410{
4411 return single_open(file, l2cap_debugfs_show, inode->i_private);
4412}
4413
4414static const struct file_operations l2cap_debugfs_fops = {
4415 .open = l2cap_debugfs_open,
4416 .read = seq_read,
4417 .llseek = seq_lseek,
4418 .release = single_release,
4419};
4420
4421static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422
Linus Torvalds1da177e2005-04-16 15:20:36 -07004423static struct hci_proto l2cap_hci_proto = {
4424 .name = "L2CAP",
4425 .id = HCI_PROTO_L2CAP,
4426 .connect_ind = l2cap_connect_ind,
4427 .connect_cfm = l2cap_connect_cfm,
4428 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004429 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004430 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004431 .recv_acldata = l2cap_recv_acldata
4432};
4433
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004434int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435{
4436 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004437
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004438 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439 if (err < 0)
4440 return err;
4441
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004442 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004443 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004444 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445 goto error;
4446 }
4447
4448 err = hci_register_proto(&l2cap_hci_proto);
4449 if (err < 0) {
4450 BT_ERR("L2CAP protocol registration failed");
4451 bt_sock_unregister(BTPROTO_L2CAP);
4452 goto error;
4453 }
4454
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004455 if (bt_debugfs) {
4456 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4457 bt_debugfs, NULL, &l2cap_debugfs_fops);
4458 if (!l2cap_debugfs)
4459 BT_ERR("Failed to create L2CAP debug file");
4460 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004461
Linus Torvalds1da177e2005-04-16 15:20:36 -07004462 return 0;
4463
4464error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004465 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004466 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467 return err;
4468}
4469
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004470void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004471{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004472 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004473
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004474 flush_workqueue(_busy_wq);
4475 destroy_workqueue(_busy_wq);
4476
Linus Torvalds1da177e2005-04-16 15:20:36 -07004477 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4478 BT_ERR("L2CAP protocol unregistration failed");
4479
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004480 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004481}
4482
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004483module_param(disable_ertm, bool, 0644);
4484MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");