blob: b4e927eb174eba5964d14630b2e73994973a6377 [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. Padovan710f9b0a2011-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{
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300226 BT_DBG("chan %p state %d timeout %ld", chan->sk, chan->state, timeout);
227
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300228 if (!mod_timer(timer, jiffies + timeout))
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300229 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{
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300234 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300235
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300236 if (timer_pending(timer) && del_timer(timer))
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300237 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. Padovan525cd182011-03-25 19:43:39 -0300587 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300588 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300589 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300590 }
591
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300592 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300593 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300594 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300595 }
596
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300597 skb = bt_skb_alloc(count, GFP_ATOMIC);
598 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300599 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300600
601 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300602 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300603 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300604 put_unaligned_le16(control, skb_put(skb, 2));
605
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300606 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300607 u16 fcs = crc16(0, (u8 *)lh, count - 2);
608 put_unaligned_le16(fcs, skb_put(skb, 2));
609 }
610
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200611 if (lmp_no_flush_capable(conn->hcon->hdev))
612 flags = ACL_START_NO_FLUSH;
613 else
614 flags = ACL_START;
615
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700616 bt_cb(skb)->force_active = chan->force_active;
617
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300618 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300619}
620
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300621static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300622{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300623 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300624 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300625 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300626 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300627 control |= L2CAP_SUPER_RCV_READY;
628
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300629 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300630
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300631 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300632}
633
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300634static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300635{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300636 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300637}
638
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300639static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200640{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300641 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200642
643 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100644 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
645 return;
646
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300647 if (l2cap_check_security(chan) &&
648 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200649 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300650 req.scid = cpu_to_le16(chan->scid);
651 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200652
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300653 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300654 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200655
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300656 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
657 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200658 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200659 } else {
660 struct l2cap_info_req req;
661 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
662
663 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
664 conn->info_ident = l2cap_get_ident(conn);
665
666 mod_timer(&conn->info_timer, jiffies +
667 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
668
669 l2cap_send_cmd(conn, conn->info_ident,
670 L2CAP_INFO_REQ, sizeof(req), &req);
671 }
672}
673
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300674static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
675{
676 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300677 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300678 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
679
680 switch (mode) {
681 case L2CAP_MODE_ERTM:
682 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
683 case L2CAP_MODE_STREAMING:
684 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
685 default:
686 return 0x00;
687 }
688}
689
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300690static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300691{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300692 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300693 struct l2cap_disconn_req req;
694
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300695 if (!conn)
696 return;
697
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300698 sk = chan->sk;
699
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300700 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300701 __clear_retrans_timer(chan);
702 __clear_monitor_timer(chan);
703 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300704 }
705
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300706 req.dcid = cpu_to_le16(chan->dcid);
707 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300708 l2cap_send_cmd(conn, l2cap_get_ident(conn),
709 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300710
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300711 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300712 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300713}
714
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200716static void l2cap_conn_start(struct l2cap_conn *conn)
717{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300718 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200719
720 BT_DBG("conn %p", conn);
721
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300722 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200723
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300724 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300725 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300726
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200727 bh_lock_sock(sk);
728
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300729 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200730 bh_unlock_sock(sk);
731 continue;
732 }
733
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300734 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300735 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300736
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300737 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300738 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300739 bh_unlock_sock(sk);
740 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200741 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300742
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300743 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
744 && test_bit(CONF_STATE2_DEVICE,
745 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300746 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300747 * so release the lock */
748 read_unlock_bh(&conn->chan_lock);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300749 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300750 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300751 bh_unlock_sock(sk);
752 continue;
753 }
754
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300755 req.scid = cpu_to_le16(chan->scid);
756 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300757
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300758 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300759 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300760
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300761 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
762 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300763
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300764 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200765 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300766 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300767 rsp.scid = cpu_to_le16(chan->dcid);
768 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200769
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300770 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100771 if (bt_sk(sk)->defer_setup) {
772 struct sock *parent = bt_sk(sk)->parent;
773 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
774 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
775 parent->sk_data_ready(parent, 0);
776
777 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300778 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100779 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
780 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
781 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200782 } else {
783 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
784 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
785 }
786
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300787 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
788 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300789
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300790 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300791 rsp.result != L2CAP_CR_SUCCESS) {
792 bh_unlock_sock(sk);
793 continue;
794 }
795
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300796 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300797 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300798 l2cap_build_conf_req(chan, buf), buf);
799 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200800 }
801
802 bh_unlock_sock(sk);
803 }
804
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300805 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200806}
807
Ville Tervob62f3282011-02-10 22:38:50 -0300808/* Find socket with cid and source bdaddr.
809 * Returns closest match, locked.
810 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300811static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300812{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300813 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300814
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300815 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300816
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300817 list_for_each_entry(c, &chan_list, global_l) {
818 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300819
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300820 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300821 continue;
822
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300823 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300824 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300825 if (!bacmp(&bt_sk(sk)->src, src)) {
826 read_unlock(&chan_list_lock);
827 return c;
828 }
Ville Tervob62f3282011-02-10 22:38:50 -0300829
830 /* Closest match */
831 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300832 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300833 }
834 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300835
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300836 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300837
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300838 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300839}
840
841static void l2cap_le_conn_ready(struct l2cap_conn *conn)
842{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300843 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300844 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300845
846 BT_DBG("");
847
848 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300849 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300850 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300851 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300852 return;
853
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300854 parent = pchan->sk;
855
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300856 bh_lock_sock(parent);
857
Ville Tervob62f3282011-02-10 22:38:50 -0300858 /* Check for backlog size */
859 if (sk_acceptq_is_full(parent)) {
860 BT_DBG("backlog full %d", parent->sk_ack_backlog);
861 goto clean;
862 }
863
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300864 chan = pchan->ops->new_connection(pchan->data);
865 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300866 goto clean;
867
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300868 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300869
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300870 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300871
872 hci_conn_hold(conn->hcon);
873
Ville Tervob62f3282011-02-10 22:38:50 -0300874 bacpy(&bt_sk(sk)->src, conn->src);
875 bacpy(&bt_sk(sk)->dst, conn->dst);
876
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300877 bt_accept_enqueue(parent, sk);
878
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300879 __l2cap_chan_add(conn, chan);
880
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300881 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300882
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300883 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300884 parent->sk_data_ready(parent, 0);
885
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300886 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300887
888clean:
889 bh_unlock_sock(parent);
890}
891
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300892static void l2cap_chan_ready(struct sock *sk)
893{
894 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
895 struct sock *parent = bt_sk(sk)->parent;
896
897 BT_DBG("sk %p, parent %p", sk, parent);
898
899 chan->conf_state = 0;
900 __clear_chan_timer(chan);
901
902 sk->sk_state = BT_CONNECTED;
903 sk->sk_state_change(sk);
904
905 if (parent)
906 parent->sk_data_ready(parent, 0);
907}
908
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200909static void l2cap_conn_ready(struct l2cap_conn *conn)
910{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300911 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200912
913 BT_DBG("conn %p", conn);
914
Ville Tervob62f3282011-02-10 22:38:50 -0300915 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
916 l2cap_le_conn_ready(conn);
917
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300918 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200919
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300920 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300921 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300922
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200923 bh_lock_sock(sk);
924
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300925 if (conn->hcon->type == LE_LINK)
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300926 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300927 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300928
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300929 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300930 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300931 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200932 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300933
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300934 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300935 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200936
937 bh_unlock_sock(sk);
938 }
939
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300940 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200941}
942
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200943/* Notify sockets that we cannot guaranty reliability anymore */
944static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
945{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300946 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200947
948 BT_DBG("conn %p", conn);
949
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300950 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200951
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300952 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300953 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300954
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300955 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200956 sk->sk_err = err;
957 }
958
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300959 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200960}
961
962static void l2cap_info_timeout(unsigned long arg)
963{
964 struct l2cap_conn *conn = (void *) arg;
965
Marcel Holtmann984947d2009-02-06 23:35:19 +0100966 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100967 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100968
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200969 l2cap_conn_start(conn);
970}
971
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300972static void l2cap_conn_del(struct hci_conn *hcon, int err)
973{
974 struct l2cap_conn *conn = hcon->l2cap_data;
975 struct l2cap_chan *chan, *l;
976 struct sock *sk;
977
978 if (!conn)
979 return;
980
981 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
982
983 kfree_skb(conn->rx_skb);
984
985 /* Kill channels */
986 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
987 sk = chan->sk;
988 bh_lock_sock(sk);
989 l2cap_chan_del(chan, err);
990 bh_unlock_sock(sk);
991 chan->ops->close(chan->data);
992 }
993
994 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
995 del_timer_sync(&conn->info_timer);
996
997 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
998 del_timer(&conn->security_timer);
999
1000 hcon->l2cap_data = NULL;
1001 kfree(conn);
1002}
1003
1004static void security_timeout(unsigned long arg)
1005{
1006 struct l2cap_conn *conn = (void *) arg;
1007
1008 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1009}
1010
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1012{
Marcel Holtmann01394182006-07-03 10:02:46 +02001013 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014
Marcel Holtmann01394182006-07-03 10:02:46 +02001015 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 return conn;
1017
Marcel Holtmann01394182006-07-03 10:02:46 +02001018 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1019 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021
1022 hcon->l2cap_data = conn;
1023 conn->hcon = hcon;
1024
Marcel Holtmann01394182006-07-03 10:02:46 +02001025 BT_DBG("hcon %p conn %p", hcon, conn);
1026
Ville Tervoacd7d372011-02-10 22:38:49 -03001027 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1028 conn->mtu = hcon->hdev->le_mtu;
1029 else
1030 conn->mtu = hcon->hdev->acl_mtu;
1031
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 conn->src = &hcon->hdev->bdaddr;
1033 conn->dst = &hcon->dst;
1034
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001035 conn->feat_mask = 0;
1036
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001038 rwlock_init(&conn->chan_lock);
1039
1040 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001042 if (hcon->type == LE_LINK)
1043 setup_timer(&conn->security_timer, security_timeout,
1044 (unsigned long) conn);
1045 else
Ville Tervob62f3282011-02-10 22:38:50 -03001046 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +00001047 (unsigned long) conn);
1048
Marcel Holtmann2950f212009-02-12 14:02:50 +01001049 conn->disc_reason = 0x13;
1050
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 return conn;
1052}
1053
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001054static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001056 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001057 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001058 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059}
1060
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062
1063/* Find socket with psm and source bdaddr.
1064 * Returns closest match.
1065 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001066static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001068 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001070 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001071
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001072 list_for_each_entry(c, &chan_list, global_l) {
1073 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001074
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001075 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 continue;
1077
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001078 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001080 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001081 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001082 return c;
1083 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084
1085 /* Closest match */
1086 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001087 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 }
1089 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001091 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001092
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001093 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094}
1095
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001096int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001098 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 bdaddr_t *src = &bt_sk(sk)->src;
1100 bdaddr_t *dst = &bt_sk(sk)->dst;
1101 struct l2cap_conn *conn;
1102 struct hci_conn *hcon;
1103 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001104 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001105 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001107 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001108 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001110 hdev = hci_get_route(dst, src);
1111 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 return -EHOSTUNREACH;
1113
1114 hci_dev_lock_bh(hdev);
1115
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001116 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001117
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001118 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001119 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001120 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001121 else
1122 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001123 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001124
Ville Tervo30e76272011-02-22 16:10:53 -03001125 if (IS_ERR(hcon)) {
1126 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001128 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129
1130 conn = l2cap_conn_add(hcon, 0);
1131 if (!conn) {
1132 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001133 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 goto done;
1135 }
1136
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 /* Update source addr of the socket */
1138 bacpy(src, conn->src);
1139
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001140 l2cap_chan_add(conn, chan);
1141
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001142 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001143 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
1145 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001146 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001147 __clear_chan_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001148 if (l2cap_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001149 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001150 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001151 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 }
1153
Ville Tervo30e76272011-02-22 16:10:53 -03001154 err = 0;
1155
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156done:
1157 hci_dev_unlock_bh(hdev);
1158 hci_dev_put(hdev);
1159 return err;
1160}
1161
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001162int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001163{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001164 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001165 DECLARE_WAITQUEUE(wait, current);
1166 int err = 0;
1167 int timeo = HZ/5;
1168
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001169 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001170 while ((chan->unacked_frames > 0 && chan->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001171 set_current_state(TASK_INTERRUPTIBLE);
1172
1173 if (!timeo)
1174 timeo = HZ/5;
1175
1176 if (signal_pending(current)) {
1177 err = sock_intr_errno(timeo);
1178 break;
1179 }
1180
1181 release_sock(sk);
1182 timeo = schedule_timeout(timeo);
1183 lock_sock(sk);
1184
1185 err = sock_error(sk);
1186 if (err)
1187 break;
1188 }
1189 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001190 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001191 return err;
1192}
1193
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001194static void l2cap_monitor_timeout(unsigned long arg)
1195{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001196 struct l2cap_chan *chan = (void *) arg;
1197 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001198
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001199 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001200
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001201 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001202 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001203 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001204 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001205 return;
1206 }
1207
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001208 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001209 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001210
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001211 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001212 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001213}
1214
1215static void l2cap_retrans_timeout(unsigned long arg)
1216{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001217 struct l2cap_chan *chan = (void *) arg;
1218 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001219
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001220 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001221
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001222 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001223 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001224 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001225
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001226 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001227
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001228 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001229 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001230}
1231
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001232static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001233{
1234 struct sk_buff *skb;
1235
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001236 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001237 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001238 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001239 break;
1240
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001241 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001242 kfree_skb(skb);
1243
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001244 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001245 }
1246
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001247 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001248 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001249}
1250
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001251void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001252{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001253 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001254 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001255
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001256 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001257
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001258 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001259 flags = ACL_START_NO_FLUSH;
1260 else
1261 flags = ACL_START;
1262
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -07001263 bt_cb(skb)->force_active = chan->force_active;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001264 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001265}
1266
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001267void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001268{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001269 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001270 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001271
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001272 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001273 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001274 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001275 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001276
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001277 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001278 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1279 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001280 }
1281
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001282 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001283
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001284 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001285 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001286}
1287
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001288static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001289{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001290 struct sk_buff *skb, *tx_skb;
1291 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001292
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001293 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001294 if (!skb)
1295 return;
1296
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001297 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001298 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001299 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001300
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001301 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001302 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001303
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001304 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001305
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001306 if (chan->remote_max_tx &&
1307 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001308 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001309 return;
1310 }
1311
1312 tx_skb = skb_clone(skb, GFP_ATOMIC);
1313 bt_cb(skb)->retries++;
1314 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001315 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001316
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001317 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001318 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001319 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001320 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001321
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001322 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001323 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001324
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001325 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1326
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001327 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001328 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1329 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1330 }
1331
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001332 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001333}
1334
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001335int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001336{
1337 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001338 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001339 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001340
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001341 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001342 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001343
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001344 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001345
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001346 if (chan->remote_max_tx &&
1347 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001348 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001349 break;
1350 }
1351
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001352 tx_skb = skb_clone(skb, GFP_ATOMIC);
1353
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001354 bt_cb(skb)->retries++;
1355
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001356 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001357 control &= L2CAP_CTRL_SAR;
1358
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001359 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001360 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001361 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001362 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001363 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1364 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001365 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1366
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001367
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001368 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001369 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1370 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1371 }
1372
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001373 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001374
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001375 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001376
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001377 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1378 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001379
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301380 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001381 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301382
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001383 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001384
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001385 if (skb_queue_is_last(&chan->tx_q, skb))
1386 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001387 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001388 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001389
1390 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001391 }
1392
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001393 return nsent;
1394}
1395
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001396static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001397{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001398 int ret;
1399
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001400 if (!skb_queue_empty(&chan->tx_q))
1401 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001402
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001403 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001404 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001405 return ret;
1406}
1407
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001408static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001409{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001410 u16 control = 0;
1411
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001412 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001413
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001414 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001415 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001416 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1417 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001418 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001419 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001420
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001421 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001422 return;
1423
1424 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001425 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001426}
1427
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001428static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001429{
1430 struct srej_list *tail;
1431 u16 control;
1432
1433 control = L2CAP_SUPER_SELECT_REJECT;
1434 control |= L2CAP_CTRL_FINAL;
1435
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001436 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001437 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1438
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001439 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001440}
1441
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001442static 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 -07001443{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001444 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001445 struct sk_buff **frag;
1446 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001448 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001449 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450
1451 sent += count;
1452 len -= count;
1453
1454 /* Continuation fragments (no L2CAP header) */
1455 frag = &skb_shinfo(skb)->frag_list;
1456 while (len) {
1457 count = min_t(unsigned int, conn->mtu, len);
1458
1459 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1460 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001461 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001462 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1463 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
1465 sent += count;
1466 len -= count;
1467
1468 frag = &(*frag)->next;
1469 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
1471 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001472}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001474struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001475{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001476 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001477 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001478 struct sk_buff *skb;
1479 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1480 struct l2cap_hdr *lh;
1481
1482 BT_DBG("sk %p len %d", sk, (int)len);
1483
1484 count = min_t(unsigned int, (conn->mtu - hlen), len);
1485 skb = bt_skb_send_alloc(sk, count + hlen,
1486 msg->msg_flags & MSG_DONTWAIT, &err);
1487 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001488 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001489
1490 /* Create L2CAP header */
1491 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001492 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001493 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001494 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001495
1496 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1497 if (unlikely(err < 0)) {
1498 kfree_skb(skb);
1499 return ERR_PTR(err);
1500 }
1501 return skb;
1502}
1503
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001504struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001505{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001506 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001507 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001508 struct sk_buff *skb;
1509 int err, count, hlen = L2CAP_HDR_SIZE;
1510 struct l2cap_hdr *lh;
1511
1512 BT_DBG("sk %p len %d", sk, (int)len);
1513
1514 count = min_t(unsigned int, (conn->mtu - hlen), len);
1515 skb = bt_skb_send_alloc(sk, count + hlen,
1516 msg->msg_flags & MSG_DONTWAIT, &err);
1517 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001518 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001519
1520 /* Create L2CAP header */
1521 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001522 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001523 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1524
1525 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1526 if (unlikely(err < 0)) {
1527 kfree_skb(skb);
1528 return ERR_PTR(err);
1529 }
1530 return skb;
1531}
1532
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001533struct 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 -03001534{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001535 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001536 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001537 struct sk_buff *skb;
1538 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1539 struct l2cap_hdr *lh;
1540
1541 BT_DBG("sk %p len %d", sk, (int)len);
1542
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001543 if (!conn)
1544 return ERR_PTR(-ENOTCONN);
1545
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001546 if (sdulen)
1547 hlen += 2;
1548
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001549 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001550 hlen += 2;
1551
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001552 count = min_t(unsigned int, (conn->mtu - hlen), len);
1553 skb = bt_skb_send_alloc(sk, count + hlen,
1554 msg->msg_flags & MSG_DONTWAIT, &err);
1555 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001556 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001557
1558 /* Create L2CAP header */
1559 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001560 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001561 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1562 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001563 if (sdulen)
1564 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001565
1566 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1567 if (unlikely(err < 0)) {
1568 kfree_skb(skb);
1569 return ERR_PTR(err);
1570 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001571
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001572 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001573 put_unaligned_le16(0, skb_put(skb, 2));
1574
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001575 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001576 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577}
1578
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001579int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001580{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001581 struct sk_buff *skb;
1582 struct sk_buff_head sar_queue;
1583 u16 control;
1584 size_t size = 0;
1585
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001586 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001587 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001588 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001589 if (IS_ERR(skb))
1590 return PTR_ERR(skb);
1591
1592 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001593 len -= chan->remote_mps;
1594 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001595
1596 while (len > 0) {
1597 size_t buflen;
1598
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001599 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001600 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001601 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001602 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001603 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001604 buflen = len;
1605 }
1606
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001607 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001608 if (IS_ERR(skb)) {
1609 skb_queue_purge(&sar_queue);
1610 return PTR_ERR(skb);
1611 }
1612
1613 __skb_queue_tail(&sar_queue, skb);
1614 len -= buflen;
1615 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001616 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001617 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1618 if (chan->tx_send_head == NULL)
1619 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001620
1621 return size;
1622}
1623
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001624int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1625{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001626 struct sk_buff *skb;
1627 u16 control;
1628 int err;
1629
1630 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001631 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001632 skb = l2cap_create_connless_pdu(chan, msg, len);
1633 if (IS_ERR(skb))
1634 return PTR_ERR(skb);
1635
1636 l2cap_do_send(chan, skb);
1637 return len;
1638 }
1639
1640 switch (chan->mode) {
1641 case L2CAP_MODE_BASIC:
1642 /* Check outgoing MTU */
1643 if (len > chan->omtu)
1644 return -EMSGSIZE;
1645
1646 /* Create a basic PDU */
1647 skb = l2cap_create_basic_pdu(chan, msg, len);
1648 if (IS_ERR(skb))
1649 return PTR_ERR(skb);
1650
1651 l2cap_do_send(chan, skb);
1652 err = len;
1653 break;
1654
1655 case L2CAP_MODE_ERTM:
1656 case L2CAP_MODE_STREAMING:
1657 /* Entire SDU fits into one PDU */
1658 if (len <= chan->remote_mps) {
1659 control = L2CAP_SDU_UNSEGMENTED;
1660 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1661 0);
1662 if (IS_ERR(skb))
1663 return PTR_ERR(skb);
1664
1665 __skb_queue_tail(&chan->tx_q, skb);
1666
1667 if (chan->tx_send_head == NULL)
1668 chan->tx_send_head = skb;
1669
1670 } else {
1671 /* Segment SDU into multiples PDUs */
1672 err = l2cap_sar_segment_sdu(chan, msg, len);
1673 if (err < 0)
1674 return err;
1675 }
1676
1677 if (chan->mode == L2CAP_MODE_STREAMING) {
1678 l2cap_streaming_send(chan);
1679 err = len;
1680 break;
1681 }
1682
1683 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
1684 (chan->conn_state & L2CAP_CONN_WAIT_F)) {
1685 err = len;
1686 break;
1687 }
1688
1689 err = l2cap_ertm_send(chan);
1690 if (err >= 0)
1691 err = len;
1692
1693 break;
1694
1695 default:
1696 BT_DBG("bad state %1.1x", chan->mode);
1697 err = -EBADFD;
1698 }
1699
1700 return err;
1701}
1702
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703/* Copy frame to all raw sockets on that connection */
1704static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1705{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001707 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708
1709 BT_DBG("conn %p", conn);
1710
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001711 read_lock(&conn->chan_lock);
1712 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001713 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001714 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 continue;
1716
1717 /* Don't send frame to the socket it came from */
1718 if (skb->sk == sk)
1719 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001720 nskb = skb_clone(skb, GFP_ATOMIC);
1721 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 continue;
1723
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001724 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 kfree_skb(nskb);
1726 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001727 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728}
1729
1730/* ---- L2CAP signalling commands ---- */
1731static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1732 u8 code, u8 ident, u16 dlen, void *data)
1733{
1734 struct sk_buff *skb, **frag;
1735 struct l2cap_cmd_hdr *cmd;
1736 struct l2cap_hdr *lh;
1737 int len, count;
1738
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001739 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1740 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741
1742 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1743 count = min_t(unsigned int, conn->mtu, len);
1744
1745 skb = bt_skb_alloc(count, GFP_ATOMIC);
1746 if (!skb)
1747 return NULL;
1748
1749 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001750 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001751
1752 if (conn->hcon->type == LE_LINK)
1753 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1754 else
1755 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756
1757 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1758 cmd->code = code;
1759 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001760 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761
1762 if (dlen) {
1763 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1764 memcpy(skb_put(skb, count), data, count);
1765 data += count;
1766 }
1767
1768 len -= skb->len;
1769
1770 /* Continuation fragments (no L2CAP header) */
1771 frag = &skb_shinfo(skb)->frag_list;
1772 while (len) {
1773 count = min_t(unsigned int, conn->mtu, len);
1774
1775 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1776 if (!*frag)
1777 goto fail;
1778
1779 memcpy(skb_put(*frag, count), data, count);
1780
1781 len -= count;
1782 data += count;
1783
1784 frag = &(*frag)->next;
1785 }
1786
1787 return skb;
1788
1789fail:
1790 kfree_skb(skb);
1791 return NULL;
1792}
1793
1794static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1795{
1796 struct l2cap_conf_opt *opt = *ptr;
1797 int len;
1798
1799 len = L2CAP_CONF_OPT_SIZE + opt->len;
1800 *ptr += len;
1801
1802 *type = opt->type;
1803 *olen = opt->len;
1804
1805 switch (opt->len) {
1806 case 1:
1807 *val = *((u8 *) opt->val);
1808 break;
1809
1810 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001811 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 break;
1813
1814 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001815 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816 break;
1817
1818 default:
1819 *val = (unsigned long) opt->val;
1820 break;
1821 }
1822
1823 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1824 return len;
1825}
1826
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1828{
1829 struct l2cap_conf_opt *opt = *ptr;
1830
1831 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1832
1833 opt->type = type;
1834 opt->len = len;
1835
1836 switch (len) {
1837 case 1:
1838 *((u8 *) opt->val) = val;
1839 break;
1840
1841 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001842 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 break;
1844
1845 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001846 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 break;
1848
1849 default:
1850 memcpy(opt->val, (void *) val, len);
1851 break;
1852 }
1853
1854 *ptr += L2CAP_CONF_OPT_SIZE + len;
1855}
1856
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001857static void l2cap_ack_timeout(unsigned long arg)
1858{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001859 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001860
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001861 bh_lock_sock(chan->sk);
1862 l2cap_send_ack(chan);
1863 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001864}
1865
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001866static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001867{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001868 struct sock *sk = chan->sk;
1869
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001870 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001871 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001872 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001873 chan->num_acked = 0;
1874 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001875
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001876 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1877 (unsigned long) chan);
1878 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1879 (unsigned long) chan);
1880 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001881
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001882 skb_queue_head_init(&chan->srej_q);
1883 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001884
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001885 INIT_LIST_HEAD(&chan->srej_l);
1886
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001887 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001888
1889 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001890}
1891
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001892static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1893{
1894 switch (mode) {
1895 case L2CAP_MODE_STREAMING:
1896 case L2CAP_MODE_ERTM:
1897 if (l2cap_mode_supported(mode, remote_feat_mask))
1898 return mode;
1899 /* fall through */
1900 default:
1901 return L2CAP_MODE_BASIC;
1902 }
1903}
1904
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03001905static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001908 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 void *ptr = req->data;
1910
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001911 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001913 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001914 goto done;
1915
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001916 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001917 case L2CAP_MODE_STREAMING:
1918 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001919 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001920 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001921
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001922 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001923 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001924 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001925 break;
1926 }
1927
1928done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001929 if (chan->imtu != L2CAP_DEFAULT_MTU)
1930 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001931
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001932 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001933 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001934 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1935 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001936 break;
1937
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001938 rfc.mode = L2CAP_MODE_BASIC;
1939 rfc.txwin_size = 0;
1940 rfc.max_transmit = 0;
1941 rfc.retrans_timeout = 0;
1942 rfc.monitor_timeout = 0;
1943 rfc.max_pdu_size = 0;
1944
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001945 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1946 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001947 break;
1948
1949 case L2CAP_MODE_ERTM:
1950 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001951 rfc.txwin_size = chan->tx_win;
1952 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001953 rfc.retrans_timeout = 0;
1954 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001955 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001956 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1957 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001958
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001959 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1960 (unsigned long) &rfc);
1961
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001962 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001963 break;
1964
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001965 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001966 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001967 chan->fcs = L2CAP_FCS_NONE;
1968 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001969 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001970 break;
1971
1972 case L2CAP_MODE_STREAMING:
1973 rfc.mode = L2CAP_MODE_STREAMING;
1974 rfc.txwin_size = 0;
1975 rfc.max_transmit = 0;
1976 rfc.retrans_timeout = 0;
1977 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001978 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001979 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1980 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001981
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001982 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1983 (unsigned long) &rfc);
1984
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001985 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001986 break;
1987
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001988 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001989 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001990 chan->fcs = L2CAP_FCS_NONE;
1991 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001992 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001993 break;
1994 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001996 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001997 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998
1999 return ptr - data;
2000}
2001
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002002static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002004 struct l2cap_conf_rsp *rsp = data;
2005 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002006 void *req = chan->conf_req;
2007 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002008 int type, hint, olen;
2009 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002010 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002011 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002012 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002014 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002015
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002016 while (len >= L2CAP_CONF_OPT_SIZE) {
2017 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002019 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002020 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002021
2022 switch (type) {
2023 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002024 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002025 break;
2026
2027 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002028 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002029 break;
2030
2031 case L2CAP_CONF_QOS:
2032 break;
2033
Marcel Holtmann6464f352007-10-20 13:39:51 +02002034 case L2CAP_CONF_RFC:
2035 if (olen == sizeof(rfc))
2036 memcpy(&rfc, (void *) val, olen);
2037 break;
2038
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002039 case L2CAP_CONF_FCS:
2040 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002041 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002042
2043 break;
2044
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002045 default:
2046 if (hint)
2047 break;
2048
2049 result = L2CAP_CONF_UNKNOWN;
2050 *((u8 *) ptr++) = type;
2051 break;
2052 }
2053 }
2054
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002055 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002056 goto done;
2057
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002058 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002059 case L2CAP_MODE_STREAMING:
2060 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002061 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002062 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002063 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002064 break;
2065 }
2066
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002067 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002068 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002069
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002070 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002071 }
2072
2073done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002074 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002075 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002076 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002077
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002078 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002079 return -ECONNREFUSED;
2080
2081 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2082 sizeof(rfc), (unsigned long) &rfc);
2083 }
2084
2085
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002086 if (result == L2CAP_CONF_SUCCESS) {
2087 /* Configure output options and let the other side know
2088 * which ones we don't like. */
2089
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002090 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2091 result = L2CAP_CONF_UNACCEPT;
2092 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002093 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002094 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002095 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002096 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002097
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002098 switch (rfc.mode) {
2099 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002100 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002101 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002102 break;
2103
2104 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002105 chan->remote_tx_win = rfc.txwin_size;
2106 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002107
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002108 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2109 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002110
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002111 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002112
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002113 rfc.retrans_timeout =
2114 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2115 rfc.monitor_timeout =
2116 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002117
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002118 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002119
2120 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2121 sizeof(rfc), (unsigned long) &rfc);
2122
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002123 break;
2124
2125 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002126 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2127 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002128
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002129 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002130
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002131 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002132
2133 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2134 sizeof(rfc), (unsigned long) &rfc);
2135
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002136 break;
2137
2138 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002139 result = L2CAP_CONF_UNACCEPT;
2140
2141 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002142 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002143 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002144
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002145 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002146 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002147 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002148 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002149 rsp->result = cpu_to_le16(result);
2150 rsp->flags = cpu_to_le16(0x0000);
2151
2152 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153}
2154
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002155static 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 -03002156{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002157 struct l2cap_conf_req *req = data;
2158 void *ptr = req->data;
2159 int type, olen;
2160 unsigned long val;
2161 struct l2cap_conf_rfc rfc;
2162
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002163 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002164
2165 while (len >= L2CAP_CONF_OPT_SIZE) {
2166 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2167
2168 switch (type) {
2169 case L2CAP_CONF_MTU:
2170 if (val < L2CAP_DEFAULT_MIN_MTU) {
2171 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002172 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002173 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002174 chan->imtu = val;
2175 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002176 break;
2177
2178 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002179 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002180 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002181 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002182 break;
2183
2184 case L2CAP_CONF_RFC:
2185 if (olen == sizeof(rfc))
2186 memcpy(&rfc, (void *)val, olen);
2187
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002188 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002189 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002190 return -ECONNREFUSED;
2191
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002192 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002193
2194 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2195 sizeof(rfc), (unsigned long) &rfc);
2196 break;
2197 }
2198 }
2199
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002200 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002201 return -ECONNREFUSED;
2202
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002203 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002204
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002205 if (*result == L2CAP_CONF_SUCCESS) {
2206 switch (rfc.mode) {
2207 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002208 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2209 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2210 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002211 break;
2212 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002213 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002214 }
2215 }
2216
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002217 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002218 req->flags = cpu_to_le16(0x0000);
2219
2220 return ptr - data;
2221}
2222
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002223static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224{
2225 struct l2cap_conf_rsp *rsp = data;
2226 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002228 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002230 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002231 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002232 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233
2234 return ptr - data;
2235}
2236
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002237void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002238{
2239 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002240 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002241 u8 buf[128];
2242
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002243 rsp.scid = cpu_to_le16(chan->dcid);
2244 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002245 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2246 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2247 l2cap_send_cmd(conn, chan->ident,
2248 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2249
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002250 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002251 return;
2252
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002253 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2254 l2cap_build_conf_req(chan, buf), buf);
2255 chan->num_conf_req++;
2256}
2257
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002258static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002259{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002260 int type, olen;
2261 unsigned long val;
2262 struct l2cap_conf_rfc rfc;
2263
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002264 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002265
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002266 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002267 return;
2268
2269 while (len >= L2CAP_CONF_OPT_SIZE) {
2270 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2271
2272 switch (type) {
2273 case L2CAP_CONF_RFC:
2274 if (olen == sizeof(rfc))
2275 memcpy(&rfc, (void *)val, olen);
2276 goto done;
2277 }
2278 }
2279
2280done:
2281 switch (rfc.mode) {
2282 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002283 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2284 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2285 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002286 break;
2287 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002288 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002289 }
2290}
2291
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002292static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2293{
2294 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2295
2296 if (rej->reason != 0x0000)
2297 return 0;
2298
2299 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2300 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002301 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002302
2303 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002304 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002305
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002306 l2cap_conn_start(conn);
2307 }
2308
2309 return 0;
2310}
2311
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2313{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2315 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002316 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002317 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002318 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319
2320 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002321 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322
2323 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2324
2325 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002326 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2327 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 result = L2CAP_CR_BAD_PSM;
2329 goto sendresp;
2330 }
2331
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002332 parent = pchan->sk;
2333
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002334 bh_lock_sock(parent);
2335
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002336 /* Check if the ACL is secure enough (if not SDP) */
2337 if (psm != cpu_to_le16(0x0001) &&
2338 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002339 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002340 result = L2CAP_CR_SEC_BLOCK;
2341 goto response;
2342 }
2343
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 result = L2CAP_CR_NO_MEM;
2345
2346 /* Check for backlog size */
2347 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002348 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 goto response;
2350 }
2351
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002352 chan = pchan->ops->new_connection(pchan->data);
2353 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 goto response;
2355
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002356 sk = chan->sk;
2357
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002358 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359
2360 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002361 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2362 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002364 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 goto response;
2366 }
2367
2368 hci_conn_hold(conn->hcon);
2369
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370 bacpy(&bt_sk(sk)->src, conn->src);
2371 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002372 chan->psm = psm;
2373 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002375 bt_accept_enqueue(parent, sk);
2376
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002377 __l2cap_chan_add(conn, chan);
2378
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002379 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002381 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002383 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384
Marcel Holtmann984947d2009-02-06 23:35:19 +01002385 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002386 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002387 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002388 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002389 result = L2CAP_CR_PEND;
2390 status = L2CAP_CS_AUTHOR_PEND;
2391 parent->sk_data_ready(parent, 0);
2392 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002393 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002394 result = L2CAP_CR_SUCCESS;
2395 status = L2CAP_CS_NO_INFO;
2396 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002397 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002398 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002399 result = L2CAP_CR_PEND;
2400 status = L2CAP_CS_AUTHEN_PEND;
2401 }
2402 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002403 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002404 result = L2CAP_CR_PEND;
2405 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 }
2407
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002408 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409
2410response:
2411 bh_unlock_sock(parent);
2412
2413sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002414 rsp.scid = cpu_to_le16(scid);
2415 rsp.dcid = cpu_to_le16(dcid);
2416 rsp.result = cpu_to_le16(result);
2417 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002419
2420 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2421 struct l2cap_info_req info;
2422 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2423
2424 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2425 conn->info_ident = l2cap_get_ident(conn);
2426
2427 mod_timer(&conn->info_timer, jiffies +
2428 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2429
2430 l2cap_send_cmd(conn, conn->info_ident,
2431 L2CAP_INFO_REQ, sizeof(info), &info);
2432 }
2433
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002434 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002435 result == L2CAP_CR_SUCCESS) {
2436 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002437 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002438 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002439 l2cap_build_conf_req(chan, buf), buf);
2440 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002441 }
2442
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 return 0;
2444}
2445
2446static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2447{
2448 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2449 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002450 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 struct sock *sk;
2452 u8 req[128];
2453
2454 scid = __le16_to_cpu(rsp->scid);
2455 dcid = __le16_to_cpu(rsp->dcid);
2456 result = __le16_to_cpu(rsp->result);
2457 status = __le16_to_cpu(rsp->status);
2458
2459 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2460
2461 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002462 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002463 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002464 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002466 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002467 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002468 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 }
2470
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002471 sk = chan->sk;
2472
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473 switch (result) {
2474 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002475 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002476 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002477 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002478 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002479
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002480 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002481 break;
2482
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002484 l2cap_build_conf_req(chan, req), req);
2485 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486 break;
2487
2488 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002489 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 break;
2491
2492 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002493 /* don't delete l2cap channel if sk is owned by user */
2494 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002495 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002496 __clear_chan_timer(chan);
2497 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002498 break;
2499 }
2500
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002501 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502 break;
2503 }
2504
2505 bh_unlock_sock(sk);
2506 return 0;
2507}
2508
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002509static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002510{
2511 /* FCS is enabled only in ERTM or streaming mode, if one or both
2512 * sides request it.
2513 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002514 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002515 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002516 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002517 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002518}
2519
Al Viro88219a02007-07-29 00:17:25 -07002520static 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 -07002521{
2522 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2523 u16 dcid, flags;
2524 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002525 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002527 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528
2529 dcid = __le16_to_cpu(req->dcid);
2530 flags = __le16_to_cpu(req->flags);
2531
2532 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2533
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002534 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002535 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536 return -ENOENT;
2537
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002538 sk = chan->sk;
2539
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002540 if (chan->state != BT_CONFIG) {
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002541 struct l2cap_cmd_rej rej;
2542
2543 rej.reason = cpu_to_le16(0x0002);
2544 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2545 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002546 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002547 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002548
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002549 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002550 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002551 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002552 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002553 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002554 L2CAP_CONF_REJECT, flags), rsp);
2555 goto unlock;
2556 }
2557
2558 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002559 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2560 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561
2562 if (flags & 0x0001) {
2563 /* Incomplete config. Send empty response. */
2564 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002565 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002566 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 goto unlock;
2568 }
2569
2570 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002571 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002572 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002573 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002575 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002577 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002578 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002579
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002580 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002581 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002582
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002583 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002584 goto unlock;
2585
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002586 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002587 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002588
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002589 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002590
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002591 chan->next_tx_seq = 0;
2592 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002593 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002594 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002595 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002596
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002598 goto unlock;
2599 }
2600
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002601 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002602 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002604 l2cap_build_conf_req(chan, buf), buf);
2605 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606 }
2607
2608unlock:
2609 bh_unlock_sock(sk);
2610 return 0;
2611}
2612
2613static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2614{
2615 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2616 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002617 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002619 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620
2621 scid = __le16_to_cpu(rsp->scid);
2622 flags = __le16_to_cpu(rsp->flags);
2623 result = __le16_to_cpu(rsp->result);
2624
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002625 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2626 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002628 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002629 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630 return 0;
2631
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002632 sk = chan->sk;
2633
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634 switch (result) {
2635 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002636 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 break;
2638
2639 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002640 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002641 char req[64];
2642
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002643 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002644 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002645 goto done;
2646 }
2647
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002648 /* throw out any old stored conf requests */
2649 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002650 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2651 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002652 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002653 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002654 goto done;
2655 }
2656
2657 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2658 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002659 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002660 if (result != L2CAP_CONF_SUCCESS)
2661 goto done;
2662 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663 }
2664
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002665 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002666 sk->sk_err = ECONNRESET;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002667 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002668 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669 goto done;
2670 }
2671
2672 if (flags & 0x01)
2673 goto done;
2674
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002675 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002677 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002678 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002679
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002680 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002681 chan->next_tx_seq = 0;
2682 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002683 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002684 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002685 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002686
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687 l2cap_chan_ready(sk);
2688 }
2689
2690done:
2691 bh_unlock_sock(sk);
2692 return 0;
2693}
2694
2695static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2696{
2697 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2698 struct l2cap_disconn_rsp rsp;
2699 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002700 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701 struct sock *sk;
2702
2703 scid = __le16_to_cpu(req->scid);
2704 dcid = __le16_to_cpu(req->dcid);
2705
2706 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2707
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002708 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002709 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710 return 0;
2711
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002712 sk = chan->sk;
2713
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002714 rsp.dcid = cpu_to_le16(chan->scid);
2715 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2717
2718 sk->sk_shutdown = SHUTDOWN_MASK;
2719
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002720 /* don't delete l2cap channel if sk is owned by user */
2721 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002722 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002723 __clear_chan_timer(chan);
2724 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002725 bh_unlock_sock(sk);
2726 return 0;
2727 }
2728
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002729 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 bh_unlock_sock(sk);
2731
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002732 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 return 0;
2734}
2735
2736static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2737{
2738 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2739 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002740 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741 struct sock *sk;
2742
2743 scid = __le16_to_cpu(rsp->scid);
2744 dcid = __le16_to_cpu(rsp->dcid);
2745
2746 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2747
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002748 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002749 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750 return 0;
2751
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002752 sk = chan->sk;
2753
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002754 /* don't delete l2cap channel if sk is owned by user */
2755 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002756 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002757 __clear_chan_timer(chan);
2758 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002759 bh_unlock_sock(sk);
2760 return 0;
2761 }
2762
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002763 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 bh_unlock_sock(sk);
2765
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002766 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 return 0;
2768}
2769
2770static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2771{
2772 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773 u16 type;
2774
2775 type = __le16_to_cpu(req->type);
2776
2777 BT_DBG("type 0x%4.4x", type);
2778
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002779 if (type == L2CAP_IT_FEAT_MASK) {
2780 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002781 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002782 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2783 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2784 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002785 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002786 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2787 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002788 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002789 l2cap_send_cmd(conn, cmd->ident,
2790 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002791 } else if (type == L2CAP_IT_FIXED_CHAN) {
2792 u8 buf[12];
2793 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2794 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2795 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2796 memcpy(buf + 4, l2cap_fixed_chan, 8);
2797 l2cap_send_cmd(conn, cmd->ident,
2798 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002799 } else {
2800 struct l2cap_info_rsp rsp;
2801 rsp.type = cpu_to_le16(type);
2802 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2803 l2cap_send_cmd(conn, cmd->ident,
2804 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2805 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806
2807 return 0;
2808}
2809
2810static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2811{
2812 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2813 u16 type, result;
2814
2815 type = __le16_to_cpu(rsp->type);
2816 result = __le16_to_cpu(rsp->result);
2817
2818 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2819
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002820 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2821 if (cmd->ident != conn->info_ident ||
2822 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2823 return 0;
2824
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002825 del_timer(&conn->info_timer);
2826
Ville Tervoadb08ed2010-08-04 09:43:33 +03002827 if (result != L2CAP_IR_SUCCESS) {
2828 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2829 conn->info_ident = 0;
2830
2831 l2cap_conn_start(conn);
2832
2833 return 0;
2834 }
2835
Marcel Holtmann984947d2009-02-06 23:35:19 +01002836 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002837 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002838
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002839 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002840 struct l2cap_info_req req;
2841 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2842
2843 conn->info_ident = l2cap_get_ident(conn);
2844
2845 l2cap_send_cmd(conn, conn->info_ident,
2846 L2CAP_INFO_REQ, sizeof(req), &req);
2847 } else {
2848 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2849 conn->info_ident = 0;
2850
2851 l2cap_conn_start(conn);
2852 }
2853 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002854 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002855 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002856
2857 l2cap_conn_start(conn);
2858 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002859
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860 return 0;
2861}
2862
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002863static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002864 u16 to_multiplier)
2865{
2866 u16 max_latency;
2867
2868 if (min > max || min < 6 || max > 3200)
2869 return -EINVAL;
2870
2871 if (to_multiplier < 10 || to_multiplier > 3200)
2872 return -EINVAL;
2873
2874 if (max >= to_multiplier * 8)
2875 return -EINVAL;
2876
2877 max_latency = (to_multiplier * 8 / max) - 1;
2878 if (latency > 499 || latency > max_latency)
2879 return -EINVAL;
2880
2881 return 0;
2882}
2883
2884static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2885 struct l2cap_cmd_hdr *cmd, u8 *data)
2886{
2887 struct hci_conn *hcon = conn->hcon;
2888 struct l2cap_conn_param_update_req *req;
2889 struct l2cap_conn_param_update_rsp rsp;
2890 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002891 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002892
2893 if (!(hcon->link_mode & HCI_LM_MASTER))
2894 return -EINVAL;
2895
2896 cmd_len = __le16_to_cpu(cmd->len);
2897 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2898 return -EPROTO;
2899
2900 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002901 min = __le16_to_cpu(req->min);
2902 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002903 latency = __le16_to_cpu(req->latency);
2904 to_multiplier = __le16_to_cpu(req->to_multiplier);
2905
2906 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2907 min, max, latency, to_multiplier);
2908
2909 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002910
2911 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2912 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002913 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2914 else
2915 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2916
2917 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2918 sizeof(rsp), &rsp);
2919
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002920 if (!err)
2921 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2922
Claudio Takahaside731152011-02-11 19:28:55 -02002923 return 0;
2924}
2925
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002926static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2927 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2928{
2929 int err = 0;
2930
2931 switch (cmd->code) {
2932 case L2CAP_COMMAND_REJ:
2933 l2cap_command_rej(conn, cmd, data);
2934 break;
2935
2936 case L2CAP_CONN_REQ:
2937 err = l2cap_connect_req(conn, cmd, data);
2938 break;
2939
2940 case L2CAP_CONN_RSP:
2941 err = l2cap_connect_rsp(conn, cmd, data);
2942 break;
2943
2944 case L2CAP_CONF_REQ:
2945 err = l2cap_config_req(conn, cmd, cmd_len, data);
2946 break;
2947
2948 case L2CAP_CONF_RSP:
2949 err = l2cap_config_rsp(conn, cmd, data);
2950 break;
2951
2952 case L2CAP_DISCONN_REQ:
2953 err = l2cap_disconnect_req(conn, cmd, data);
2954 break;
2955
2956 case L2CAP_DISCONN_RSP:
2957 err = l2cap_disconnect_rsp(conn, cmd, data);
2958 break;
2959
2960 case L2CAP_ECHO_REQ:
2961 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2962 break;
2963
2964 case L2CAP_ECHO_RSP:
2965 break;
2966
2967 case L2CAP_INFO_REQ:
2968 err = l2cap_information_req(conn, cmd, data);
2969 break;
2970
2971 case L2CAP_INFO_RSP:
2972 err = l2cap_information_rsp(conn, cmd, data);
2973 break;
2974
2975 default:
2976 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2977 err = -EINVAL;
2978 break;
2979 }
2980
2981 return err;
2982}
2983
2984static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2985 struct l2cap_cmd_hdr *cmd, u8 *data)
2986{
2987 switch (cmd->code) {
2988 case L2CAP_COMMAND_REJ:
2989 return 0;
2990
2991 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002992 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002993
2994 case L2CAP_CONN_PARAM_UPDATE_RSP:
2995 return 0;
2996
2997 default:
2998 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2999 return -EINVAL;
3000 }
3001}
3002
3003static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3004 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005{
3006 u8 *data = skb->data;
3007 int len = skb->len;
3008 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003009 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010
3011 l2cap_raw_recv(conn, skb);
3012
3013 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003014 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3016 data += L2CAP_CMD_HDR_SIZE;
3017 len -= L2CAP_CMD_HDR_SIZE;
3018
Al Viro88219a02007-07-29 00:17:25 -07003019 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020
Al Viro88219a02007-07-29 00:17:25 -07003021 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 -07003022
Al Viro88219a02007-07-29 00:17:25 -07003023 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024 BT_DBG("corrupted command");
3025 break;
3026 }
3027
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003028 if (conn->hcon->type == LE_LINK)
3029 err = l2cap_le_sig_cmd(conn, &cmd, data);
3030 else
3031 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032
3033 if (err) {
3034 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003035
3036 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037
3038 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003039 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003040 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3041 }
3042
Al Viro88219a02007-07-29 00:17:25 -07003043 data += cmd_len;
3044 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045 }
3046
3047 kfree_skb(skb);
3048}
3049
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003050static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003051{
3052 u16 our_fcs, rcv_fcs;
3053 int hdr_size = L2CAP_HDR_SIZE + 2;
3054
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003055 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003056 skb_trim(skb, skb->len - 2);
3057 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3058 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3059
3060 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003061 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003062 }
3063 return 0;
3064}
3065
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003066static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003067{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003068 u16 control = 0;
3069
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003070 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003071
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003072 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003073
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003074 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003075 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003076 l2cap_send_sframe(chan, control);
3077 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003078 }
3079
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003080 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
3081 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003082
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003083 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003084
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003085 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003086 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003087 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003088 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003089 }
3090}
3091
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003092static 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 -03003093{
3094 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003095 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003096
3097 bt_cb(skb)->tx_seq = tx_seq;
3098 bt_cb(skb)->sar = sar;
3099
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003100 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003101 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003102 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003103 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003104 }
3105
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003106 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003107 if (tx_seq_offset < 0)
3108 tx_seq_offset += 64;
3109
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003110 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003111 if (bt_cb(next_skb)->tx_seq == tx_seq)
3112 return -EINVAL;
3113
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003114 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003115 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003116 if (next_tx_seq_offset < 0)
3117 next_tx_seq_offset += 64;
3118
3119 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003120 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003121 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003122 }
3123
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003124 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003125 break;
3126
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003127 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003128
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003129 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003130
3131 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003132}
3133
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003134static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003135{
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003136 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003137 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003138
3139 switch (control & L2CAP_CTRL_SAR) {
3140 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003141 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003142 goto drop;
3143
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003144 return chan->ops->recv(chan->data, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003145
3146 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003147 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003148 goto drop;
3149
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003150 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003151
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003152 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003153 goto disconnect;
3154
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003155 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3156 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003157 return -ENOMEM;
3158
3159 /* pull sdu_len bytes only after alloc, because of Local Busy
3160 * condition we have to be sure that this will be executed
3161 * only once, i.e., when alloc does not fail */
3162 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003163
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003164 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003165
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003166 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003167 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003168 break;
3169
3170 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003171 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003172 goto disconnect;
3173
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003174 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003175 goto disconnect;
3176
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003177 chan->partial_sdu_len += skb->len;
3178 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003179 goto drop;
3180
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003181 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003182
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003183 break;
3184
3185 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003186 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003187 goto disconnect;
3188
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003189 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003190 goto disconnect;
3191
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003192 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003193 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003194
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003195 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003196 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003197
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003198 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003199 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003200
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003201 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003202 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003203
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003204 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003205 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003206 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003207 return -ENOMEM;
3208 }
3209
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003210 err = chan->ops->recv(chan->data, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003211 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003212 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003213 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003214 return err;
3215 }
3216
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003217 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
3218 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003219
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003220 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003221 break;
3222 }
3223
3224 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003225 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003226
3227drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003228 kfree_skb(chan->sdu);
3229 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003230
3231disconnect:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003232 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003233 kfree_skb(skb);
3234 return 0;
3235}
3236
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003237static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003238{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003239 struct sk_buff *skb;
3240 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003241 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003242
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003243 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003244 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003245 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003246 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003247 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003248 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003249 }
3250
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003251 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003252 }
3253
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003254 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003255 goto done;
3256
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003257 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003258 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003259 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003260 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003261
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003262 __clear_retrans_timer(chan);
3263 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003264
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003265 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003266
3267done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003268 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3269 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003270
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003271 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003272
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003273 return 0;
3274}
3275
3276static void l2cap_busy_work(struct work_struct *work)
3277{
3278 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003279 struct l2cap_chan *chan =
3280 container_of(work, struct l2cap_chan, busy_work);
3281 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003282 int n_tries = 0, timeo = HZ/5, err;
3283 struct sk_buff *skb;
3284
3285 lock_sock(sk);
3286
3287 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003288 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003289 set_current_state(TASK_INTERRUPTIBLE);
3290
3291 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3292 err = -EBUSY;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003293 l2cap_send_disconn_req(chan->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003294 break;
3295 }
3296
3297 if (!timeo)
3298 timeo = HZ/5;
3299
3300 if (signal_pending(current)) {
3301 err = sock_intr_errno(timeo);
3302 break;
3303 }
3304
3305 release_sock(sk);
3306 timeo = schedule_timeout(timeo);
3307 lock_sock(sk);
3308
3309 err = sock_error(sk);
3310 if (err)
3311 break;
3312
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003313 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003314 break;
3315 }
3316
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003317 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003318 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003319
3320 release_sock(sk);
3321}
3322
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003323static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003324{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003325 int sctrl, err;
3326
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003327 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003328 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003329 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003330 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003331
3332
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003333 }
3334
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003335 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003336 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003337 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003338 return err;
3339 }
3340
3341 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003342 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003343
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003344 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
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. Padovan1890d362010-05-01 16:15:44 -03003347
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003348 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003349 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003350 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003351
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003352 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003353
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003354 __clear_ack_timer(chan);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003355
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003356 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003357
3358 return err;
3359}
3360
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003361static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003362{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003363 struct sk_buff *_skb;
3364 int err = -EINVAL;
3365
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003366 /*
3367 * TODO: We have to notify the userland if some data is lost with the
3368 * Streaming Mode.
3369 */
3370
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003371 switch (control & L2CAP_CTRL_SAR) {
3372 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003373 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003374 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003375 break;
3376 }
3377
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003378 err = chan->ops->recv(chan->data, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003379 if (!err)
3380 return 0;
3381
3382 break;
3383
3384 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003385 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003386 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003387 break;
3388 }
3389
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003390 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003391 skb_pull(skb, 2);
3392
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003393 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003394 err = -EMSGSIZE;
3395 break;
3396 }
3397
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003398 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3399 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003400 err = -ENOMEM;
3401 break;
3402 }
3403
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003404 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003405
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003406 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003407 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003408 err = 0;
3409 break;
3410
3411 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003412 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003413 break;
3414
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003415 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003416
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003417 chan->partial_sdu_len += skb->len;
3418 if (chan->partial_sdu_len > chan->sdu_len)
3419 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003420 else
3421 err = 0;
3422
3423 break;
3424
3425 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003426 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003427 break;
3428
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003429 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003430
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003431 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003432 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003433
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003434 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003435 goto drop;
3436
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003437 if (chan->partial_sdu_len == chan->sdu_len) {
3438 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003439 err = chan->ops->recv(chan->data, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003440 if (err < 0)
3441 kfree_skb(_skb);
3442 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003443 err = 0;
3444
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003445drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003446 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003447 break;
3448 }
3449
3450 kfree_skb(skb);
3451 return err;
3452}
3453
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003454static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003455{
3456 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003457 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003458
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003459 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003460 if (bt_cb(skb)->tx_seq != tx_seq)
3461 break;
3462
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003463 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003464 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003465 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003466 chan->buffer_seq_srej =
3467 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003468 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003469 }
3470}
3471
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003472static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003473{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003474 struct srej_list *l, *tmp;
3475 u16 control;
3476
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003477 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003478 if (l->tx_seq == tx_seq) {
3479 list_del(&l->list);
3480 kfree(l);
3481 return;
3482 }
3483 control = L2CAP_SUPER_SELECT_REJECT;
3484 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003485 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003486 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003487 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003488 }
3489}
3490
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003491static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003492{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003493 struct srej_list *new;
3494 u16 control;
3495
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003496 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003497 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003498 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003499 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003500
3501 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003502 new->tx_seq = chan->expected_tx_seq;
3503 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003504 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003505 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003506 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003507}
3508
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003509static 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 -03003510{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003511 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003512 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003513 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003514 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003515 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003516 int err = 0;
3517
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003518 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3519 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003520
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003521 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003522 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003523 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003524 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003525 __set_retrans_timer(chan);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003526 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003527 }
3528
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003529 chan->expected_ack_seq = req_seq;
3530 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003531
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003532 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003533 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003534
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003535 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003536 if (tx_seq_offset < 0)
3537 tx_seq_offset += 64;
3538
3539 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003540 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003541 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003542 goto drop;
3543 }
3544
Mat Martineaue6949282011-06-03 16:21:10 -07003545 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003546 goto drop;
3547
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003548 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003549 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003550
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003551 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003552 struct srej_list, list);
3553 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003554 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003555 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003556
3557 list_del(&first->list);
3558 kfree(first);
3559
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003560 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003561 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003562 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3563 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003564 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003565 }
3566 } else {
3567 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003568
3569 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003570 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003571 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003572
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003573 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003574 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003575 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003576 return 0;
3577 }
3578 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003579 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003580 }
3581 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003582 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003583 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003584 if (expected_tx_seq_offset < 0)
3585 expected_tx_seq_offset += 64;
3586
3587 /* duplicated tx_seq */
3588 if (tx_seq_offset < expected_tx_seq_offset)
3589 goto drop;
3590
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003591 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003592
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003593 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003594
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003595 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003596 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003597
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003598 __skb_queue_head_init(&chan->srej_q);
3599 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003600 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003601
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003602 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003603
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003604 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003605
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003606 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003607 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003608 return 0;
3609
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003610expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003611 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003612
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003613 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003614 bt_cb(skb)->tx_seq = tx_seq;
3615 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003616 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003617 return 0;
3618 }
3619
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003620 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003621 if (err < 0)
3622 return 0;
3623
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003624 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003625 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3626 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003627 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003628 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003629 }
3630
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003631 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003632
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003633 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3634 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003635 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003636
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003637 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003638
3639drop:
3640 kfree_skb(skb);
3641 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003642}
3643
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003644static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003645{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003646 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003647 rx_control);
3648
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003649 chan->expected_ack_seq = __get_reqseq(rx_control);
3650 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003651
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003652 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003653 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3654 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3655 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003656 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003657 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003658
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003659 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3660 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003661 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003662 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003663 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003664
3665 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003666 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003667
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003668 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3669 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003670 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003671 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003672
3673 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003674 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003675 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003676 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003677
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003678 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3679 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3680 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003681 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003682 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003683 }
3684}
3685
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003686static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003687{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003688 u8 tx_seq = __get_reqseq(rx_control);
3689
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003690 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003691
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003692 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003693
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003694 chan->expected_ack_seq = tx_seq;
3695 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003696
3697 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003698 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3699 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003700 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003701 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003702 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003703 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003704
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003705 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3706 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003707 }
3708}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003709static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003710{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003711 u8 tx_seq = __get_reqseq(rx_control);
3712
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003713 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003714
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003715 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003716
3717 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003718 chan->expected_ack_seq = tx_seq;
3719 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003720
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003721 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3722 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003723
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003724 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003725
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003726 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003727 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003728 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003729 }
3730 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003731 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003732 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003733 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003734 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003735 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003736 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003737 l2cap_retransmit_one_frame(chan, tx_seq);
3738 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003739 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003740 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003741 }
3742 }
3743}
3744
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003745static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003746{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003747 u8 tx_seq = __get_reqseq(rx_control);
3748
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003749 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003750
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003751 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003752 chan->expected_ack_seq = tx_seq;
3753 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003754
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003755 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003756 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003757
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003758 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003759 __clear_retrans_timer(chan);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003760 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003761 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003762 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003763 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003764
3765 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003766 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003767 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003768 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003769}
3770
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003771static 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 -03003772{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003773 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003774
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003775 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003776 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003777 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003778 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003779 __set_retrans_timer(chan);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003780 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003781 }
3782
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003783 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3784 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003785 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003786 break;
3787
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003788 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003789 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003790 break;
3791
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003792 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003793 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003794 break;
3795
3796 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003797 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003798 break;
3799 }
3800
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003801 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003802 return 0;
3803}
3804
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003805static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3806{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003807 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003808 u16 control;
3809 u8 req_seq;
3810 int len, next_tx_seq_offset, req_seq_offset;
3811
3812 control = get_unaligned_le16(skb->data);
3813 skb_pull(skb, 2);
3814 len = skb->len;
3815
3816 /*
3817 * We can just drop the corrupted I-frame here.
3818 * Receiver will miss it and start proper recovery
3819 * procedures and ask retransmission.
3820 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003821 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003822 goto drop;
3823
3824 if (__is_sar_start(control) && __is_iframe(control))
3825 len -= 2;
3826
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003827 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003828 len -= 2;
3829
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003830 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003831 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003832 goto drop;
3833 }
3834
3835 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003836 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003837 if (req_seq_offset < 0)
3838 req_seq_offset += 64;
3839
3840 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003841 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003842 if (next_tx_seq_offset < 0)
3843 next_tx_seq_offset += 64;
3844
3845 /* check for invalid req-seq */
3846 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003847 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003848 goto drop;
3849 }
3850
3851 if (__is_iframe(control)) {
3852 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003853 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003854 goto drop;
3855 }
3856
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003857 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003858 } else {
3859 if (len != 0) {
3860 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003861 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003862 goto drop;
3863 }
3864
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003865 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003866 }
3867
3868 return 0;
3869
3870drop:
3871 kfree_skb(skb);
3872 return 0;
3873}
3874
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3876{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003877 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003878 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003879 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003880 u8 tx_seq;
3881 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003883 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003884 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885 BT_DBG("unknown cid 0x%4.4x", cid);
3886 goto drop;
3887 }
3888
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003889 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003890
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003891 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003893 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894 goto drop;
3895
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003896 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003897 case L2CAP_MODE_BASIC:
3898 /* If socket recv buffers overflows we drop data here
3899 * which is *bad* because L2CAP has to be reliable.
3900 * But we don't have any other choice. L2CAP doesn't
3901 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003903 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003904 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003906 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003907 goto done;
3908 break;
3909
3910 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003911 if (!sock_owned_by_user(sk)) {
3912 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003913 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003914 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003915 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003916 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003917
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003918 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003919
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003920 case L2CAP_MODE_STREAMING:
3921 control = get_unaligned_le16(skb->data);
3922 skb_pull(skb, 2);
3923 len = skb->len;
3924
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003925 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003926 goto drop;
3927
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003928 if (__is_sar_start(control))
3929 len -= 2;
3930
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003931 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003932 len -= 2;
3933
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003934 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003935 goto drop;
3936
3937 tx_seq = __get_txseq(control);
3938
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003939 if (chan->expected_tx_seq == tx_seq)
3940 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003941 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003942 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003943
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003944 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003945
3946 goto done;
3947
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003948 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003949 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003950 break;
3951 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003952
3953drop:
3954 kfree_skb(skb);
3955
3956done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003957 if (sk)
3958 bh_unlock_sock(sk);
3959
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960 return 0;
3961}
3962
Al Viro8e036fc2007-07-29 00:16:36 -07003963static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003965 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003966 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003968 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3969 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970 goto drop;
3971
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003972 sk = chan->sk;
3973
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003974 bh_lock_sock(sk);
3975
Linus Torvalds1da177e2005-04-16 15:20:36 -07003976 BT_DBG("sk %p, len %d", sk, skb->len);
3977
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003978 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003979 goto drop;
3980
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003981 if (l2cap_pi(sk)->chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982 goto drop;
3983
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003984 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985 goto done;
3986
3987drop:
3988 kfree_skb(skb);
3989
3990done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003991 if (sk)
3992 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993 return 0;
3994}
3995
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003996static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3997{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003998 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003999 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004000
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004001 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4002 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004003 goto drop;
4004
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004005 sk = chan->sk;
4006
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004007 bh_lock_sock(sk);
4008
4009 BT_DBG("sk %p, len %d", sk, skb->len);
4010
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004011 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004012 goto drop;
4013
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004014 if (l2cap_pi(sk)->chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004015 goto drop;
4016
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004017 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004018 goto done;
4019
4020drop:
4021 kfree_skb(skb);
4022
4023done:
4024 if (sk)
4025 bh_unlock_sock(sk);
4026 return 0;
4027}
4028
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4030{
4031 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004032 u16 cid, len;
4033 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034
4035 skb_pull(skb, L2CAP_HDR_SIZE);
4036 cid = __le16_to_cpu(lh->cid);
4037 len = __le16_to_cpu(lh->len);
4038
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004039 if (len != skb->len) {
4040 kfree_skb(skb);
4041 return;
4042 }
4043
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4045
4046 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004047 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004048 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049 l2cap_sig_channel(conn, skb);
4050 break;
4051
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004052 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004053 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054 skb_pull(skb, 2);
4055 l2cap_conless_channel(conn, psm, skb);
4056 break;
4057
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004058 case L2CAP_CID_LE_DATA:
4059 l2cap_att_channel(conn, cid, skb);
4060 break;
4061
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004062 case L2CAP_CID_SMP:
4063 if (smp_sig_channel(conn, skb))
4064 l2cap_conn_del(conn->hcon, EACCES);
4065 break;
4066
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067 default:
4068 l2cap_data_channel(conn, cid, skb);
4069 break;
4070 }
4071}
4072
4073/* ---- L2CAP interface with lower layer (HCI) ---- */
4074
4075static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4076{
4077 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004078 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079
4080 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004081 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082
4083 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4084
4085 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004086 read_lock(&chan_list_lock);
4087 list_for_each_entry(c, &chan_list, global_l) {
4088 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004089
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004090 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091 continue;
4092
4093 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004094 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004095 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004096 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004098 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4099 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004100 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004101 lm2 |= HCI_LM_MASTER;
4102 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004104 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105
4106 return exact ? lm1 : lm2;
4107}
4108
4109static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4110{
Marcel Holtmann01394182006-07-03 10:02:46 +02004111 struct l2cap_conn *conn;
4112
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4114
Ville Tervoacd7d372011-02-10 22:38:49 -03004115 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004116 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117
4118 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119 conn = l2cap_conn_add(hcon, status);
4120 if (conn)
4121 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004122 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123 l2cap_conn_del(hcon, bt_err(status));
4124
4125 return 0;
4126}
4127
Marcel Holtmann2950f212009-02-12 14:02:50 +01004128static int l2cap_disconn_ind(struct hci_conn *hcon)
4129{
4130 struct l2cap_conn *conn = hcon->l2cap_data;
4131
4132 BT_DBG("hcon %p", hcon);
4133
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03004134 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004135 return 0x13;
4136
4137 return conn->disc_reason;
4138}
4139
4140static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004141{
4142 BT_DBG("hcon %p reason %d", hcon, reason);
4143
Ville Tervoacd7d372011-02-10 22:38:49 -03004144 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004145 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146
4147 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004148
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149 return 0;
4150}
4151
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004152static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004153{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004154 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004155 return;
4156
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004157 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004158 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004159 __clear_chan_timer(chan);
4160 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004161 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004162 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004163 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004164 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004165 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004166 }
4167}
4168
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004169static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004171 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004172 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173
Marcel Holtmann01394182006-07-03 10:02:46 +02004174 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004176
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177 BT_DBG("conn %p", conn);
4178
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004179 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004180
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004181 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004182 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004183
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184 bh_lock_sock(sk);
4185
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004186 BT_DBG("chan->scid %d", chan->scid);
4187
4188 if (chan->scid == L2CAP_CID_LE_DATA) {
4189 if (!status && encrypt) {
4190 chan->sec_level = hcon->sec_level;
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03004191 del_timer(&conn->security_timer);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004192 l2cap_chan_ready(sk);
4193 }
4194
4195 bh_unlock_sock(sk);
4196 continue;
4197 }
4198
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004199 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004200 bh_unlock_sock(sk);
4201 continue;
4202 }
4203
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004204 if (!status && (chan->state == BT_CONNECTED ||
4205 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004206 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004207 bh_unlock_sock(sk);
4208 continue;
4209 }
4210
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004211 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004212 if (!status) {
4213 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004214 req.scid = cpu_to_le16(chan->scid);
4215 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004216
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004217 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004218 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004219
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004220 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004221 L2CAP_CONN_REQ, sizeof(req), &req);
4222 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004223 __clear_chan_timer(chan);
4224 __set_chan_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004225 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004226 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004227 struct l2cap_conn_rsp rsp;
4228 __u16 result;
4229
4230 if (!status) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004231 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004232 result = L2CAP_CR_SUCCESS;
4233 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004234 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004235 __set_chan_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004236 result = L2CAP_CR_SEC_BLOCK;
4237 }
4238
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004239 rsp.scid = cpu_to_le16(chan->dcid);
4240 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004241 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02004242 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004243 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4244 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245 }
4246
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247 bh_unlock_sock(sk);
4248 }
4249
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004250 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004251
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252 return 0;
4253}
4254
4255static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4256{
4257 struct l2cap_conn *conn = hcon->l2cap_data;
4258
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004259 if (!conn)
4260 conn = l2cap_conn_add(hcon, 0);
4261
4262 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004263 goto drop;
4264
4265 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4266
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004267 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004269 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004270 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271 int len;
4272
4273 if (conn->rx_len) {
4274 BT_ERR("Unexpected start frame (len %d)", skb->len);
4275 kfree_skb(conn->rx_skb);
4276 conn->rx_skb = NULL;
4277 conn->rx_len = 0;
4278 l2cap_conn_unreliable(conn, ECOMM);
4279 }
4280
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004281 /* Start fragment always begin with Basic L2CAP header */
4282 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283 BT_ERR("Frame is too short (len %d)", skb->len);
4284 l2cap_conn_unreliable(conn, ECOMM);
4285 goto drop;
4286 }
4287
4288 hdr = (struct l2cap_hdr *) skb->data;
4289 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004290 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291
4292 if (len == skb->len) {
4293 /* Complete frame received */
4294 l2cap_recv_frame(conn, skb);
4295 return 0;
4296 }
4297
4298 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4299
4300 if (skb->len > len) {
4301 BT_ERR("Frame is too long (len %d, expected len %d)",
4302 skb->len, len);
4303 l2cap_conn_unreliable(conn, ECOMM);
4304 goto drop;
4305 }
4306
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004307 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004308
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004309 if (chan && chan->sk) {
4310 struct sock *sk = chan->sk;
4311
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004312 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004313 BT_ERR("Frame exceeding recv MTU (len %d, "
4314 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004315 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004316 bh_unlock_sock(sk);
4317 l2cap_conn_unreliable(conn, ECOMM);
4318 goto drop;
4319 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004320 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004321 }
4322
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004324 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4325 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326 goto drop;
4327
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004328 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004329 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330 conn->rx_len = len - skb->len;
4331 } else {
4332 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4333
4334 if (!conn->rx_len) {
4335 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4336 l2cap_conn_unreliable(conn, ECOMM);
4337 goto drop;
4338 }
4339
4340 if (skb->len > conn->rx_len) {
4341 BT_ERR("Fragment is too long (len %d, expected %d)",
4342 skb->len, conn->rx_len);
4343 kfree_skb(conn->rx_skb);
4344 conn->rx_skb = NULL;
4345 conn->rx_len = 0;
4346 l2cap_conn_unreliable(conn, ECOMM);
4347 goto drop;
4348 }
4349
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004350 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004351 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352 conn->rx_len -= skb->len;
4353
4354 if (!conn->rx_len) {
4355 /* Complete frame received */
4356 l2cap_recv_frame(conn, conn->rx_skb);
4357 conn->rx_skb = NULL;
4358 }
4359 }
4360
4361drop:
4362 kfree_skb(skb);
4363 return 0;
4364}
4365
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004366static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004368 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004370 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004372 list_for_each_entry(c, &chan_list, global_l) {
4373 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004375 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 +01004376 batostr(&bt_sk(sk)->src),
4377 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004378 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004379 c->scid, c->dcid, c->imtu, c->omtu,
4380 c->sec_level, c->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004381 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004383 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004384
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004385 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004386}
4387
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004388static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4389{
4390 return single_open(file, l2cap_debugfs_show, inode->i_private);
4391}
4392
4393static const struct file_operations l2cap_debugfs_fops = {
4394 .open = l2cap_debugfs_open,
4395 .read = seq_read,
4396 .llseek = seq_lseek,
4397 .release = single_release,
4398};
4399
4400static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402static struct hci_proto l2cap_hci_proto = {
4403 .name = "L2CAP",
4404 .id = HCI_PROTO_L2CAP,
4405 .connect_ind = l2cap_connect_ind,
4406 .connect_cfm = l2cap_connect_cfm,
4407 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004408 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004409 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410 .recv_acldata = l2cap_recv_acldata
4411};
4412
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004413int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414{
4415 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004416
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004417 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418 if (err < 0)
4419 return err;
4420
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004421 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004422 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004423 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424 goto error;
4425 }
4426
4427 err = hci_register_proto(&l2cap_hci_proto);
4428 if (err < 0) {
4429 BT_ERR("L2CAP protocol registration failed");
4430 bt_sock_unregister(BTPROTO_L2CAP);
4431 goto error;
4432 }
4433
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004434 if (bt_debugfs) {
4435 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4436 bt_debugfs, NULL, &l2cap_debugfs_fops);
4437 if (!l2cap_debugfs)
4438 BT_ERR("Failed to create L2CAP debug file");
4439 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440
Linus Torvalds1da177e2005-04-16 15:20:36 -07004441 return 0;
4442
4443error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004444 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004445 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446 return err;
4447}
4448
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004449void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004450{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004451 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004453 flush_workqueue(_busy_wq);
4454 destroy_workqueue(_busy_wq);
4455
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4457 BT_ERR("L2CAP protocol unregistration failed");
4458
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004459 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004460}
4461
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004462module_param(disable_ertm, bool, 0644);
4463MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");