blob: 942ba1d1a38c88e3ab061ae698d477000f1b0b56 [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.
Gustavo F. Padovan590051d2011-12-18 13:39:33 -02006 Copyright (C) 2011 ProFUSION Embedded Systems
Linus Torvalds1da177e2005-04-16 15:20:36 -07007
8 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License version 2 as
12 published by the Free Software Foundation;
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
17 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090018 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090023 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
24 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070025 SOFTWARE IS DISCLAIMED.
26*/
27
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020028/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070029
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/module.h>
31
32#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080033#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/errno.h>
35#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/sched.h>
37#include <linux/slab.h>
38#include <linux/poll.h>
39#include <linux/fcntl.h>
40#include <linux/init.h>
41#include <linux/interrupt.h>
42#include <linux/socket.h>
43#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080045#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010046#include <linux/debugfs.h>
47#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030048#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030049#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#include <net/sock.h>
51
52#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070053#include <asm/unaligned.h>
54
55#include <net/bluetooth/bluetooth.h>
56#include <net/bluetooth/hci_core.h>
57#include <net/bluetooth/l2cap.h>
Anderson Brigliab501d6a2011-06-07 18:46:31 -030058#include <net/bluetooth/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
Rusty Russelleb939922011-12-19 14:08:01 +000060bool disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020061
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070062static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Mat Martineau50a147c2011-11-02 16:18:34 -070063static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Johannes Bergb5ad8b72011-06-01 08:54:45 +020065static LIST_HEAD(chan_list);
66static DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Linus Torvalds1da177e2005-04-16 15:20:36 -070068static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
69 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030070static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
71 void *data);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -030072static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030073static void l2cap_send_disconn_req(struct l2cap_conn *conn,
74 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
Marcel Holtmann01394182006-07-03 10:02:46 +020076/* ---- L2CAP channels ---- */
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -030077
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030078static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020079{
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -020080 struct l2cap_chan *c, *r = NULL;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030081
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -020082 rcu_read_lock();
83
84 list_for_each_entry_rcu(c, &conn->chan_l, list) {
85 if (c->dcid == cid) {
86 r = c;
87 break;
88 }
Marcel Holtmann01394182006-07-03 10:02:46 +020089 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -020090
91 rcu_read_unlock();
92 return r;
Marcel Holtmann01394182006-07-03 10:02:46 +020093}
94
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030095static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020096{
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -020097 struct l2cap_chan *c, *r = NULL;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030098
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -020099 rcu_read_lock();
100
101 list_for_each_entry_rcu(c, &conn->chan_l, list) {
102 if (c->scid == cid) {
103 r = c;
104 break;
105 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200106 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200107
108 rcu_read_unlock();
109 return r;
Marcel Holtmann01394182006-07-03 10:02:46 +0200110}
111
112/* Find channel with given SCID.
113 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300114static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200115{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300116 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300117
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300118 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300119 if (c)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300120 lock_sock(c->sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300121 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200122}
123
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300124static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200125{
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200126 struct l2cap_chan *c, *r = NULL;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300127
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200128 rcu_read_lock();
129
130 list_for_each_entry_rcu(c, &conn->chan_l, list) {
131 if (c->ident == ident) {
132 r = c;
133 break;
134 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200135 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200136
137 rcu_read_unlock();
138 return r;
Marcel Holtmann01394182006-07-03 10:02:46 +0200139}
140
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300141static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200142{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300143 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300144
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300145 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300146 if (c)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300147 lock_sock(c->sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300148 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200149}
150
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300151static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300152{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300153 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300154
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300155 list_for_each_entry(c, &chan_list, global_l) {
156 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Szymon Janc250938c2011-11-16 09:32:22 +0100157 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300158 }
Szymon Janc250938c2011-11-16 09:32:22 +0100159 return NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300160}
161
162int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
163{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300164 int err;
165
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200166 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300167
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300168 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300169 err = -EADDRINUSE;
170 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300171 }
172
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300173 if (psm) {
174 chan->psm = psm;
175 chan->sport = psm;
176 err = 0;
177 } else {
178 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300179
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300180 err = -EINVAL;
181 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300182 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300183 chan->psm = cpu_to_le16(p);
184 chan->sport = cpu_to_le16(p);
185 err = 0;
186 break;
187 }
188 }
189
190done:
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200191 write_unlock(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300192 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300193}
194
195int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
196{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200197 write_lock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300198
199 chan->scid = scid;
200
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200201 write_unlock(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300202
203 return 0;
204}
205
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300206static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200207{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300208 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200209
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300210 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300211 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200212 return cid;
213 }
214
215 return 0;
216}
217
Gustavo F. Padovanbadaaa02011-11-23 20:11:46 -0200218static char *state_to_string(int state)
219{
220 switch(state) {
221 case BT_CONNECTED:
222 return "BT_CONNECTED";
223 case BT_OPEN:
224 return "BT_OPEN";
225 case BT_BOUND:
226 return "BT_BOUND";
227 case BT_LISTEN:
228 return "BT_LISTEN";
229 case BT_CONNECT:
230 return "BT_CONNECT";
231 case BT_CONNECT2:
232 return "BT_CONNECT2";
233 case BT_CONFIG:
234 return "BT_CONFIG";
235 case BT_DISCONN:
236 return "BT_DISCONN";
237 case BT_CLOSED:
238 return "BT_CLOSED";
239 }
240
241 return "invalid state";
242}
243
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300244static void l2cap_state_change(struct l2cap_chan *chan, int state)
245{
Gustavo F. Padovanbadaaa02011-11-23 20:11:46 -0200246 BT_DBG("%p %s -> %s", chan, state_to_string(chan->state),
247 state_to_string(state));
248
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300249 chan->state = state;
250 chan->ops->state_change(chan->data, state);
251}
252
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300253static void l2cap_chan_timeout(struct work_struct *work)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300254{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300255 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
256 chan_timer.work);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300257 struct sock *sk = chan->sk;
258 int reason;
259
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300260 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300261
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300262 lock_sock(sk);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300263
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
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300274 release_sock(sk);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300275
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300276 chan->ops->close(chan->data);
Ulisses Furquim371fd832011-12-21 20:02:36 -0200277 l2cap_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. Padovan333055f2011-12-22 15:14:39 -0200290 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300291 list_add(&chan->global_l, &chan_list);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200292 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300293
Gustavo F. Padovan721c4182011-06-23 19:29:58 -0300294 INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300295
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
Szymon Jancabc545b2011-11-03 16:05:44 +0100300 BT_DBG("sk %p chan %p", sk, chan);
301
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300302 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200303}
304
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300305void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300306{
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200307 write_lock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300308 list_del(&chan->global_l);
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200309 write_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300310
Ulisses Furquim371fd832011-12-21 20:02:36 -0200311 l2cap_chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300312}
313
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200314static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200315{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300316 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300317 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200318
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +0200319 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100320
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300321 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200322
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300323 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
Ville Tervob62f3282011-02-10 22:38:50 -0300324 if (conn->hcon->type == LE_LINK) {
325 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300326 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300327 chan->scid = L2CAP_CID_LE_DATA;
328 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300329 } else {
330 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300331 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300332 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300333 }
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300334 } else if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200335 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300336 chan->scid = L2CAP_CID_CONN_LESS;
337 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300338 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200339 } else {
340 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300341 chan->scid = L2CAP_CID_SIGNALING;
342 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300343 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200344 }
345
Andrei Emeltchenko8f7975b2011-10-13 16:18:54 +0300346 chan->local_id = L2CAP_BESTEFFORT_ID;
347 chan->local_stype = L2CAP_SERV_BESTEFFORT;
348 chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
349 chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
350 chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
351 chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
352
Ulisses Furquim371fd832011-12-21 20:02:36 -0200353 l2cap_chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300354
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200355 list_add_rcu(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200356}
357
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900358/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200359 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300360static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200361{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300362 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300363 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200364 struct sock *parent = bt_sk(sk)->parent;
365
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300366 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200367
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300368 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200369
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900370 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300371 /* Delete from channel list */
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200372 list_del_rcu(&chan->list);
373 synchronize_rcu();
374
Ulisses Furquim371fd832011-12-21 20:02:36 -0200375 l2cap_chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300376
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300377 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200378 hci_conn_put(conn->hcon);
379 }
380
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300381 l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200382 sock_set_flag(sk, SOCK_ZAPPED);
383
384 if (err)
385 sk->sk_err = err;
386
387 if (parent) {
388 bt_accept_unlink(sk);
389 parent->sk_data_ready(parent, 0);
390 } else
391 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300392
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300393 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
394 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300395 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300396
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300397 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300398
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300399 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300400 struct srej_list *l, *tmp;
401
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300402 __clear_retrans_timer(chan);
403 __clear_monitor_timer(chan);
404 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300405
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300406 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300407
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300408 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300409 list_del(&l->list);
410 kfree(l);
411 }
412 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200413}
414
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300415static void l2cap_chan_cleanup_listen(struct sock *parent)
416{
417 struct sock *sk;
418
419 BT_DBG("parent %p", parent);
420
421 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300422 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300423 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300424 __clear_chan_timer(chan);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300425 lock_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300426 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300427 release_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300428 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300429 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300430}
431
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300432void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300433{
434 struct l2cap_conn *conn = chan->conn;
435 struct sock *sk = chan->sk;
436
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300437 BT_DBG("chan %p state %d socket %p", chan, chan->state, sk->sk_socket);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300438
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300439 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300440 case BT_LISTEN:
441 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300442
443 l2cap_state_change(chan, BT_CLOSED);
444 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300445 break;
446
447 case BT_CONNECTED:
448 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300449 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300450 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300451 __clear_chan_timer(chan);
452 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300453 l2cap_send_disconn_req(conn, chan, reason);
454 } else
455 l2cap_chan_del(chan, reason);
456 break;
457
458 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300459 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300460 conn->hcon->type == ACL_LINK) {
461 struct l2cap_conn_rsp rsp;
462 __u16 result;
463
464 if (bt_sk(sk)->defer_setup)
465 result = L2CAP_CR_SEC_BLOCK;
466 else
467 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300468 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300469
470 rsp.scid = cpu_to_le16(chan->dcid);
471 rsp.dcid = cpu_to_le16(chan->scid);
472 rsp.result = cpu_to_le16(result);
473 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
474 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
475 sizeof(rsp), &rsp);
476 }
477
478 l2cap_chan_del(chan, reason);
479 break;
480
481 case BT_CONNECT:
482 case BT_DISCONN:
483 l2cap_chan_del(chan, reason);
484 break;
485
486 default:
487 sock_set_flag(sk, SOCK_ZAPPED);
488 break;
489 }
490}
491
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300492static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530493{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300494 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300495 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530496 case BT_SECURITY_HIGH:
497 return HCI_AT_DEDICATED_BONDING_MITM;
498 case BT_SECURITY_MEDIUM:
499 return HCI_AT_DEDICATED_BONDING;
500 default:
501 return HCI_AT_NO_BONDING;
502 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300503 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300504 if (chan->sec_level == BT_SECURITY_LOW)
505 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530506
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300507 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530508 return HCI_AT_NO_BONDING_MITM;
509 else
510 return HCI_AT_NO_BONDING;
511 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300512 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530513 case BT_SECURITY_HIGH:
514 return HCI_AT_GENERAL_BONDING_MITM;
515 case BT_SECURITY_MEDIUM:
516 return HCI_AT_GENERAL_BONDING;
517 default:
518 return HCI_AT_NO_BONDING;
519 }
520 }
521}
522
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200523/* Service level security */
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200524int l2cap_chan_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200525{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300526 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100527 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200528
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300529 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100530
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300531 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200532}
533
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200534static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200535{
536 u8 id;
537
538 /* Get next available identificator.
539 * 1 - 128 are used by kernel.
540 * 129 - 199 are reserved.
541 * 200 - 254 are used by utilities like l2ping, etc.
542 */
543
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200544 spin_lock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200545
546 if (++conn->tx_ident > 128)
547 conn->tx_ident = 1;
548
549 id = conn->tx_ident;
550
Gustavo F. Padovan333055f2011-12-22 15:14:39 -0200551 spin_unlock(&conn->lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200552
553 return id;
554}
555
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300556static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200557{
558 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200559 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200560
561 BT_DBG("code 0x%2.2x", code);
562
563 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300564 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200565
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200566 if (lmp_no_flush_capable(conn->hcon->hdev))
567 flags = ACL_START_NO_FLUSH;
568 else
569 flags = ACL_START;
570
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700571 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +0200572 skb->priority = HCI_PRIO_MAX;
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700573
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200574 hci_send_acl(conn->hchan, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200575}
576
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200577static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
578{
579 struct hci_conn *hcon = chan->conn->hcon;
580 u16 flags;
581
582 BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
583 skb->priority);
584
585 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
586 lmp_no_flush_capable(hcon->hdev))
587 flags = ACL_START_NO_FLUSH;
588 else
589 flags = ACL_START;
590
591 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
592 hci_send_acl(chan->conn->hchan, skb, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593}
594
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300595static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300596{
597 struct sk_buff *skb;
598 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300599 struct l2cap_conn *conn = chan->conn;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300600 int count, hlen;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300601
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300602 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300603 return;
604
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300605 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
606 hlen = L2CAP_EXT_HDR_SIZE;
607 else
608 hlen = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300609
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300610 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300611 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300612
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300613 BT_DBG("chan %p, control 0x%8.8x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300614
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300615 count = min_t(unsigned int, conn->mtu, hlen);
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +0300616
617 control |= __set_sframe(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300618
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300619 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +0300620 control |= __set_ctrl_final(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300621
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300622 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +0300623 control |= __set_ctrl_poll(chan);
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300624
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300625 skb = bt_skb_alloc(count, GFP_ATOMIC);
626 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300627 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300628
629 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300630 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300631 lh->cid = cpu_to_le16(chan->dcid);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300632
633 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300634
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300635 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +0300636 u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
637 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300638 }
639
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200640 skb->priority = HCI_PRIO_MAX;
641 l2cap_do_send(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300642}
643
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +0300644static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300645{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300646 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300647 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300648 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300649 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300650 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300651
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300652 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300653
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300654 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300655}
656
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300657static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300658{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300659 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300660}
661
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300662static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200663{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300664 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200665
666 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100667 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
668 return;
669
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200670 if (l2cap_chan_check_security(chan) &&
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300671 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200672 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300673 req.scid = cpu_to_le16(chan->scid);
674 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200675
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300676 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300677 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200678
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300679 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
680 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200681 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200682 } else {
683 struct l2cap_info_req req;
684 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
685
686 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
687 conn->info_ident = l2cap_get_ident(conn);
688
Gustavo F. Padovan030013d2011-12-20 10:57:28 -0200689 schedule_delayed_work(&conn->info_timer,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200690 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
691
692 l2cap_send_cmd(conn, conn->info_ident,
693 L2CAP_INFO_REQ, sizeof(req), &req);
694 }
695}
696
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300697static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
698{
699 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300700 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300701 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
702
703 switch (mode) {
704 case L2CAP_MODE_ERTM:
705 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
706 case L2CAP_MODE_STREAMING:
707 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
708 default:
709 return 0x00;
710 }
711}
712
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300713static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300714{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300715 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300716 struct l2cap_disconn_req req;
717
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300718 if (!conn)
719 return;
720
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300721 sk = chan->sk;
722
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300723 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300724 __clear_retrans_timer(chan);
725 __clear_monitor_timer(chan);
726 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300727 }
728
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300729 req.dcid = cpu_to_le16(chan->dcid);
730 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300731 l2cap_send_cmd(conn, l2cap_get_ident(conn),
732 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300733
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300734 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300735 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300736}
737
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200739static void l2cap_conn_start(struct l2cap_conn *conn)
740{
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200741 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200742
743 BT_DBG("conn %p", conn);
744
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200745 rcu_read_lock();
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200746
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200747 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300748 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300749
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200750 bh_lock_sock(sk);
751
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300752 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200753 bh_unlock_sock(sk);
754 continue;
755 }
756
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300757 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300758 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300759
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200760 if (!l2cap_chan_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300761 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300762 bh_unlock_sock(sk);
763 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200764 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300765
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300766 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
767 && test_bit(CONF_STATE2_DEVICE,
768 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300769 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300770 * so release the lock */
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300771 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300772 bh_unlock_sock(sk);
773 continue;
774 }
775
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300776 req.scid = cpu_to_le16(chan->scid);
777 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300778
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300779 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300780 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300781
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300782 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
783 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300784
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300785 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200786 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300787 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300788 rsp.scid = cpu_to_le16(chan->dcid);
789 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200790
Gustavo F. Padovand45fc422011-11-05 19:54:24 -0200791 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100792 if (bt_sk(sk)->defer_setup) {
793 struct sock *parent = bt_sk(sk)->parent;
794 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
795 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000796 if (parent)
797 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100798
799 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300800 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100801 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
802 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
803 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200804 } else {
805 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
806 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
807 }
808
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300809 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
810 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300811
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300812 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300813 rsp.result != L2CAP_CR_SUCCESS) {
814 bh_unlock_sock(sk);
815 continue;
816 }
817
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300818 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300819 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300820 l2cap_build_conf_req(chan, buf), buf);
821 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200822 }
823
824 bh_unlock_sock(sk);
825 }
826
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200827 rcu_read_unlock();
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200828}
829
Ville Tervob62f3282011-02-10 22:38:50 -0300830/* Find socket with cid and source bdaddr.
831 * Returns closest match, locked.
832 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300833static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300834{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300835 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300836
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300837 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300838
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300839 list_for_each_entry(c, &chan_list, global_l) {
840 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300841
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300842 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300843 continue;
844
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300845 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300846 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300847 if (!bacmp(&bt_sk(sk)->src, src)) {
848 read_unlock(&chan_list_lock);
849 return c;
850 }
Ville Tervob62f3282011-02-10 22:38:50 -0300851
852 /* Closest match */
853 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300854 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300855 }
856 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300857
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300858 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300859
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300860 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300861}
862
863static void l2cap_le_conn_ready(struct l2cap_conn *conn)
864{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300865 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300866 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300867
868 BT_DBG("");
869
870 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300871 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300872 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300873 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300874 return;
875
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300876 parent = pchan->sk;
877
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300878 lock_sock(parent);
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300879
Ville Tervob62f3282011-02-10 22:38:50 -0300880 /* Check for backlog size */
881 if (sk_acceptq_is_full(parent)) {
882 BT_DBG("backlog full %d", parent->sk_ack_backlog);
883 goto clean;
884 }
885
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300886 chan = pchan->ops->new_connection(pchan->data);
887 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300888 goto clean;
889
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300890 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300891
Ville Tervob62f3282011-02-10 22:38:50 -0300892 hci_conn_hold(conn->hcon);
893
Ville Tervob62f3282011-02-10 22:38:50 -0300894 bacpy(&bt_sk(sk)->src, conn->src);
895 bacpy(&bt_sk(sk)->dst, conn->dst);
896
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300897 bt_accept_enqueue(parent, sk);
898
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200899 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300900
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300901 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300902
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300903 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300904 parent->sk_data_ready(parent, 0);
905
Ville Tervob62f3282011-02-10 22:38:50 -0300906clean:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -0300907 release_sock(parent);
Ville Tervob62f3282011-02-10 22:38:50 -0300908}
909
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300910static void l2cap_chan_ready(struct sock *sk)
911{
912 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
913 struct sock *parent = bt_sk(sk)->parent;
914
915 BT_DBG("sk %p, parent %p", sk, parent);
916
917 chan->conf_state = 0;
918 __clear_chan_timer(chan);
919
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300920 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300921 sk->sk_state_change(sk);
922
923 if (parent)
924 parent->sk_data_ready(parent, 0);
925}
926
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200927static void l2cap_conn_ready(struct l2cap_conn *conn)
928{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300929 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200930
931 BT_DBG("conn %p", conn);
932
Ville Tervob62f3282011-02-10 22:38:50 -0300933 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
934 l2cap_le_conn_ready(conn);
935
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300936 if (conn->hcon->out && conn->hcon->type == LE_LINK)
937 smp_conn_security(conn, conn->hcon->pending_sec_level);
938
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200939 rcu_read_lock();
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200940
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200941 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300942 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300943
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200944 bh_lock_sock(sk);
945
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300946 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300947 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300948 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300949
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300950 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300951 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300952 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200953 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300954
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300955 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300956 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200957
958 bh_unlock_sock(sk);
959 }
960
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200961 rcu_read_unlock();
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200962}
963
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200964/* Notify sockets that we cannot guaranty reliability anymore */
965static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
966{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300967 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200968
969 BT_DBG("conn %p", conn);
970
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200971 rcu_read_lock();
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200972
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200973 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300974 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300975
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300976 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200977 sk->sk_err = err;
978 }
979
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -0200980 rcu_read_unlock();
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200981}
982
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -0200983static void l2cap_info_timeout(struct work_struct *work)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200984{
Gustavo F. Padovanf878fca2011-12-15 01:16:14 -0200985 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
Gustavo F. Padovan030013d2011-12-20 10:57:28 -0200986 info_timer.work);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200987
Marcel Holtmann984947d2009-02-06 23:35:19 +0100988 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100989 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100990
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200991 l2cap_conn_start(conn);
992}
993
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300994static void l2cap_conn_del(struct hci_conn *hcon, int err)
995{
996 struct l2cap_conn *conn = hcon->l2cap_data;
997 struct l2cap_chan *chan, *l;
998 struct sock *sk;
999
1000 if (!conn)
1001 return;
1002
1003 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
1004
1005 kfree_skb(conn->rx_skb);
1006
1007 /* Kill channels */
1008 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
1009 sk = chan->sk;
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001010 lock_sock(sk);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001011 l2cap_chan_del(chan, err);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03001012 release_sock(sk);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001013 chan->ops->close(chan->data);
1014 }
1015
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001016 hci_chan_del(conn->hchan);
1017
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001018 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
Ulisses Furquim371fd832011-12-21 20:02:36 -02001019 __cancel_delayed_work(&conn->info_timer);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001020
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001021 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
Ulisses Furquim371fd832011-12-21 20:02:36 -02001022 __cancel_delayed_work(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001023 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001024 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001025
1026 hcon->l2cap_data = NULL;
1027 kfree(conn);
1028}
1029
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001030static void security_timeout(struct work_struct *work)
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001031{
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001032 struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1033 security_timer.work);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001034
1035 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1036}
1037
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1039{
Marcel Holtmann01394182006-07-03 10:02:46 +02001040 struct l2cap_conn *conn = hcon->l2cap_data;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001041 struct hci_chan *hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042
Marcel Holtmann01394182006-07-03 10:02:46 +02001043 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 return conn;
1045
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001046 hchan = hci_chan_create(hcon);
1047 if (!hchan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001050 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1051 if (!conn) {
1052 hci_chan_del(hchan);
1053 return NULL;
1054 }
1055
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 hcon->l2cap_data = conn;
1057 conn->hcon = hcon;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001058 conn->hchan = hchan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +02001060 BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
Marcel Holtmann01394182006-07-03 10:02:46 +02001061
Ville Tervoacd7d372011-02-10 22:38:49 -03001062 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1063 conn->mtu = hcon->hdev->le_mtu;
1064 else
1065 conn->mtu = hcon->hdev->acl_mtu;
1066
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 conn->src = &hcon->hdev->bdaddr;
1068 conn->dst = &hcon->dst;
1069
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001070 conn->feat_mask = 0;
1071
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001073
1074 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001076 if (hcon->type == LE_LINK)
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001077 INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001078 else
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02001079 INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
Dave Young45054dc2009-10-18 20:28:30 +00001080
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02001081 conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01001082
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 return conn;
1084}
1085
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
1088/* Find socket with psm and source bdaddr.
1089 * Returns closest match.
1090 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001091static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001093 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001095 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001096
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001097 list_for_each_entry(c, &chan_list, global_l) {
1098 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001099
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001100 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 continue;
1102
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001103 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001105 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001106 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001107 return c;
1108 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109
1110 /* Closest match */
1111 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001112 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 }
1114 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001116 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001117
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001118 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119}
1120
Johan Hedbergcbe8fed2012-01-08 22:51:16 +02001121int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001123 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 bdaddr_t *src = &bt_sk(sk)->src;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 struct l2cap_conn *conn;
1126 struct hci_conn *hcon;
1127 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001128 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001129 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001131 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001132 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001134 hdev = hci_get_route(dst, src);
1135 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 return -EHOSTUNREACH;
1137
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001138 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001140 lock_sock(sk);
1141
1142 /* PSM must be odd and lsb of upper byte must be 0 */
1143 if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
1144 chan->chan_type != L2CAP_CHAN_RAW) {
1145 err = -EINVAL;
1146 goto done;
1147 }
1148
1149 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
1150 err = -EINVAL;
1151 goto done;
1152 }
1153
1154 switch (chan->mode) {
1155 case L2CAP_MODE_BASIC:
1156 break;
1157 case L2CAP_MODE_ERTM:
1158 case L2CAP_MODE_STREAMING:
1159 if (!disable_ertm)
1160 break;
1161 /* fall through */
1162 default:
1163 err = -ENOTSUPP;
1164 goto done;
1165 }
1166
1167 switch (sk->sk_state) {
1168 case BT_CONNECT:
1169 case BT_CONNECT2:
1170 case BT_CONFIG:
1171 /* Already connecting */
1172 err = 0;
1173 goto done;
1174
1175 case BT_CONNECTED:
1176 /* Already connected */
1177 err = -EISCONN;
1178 goto done;
1179
1180 case BT_OPEN:
1181 case BT_BOUND:
1182 /* Can connect */
1183 break;
1184
1185 default:
1186 err = -EBADFD;
1187 goto done;
1188 }
1189
1190 /* Set destination address and psm */
Gustavo F. Padovan9219b2a2012-01-02 20:08:04 -02001191 bacpy(&bt_sk(sk)->dst, dst);
Gustavo F. Padovan03a00192011-12-09 04:48:17 -02001192 chan->psm = psm;
1193 chan->dcid = cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001195 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001196
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001197 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001198 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001199 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001200 else
1201 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001202 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001203
Ville Tervo30e76272011-02-22 16:10:53 -03001204 if (IS_ERR(hcon)) {
1205 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001207 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208
1209 conn = l2cap_conn_add(hcon, 0);
1210 if (!conn) {
1211 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001212 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 goto done;
1214 }
1215
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 /* Update source addr of the socket */
1217 bacpy(src, conn->src);
1218
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001219 l2cap_chan_add(conn, chan);
1220
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001221 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001222 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223
1224 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001225 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001226 __clear_chan_timer(chan);
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02001227 if (l2cap_chan_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001228 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001229 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001230 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 }
1232
Ville Tervo30e76272011-02-22 16:10:53 -03001233 err = 0;
1234
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001236 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 hci_dev_put(hdev);
1238 return err;
1239}
1240
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001241int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001242{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001243 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001244 DECLARE_WAITQUEUE(wait, current);
1245 int err = 0;
1246 int timeo = HZ/5;
1247
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001248 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001249 set_current_state(TASK_INTERRUPTIBLE);
1250 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001251 if (!timeo)
1252 timeo = HZ/5;
1253
1254 if (signal_pending(current)) {
1255 err = sock_intr_errno(timeo);
1256 break;
1257 }
1258
1259 release_sock(sk);
1260 timeo = schedule_timeout(timeo);
1261 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001262 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001263
1264 err = sock_error(sk);
1265 if (err)
1266 break;
1267 }
1268 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001269 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001270 return err;
1271}
1272
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001273static void l2cap_monitor_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001274{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001275 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1276 monitor_timer.work);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001277 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001278
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001279 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001280
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001281 lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001282 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001283 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001284 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001285 return;
1286 }
1287
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001288 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001289 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001290
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001291 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001292 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001293}
1294
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001295static void l2cap_retrans_timeout(struct work_struct *work)
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001296{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001297 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1298 retrans_timer.work);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001299 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001300
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001301 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001302
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001303 lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001304 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001305 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001306
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001307 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001308
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001309 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001310 release_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001311}
1312
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001313static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001314{
1315 struct sk_buff *skb;
1316
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001317 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001318 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001319 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001320 break;
1321
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001322 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001323 kfree_skb(skb);
1324
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001325 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001326 }
1327
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001328 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001329 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001330}
1331
Szymon Janc67c9e842011-07-28 16:24:33 +02001332static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001333{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001334 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001335 u32 control;
1336 u16 fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001337
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001338 while ((skb = skb_dequeue(&chan->tx_q))) {
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001339 control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001340 control |= __set_txseq(chan, chan->next_tx_seq);
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001341 __put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001342
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001343 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001344 fcs = crc16(0, (u8 *)skb->data,
1345 skb->len - L2CAP_FCS_SIZE);
1346 put_unaligned_le16(fcs,
1347 skb->data + skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001348 }
1349
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001350 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001351
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001352 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001353 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001354}
1355
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001356static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001357{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001358 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001359 u16 fcs;
1360 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001361
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001362 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001363 if (!skb)
1364 return;
1365
Szymon Jancd1726b62011-11-16 09:32:20 +01001366 while (bt_cb(skb)->tx_seq != tx_seq) {
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001367 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001368 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001369
Szymon Jancd1726b62011-11-16 09:32:20 +01001370 skb = skb_queue_next(&chan->tx_q, skb);
1371 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001372
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001373 if (chan->remote_max_tx &&
1374 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001375 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001376 return;
1377 }
1378
1379 tx_skb = skb_clone(skb, GFP_ATOMIC);
1380 bt_cb(skb)->retries++;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001381
1382 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001383 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001384
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001385 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001386 control |= __set_ctrl_final(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001387
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001388 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001389 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001390
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001391 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001392
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001393 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001394 fcs = crc16(0, (u8 *)tx_skb->data,
1395 tx_skb->len - L2CAP_FCS_SIZE);
1396 put_unaligned_le16(fcs,
1397 tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001398 }
1399
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001400 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001401}
1402
Szymon Janc67c9e842011-07-28 16:24:33 +02001403static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001404{
1405 struct sk_buff *skb, *tx_skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001406 u16 fcs;
1407 u32 control;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001408 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001409
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001410 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001411 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001412
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001413 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001414
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001415 if (chan->remote_max_tx &&
1416 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001417 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001418 break;
1419 }
1420
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001421 tx_skb = skb_clone(skb, GFP_ATOMIC);
1422
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001423 bt_cb(skb)->retries++;
1424
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001425 control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001426 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001427
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001428 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001429 control |= __set_ctrl_final(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001430
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001431 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001432 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001433
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001434 __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001435
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001436 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001437 fcs = crc16(0, (u8 *)skb->data,
1438 tx_skb->len - L2CAP_FCS_SIZE);
1439 put_unaligned_le16(fcs, skb->data +
1440 tx_skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001441 }
1442
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001443 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001444
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001445 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001446
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001447 bt_cb(skb)->tx_seq = chan->next_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03001448
1449 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001450
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301451 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001452 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301453
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001454 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001455
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001456 if (skb_queue_is_last(&chan->tx_q, skb))
1457 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001458 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001459 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001460
1461 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001462 }
1463
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001464 return nsent;
1465}
1466
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001467static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001468{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001469 int ret;
1470
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001471 if (!skb_queue_empty(&chan->tx_q))
1472 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001473
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001474 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001475 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001476 return ret;
1477}
1478
Szymon Jancb17e73b2012-01-11 10:59:47 +01001479static void __l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001480{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001481 u32 control = 0;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001482
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001483 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001484
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001485 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001486 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001487 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001488 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001489 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001490 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001491
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001492 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001493 return;
1494
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001495 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001496 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001497}
1498
Szymon Jancb17e73b2012-01-11 10:59:47 +01001499static void l2cap_send_ack(struct l2cap_chan *chan)
1500{
1501 __clear_ack_timer(chan);
1502 __l2cap_send_ack(chan);
1503}
1504
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001505static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001506{
1507 struct srej_list *tail;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001508 u32 control;
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001509
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001510 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001511 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001512
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001513 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001514 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001515
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001516 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001517}
1518
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001519static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, struct msghdr *msg, int len, int count, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520{
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001521 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001522 struct sk_buff **frag;
1523 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001525 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001526 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527
1528 sent += count;
1529 len -= count;
1530
1531 /* Continuation fragments (no L2CAP header) */
1532 frag = &skb_shinfo(skb)->frag_list;
1533 while (len) {
1534 count = min_t(unsigned int, conn->mtu, len);
1535
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001536 *frag = chan->ops->alloc_skb(chan, count,
1537 msg->msg_flags & MSG_DONTWAIT, &err);
1538
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001540 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001541 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1542 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001544 (*frag)->priority = skb->priority;
1545
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 sent += count;
1547 len -= count;
1548
1549 frag = &(*frag)->next;
1550 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551
1552 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001553}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001555static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
1556 struct msghdr *msg, size_t len,
1557 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001558{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001559 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001560 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001561 struct sk_buff *skb;
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001562 int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001563 struct l2cap_hdr *lh;
1564
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001565 BT_DBG("sk %p len %d priority %u", sk, (int)len, priority);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001566
1567 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001568
1569 skb = chan->ops->alloc_skb(chan, count + hlen,
1570 msg->msg_flags & MSG_DONTWAIT, &err);
1571
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001572 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001573 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001574
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001575 skb->priority = priority;
1576
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001577 /* Create L2CAP header */
1578 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001579 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001580 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001581 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001582
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001583 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001584 if (unlikely(err < 0)) {
1585 kfree_skb(skb);
1586 return ERR_PTR(err);
1587 }
1588 return skb;
1589}
1590
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001591static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
1592 struct msghdr *msg, size_t len,
1593 u32 priority)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001594{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001595 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001596 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001597 struct sk_buff *skb;
1598 int err, count, hlen = L2CAP_HDR_SIZE;
1599 struct l2cap_hdr *lh;
1600
1601 BT_DBG("sk %p len %d", sk, (int)len);
1602
1603 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001604
1605 skb = chan->ops->alloc_skb(chan, count + hlen,
1606 msg->msg_flags & MSG_DONTWAIT, &err);
1607
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001608 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001609 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001610
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001611 skb->priority = priority;
1612
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001613 /* Create L2CAP header */
1614 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001615 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001616 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1617
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001618 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001619 if (unlikely(err < 0)) {
1620 kfree_skb(skb);
1621 return ERR_PTR(err);
1622 }
1623 return skb;
1624}
1625
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001626static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1627 struct msghdr *msg, size_t len,
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001628 u32 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001629{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001630 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001631 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001632 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001633 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001634 struct l2cap_hdr *lh;
1635
1636 BT_DBG("sk %p len %d", sk, (int)len);
1637
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001638 if (!conn)
1639 return ERR_PTR(-ENOTCONN);
1640
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001641 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1642 hlen = L2CAP_EXT_HDR_SIZE;
1643 else
1644 hlen = L2CAP_ENH_HDR_SIZE;
1645
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001646 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001647 hlen += L2CAP_SDULEN_SIZE;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001648
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001649 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001650 hlen += L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001651
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001652 count = min_t(unsigned int, (conn->mtu - hlen), len);
Andrei Emeltchenko2f7719c2012-01-20 14:08:03 +02001653
1654 skb = chan->ops->alloc_skb(chan, count + hlen,
1655 msg->msg_flags & MSG_DONTWAIT, &err);
1656
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001657 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001658 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001659
1660 /* Create L2CAP header */
1661 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001662 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001663 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001664
1665 __put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
1666
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001667 if (sdulen)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001668 put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001669
Andrei Emeltchenko0952a572012-01-13 17:21:43 +02001670 err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001671 if (unlikely(err < 0)) {
1672 kfree_skb(skb);
1673 return ERR_PTR(err);
1674 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001675
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001676 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03001677 put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001678
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001679 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001680 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681}
1682
Szymon Janc67c9e842011-07-28 16:24:33 +02001683static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001684{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001685 struct sk_buff *skb;
1686 struct sk_buff_head sar_queue;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001687 u32 control;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001688 size_t size = 0;
1689
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001690 skb_queue_head_init(&sar_queue);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001691 control = __set_ctrl_sar(chan, L2CAP_SAR_START);
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001692 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001693 if (IS_ERR(skb))
1694 return PTR_ERR(skb);
1695
1696 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001697 len -= chan->remote_mps;
1698 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001699
1700 while (len > 0) {
1701 size_t buflen;
1702
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001703 if (len > chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001704 control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001705 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001706 } else {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001707 control = __set_ctrl_sar(chan, L2CAP_SAR_END);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001708 buflen = len;
1709 }
1710
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001711 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001712 if (IS_ERR(skb)) {
1713 skb_queue_purge(&sar_queue);
1714 return PTR_ERR(skb);
1715 }
1716
1717 __skb_queue_tail(&sar_queue, skb);
1718 len -= buflen;
1719 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001720 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001721 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1722 if (chan->tx_send_head == NULL)
1723 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001724
1725 return size;
1726}
1727
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001728int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
1729 u32 priority)
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001730{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001731 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03001732 u32 control;
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001733 int err;
1734
1735 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001736 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001737 skb = l2cap_create_connless_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001738 if (IS_ERR(skb))
1739 return PTR_ERR(skb);
1740
1741 l2cap_do_send(chan, skb);
1742 return len;
1743 }
1744
1745 switch (chan->mode) {
1746 case L2CAP_MODE_BASIC:
1747 /* Check outgoing MTU */
1748 if (len > chan->omtu)
1749 return -EMSGSIZE;
1750
1751 /* Create a basic PDU */
Luiz Augusto von Dentz5e59b792011-11-01 10:58:57 +02001752 skb = l2cap_create_basic_pdu(chan, msg, len, priority);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001753 if (IS_ERR(skb))
1754 return PTR_ERR(skb);
1755
1756 l2cap_do_send(chan, skb);
1757 err = len;
1758 break;
1759
1760 case L2CAP_MODE_ERTM:
1761 case L2CAP_MODE_STREAMING:
1762 /* Entire SDU fits into one PDU */
1763 if (len <= chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001764 control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001765 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1766 0);
1767 if (IS_ERR(skb))
1768 return PTR_ERR(skb);
1769
1770 __skb_queue_tail(&chan->tx_q, skb);
1771
1772 if (chan->tx_send_head == NULL)
1773 chan->tx_send_head = skb;
1774
1775 } else {
1776 /* Segment SDU into multiples PDUs */
1777 err = l2cap_sar_segment_sdu(chan, msg, len);
1778 if (err < 0)
1779 return err;
1780 }
1781
1782 if (chan->mode == L2CAP_MODE_STREAMING) {
1783 l2cap_streaming_send(chan);
1784 err = len;
1785 break;
1786 }
1787
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001788 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1789 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001790 err = len;
1791 break;
1792 }
1793
1794 err = l2cap_ertm_send(chan);
1795 if (err >= 0)
1796 err = len;
1797
1798 break;
1799
1800 default:
1801 BT_DBG("bad state %1.1x", chan->mode);
1802 err = -EBADFD;
1803 }
1804
1805 return err;
1806}
1807
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808/* Copy frame to all raw sockets on that connection */
1809static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1810{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001812 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813
1814 BT_DBG("conn %p", conn);
1815
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001816 rcu_read_lock();
1817
1818 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001819 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001820 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821 continue;
1822
1823 /* Don't send frame to the socket it came from */
1824 if (skb->sk == sk)
1825 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001826 nskb = skb_clone(skb, GFP_ATOMIC);
1827 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 continue;
1829
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001830 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 kfree_skb(nskb);
1832 }
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02001833
1834 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835}
1836
1837/* ---- L2CAP signalling commands ---- */
1838static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1839 u8 code, u8 ident, u16 dlen, void *data)
1840{
1841 struct sk_buff *skb, **frag;
1842 struct l2cap_cmd_hdr *cmd;
1843 struct l2cap_hdr *lh;
1844 int len, count;
1845
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001846 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1847 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848
1849 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1850 count = min_t(unsigned int, conn->mtu, len);
1851
1852 skb = bt_skb_alloc(count, GFP_ATOMIC);
1853 if (!skb)
1854 return NULL;
1855
1856 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001857 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001858
1859 if (conn->hcon->type == LE_LINK)
1860 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1861 else
1862 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863
1864 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1865 cmd->code = code;
1866 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001867 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868
1869 if (dlen) {
1870 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1871 memcpy(skb_put(skb, count), data, count);
1872 data += count;
1873 }
1874
1875 len -= skb->len;
1876
1877 /* Continuation fragments (no L2CAP header) */
1878 frag = &skb_shinfo(skb)->frag_list;
1879 while (len) {
1880 count = min_t(unsigned int, conn->mtu, len);
1881
1882 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1883 if (!*frag)
1884 goto fail;
1885
1886 memcpy(skb_put(*frag, count), data, count);
1887
1888 len -= count;
1889 data += count;
1890
1891 frag = &(*frag)->next;
1892 }
1893
1894 return skb;
1895
1896fail:
1897 kfree_skb(skb);
1898 return NULL;
1899}
1900
1901static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1902{
1903 struct l2cap_conf_opt *opt = *ptr;
1904 int len;
1905
1906 len = L2CAP_CONF_OPT_SIZE + opt->len;
1907 *ptr += len;
1908
1909 *type = opt->type;
1910 *olen = opt->len;
1911
1912 switch (opt->len) {
1913 case 1:
1914 *val = *((u8 *) opt->val);
1915 break;
1916
1917 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001918 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 break;
1920
1921 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001922 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 break;
1924
1925 default:
1926 *val = (unsigned long) opt->val;
1927 break;
1928 }
1929
1930 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1931 return len;
1932}
1933
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1935{
1936 struct l2cap_conf_opt *opt = *ptr;
1937
1938 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1939
1940 opt->type = type;
1941 opt->len = len;
1942
1943 switch (len) {
1944 case 1:
1945 *((u8 *) opt->val) = val;
1946 break;
1947
1948 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001949 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 break;
1951
1952 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001953 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954 break;
1955
1956 default:
1957 memcpy(opt->val, (void *) val, len);
1958 break;
1959 }
1960
1961 *ptr += L2CAP_CONF_OPT_SIZE + len;
1962}
1963
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001964static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
1965{
1966 struct l2cap_conf_efs efs;
1967
Szymon Janc1ec918c2011-11-16 09:32:21 +01001968 switch (chan->mode) {
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001969 case L2CAP_MODE_ERTM:
1970 efs.id = chan->local_id;
1971 efs.stype = chan->local_stype;
1972 efs.msdu = cpu_to_le16(chan->local_msdu);
1973 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1974 efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
1975 efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
1976 break;
1977
1978 case L2CAP_MODE_STREAMING:
1979 efs.id = 1;
1980 efs.stype = L2CAP_SERV_BESTEFFORT;
1981 efs.msdu = cpu_to_le16(chan->local_msdu);
1982 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1983 efs.acc_lat = 0;
1984 efs.flush_to = 0;
1985 break;
1986
1987 default:
1988 return;
1989 }
1990
1991 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
1992 (unsigned long) &efs);
1993}
1994
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001995static void l2cap_ack_timeout(struct work_struct *work)
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001996{
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03001997 struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1998 ack_timer.work);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001999
Gustavo F. Padovan2fb9b3d2011-12-22 16:56:05 -02002000 BT_DBG("chan %p", chan);
2001
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002002 lock_sock(chan->sk);
Szymon Jancb17e73b2012-01-11 10:59:47 +01002003 __l2cap_send_ack(chan);
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002004 release_sock(chan->sk);
Szymon Janc09bfb2e2012-01-11 10:59:49 +01002005
2006 l2cap_chan_put(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03002007}
2008
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002009static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002010{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002011 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002012 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002013 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002014 chan->num_acked = 0;
2015 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002016
Gustavo F. Padovan721c4182011-06-23 19:29:58 -03002017 INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2018 INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2019 INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002020
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002021 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002022
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03002023 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002024}
2025
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002026static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
2027{
2028 switch (mode) {
2029 case L2CAP_MODE_STREAMING:
2030 case L2CAP_MODE_ERTM:
2031 if (l2cap_mode_supported(mode, remote_feat_mask))
2032 return mode;
2033 /* fall through */
2034 default:
2035 return L2CAP_MODE_BASIC;
2036 }
2037}
2038
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002039static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
2040{
2041 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
2042}
2043
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002044static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2045{
2046 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2047}
2048
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002049static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
2050{
2051 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002052 __l2cap_ews_supported(chan)) {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002053 /* use extended control field */
2054 set_bit(FLAG_EXT_CTRL, &chan->flags);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002055 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2056 } else {
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002057 chan->tx_win = min_t(u16, chan->tx_win,
2058 L2CAP_DEFAULT_TX_WINDOW);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002059 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2060 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002061}
2062
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002063static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002066 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 void *ptr = req->data;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002068 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002070 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002072 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002073 goto done;
2074
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002075 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002076 case L2CAP_MODE_STREAMING:
2077 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002078 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002079 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002080
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002081 if (__l2cap_efs_supported(chan))
2082 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2083
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03002084 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002085 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002086 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002087 break;
2088 }
2089
2090done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002091 if (chan->imtu != L2CAP_DEFAULT_MTU)
2092 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002093
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002094 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002095 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002096 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2097 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002098 break;
2099
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002100 rfc.mode = L2CAP_MODE_BASIC;
2101 rfc.txwin_size = 0;
2102 rfc.max_transmit = 0;
2103 rfc.retrans_timeout = 0;
2104 rfc.monitor_timeout = 0;
2105 rfc.max_pdu_size = 0;
2106
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002107 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2108 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002109 break;
2110
2111 case L2CAP_MODE_ERTM:
2112 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002113 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002114 rfc.retrans_timeout = 0;
2115 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002116
2117 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2118 L2CAP_EXT_HDR_SIZE -
2119 L2CAP_SDULEN_SIZE -
2120 L2CAP_FCS_SIZE);
2121 rfc.max_pdu_size = cpu_to_le16(size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002122
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002123 l2cap_txwin_setup(chan);
2124
2125 rfc.txwin_size = min_t(u16, chan->tx_win,
2126 L2CAP_DEFAULT_TX_WINDOW);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002127
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002128 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2129 (unsigned long) &rfc);
2130
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002131 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2132 l2cap_add_opt_efs(&ptr, chan);
2133
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002134 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002135 break;
2136
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002137 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002138 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002139 chan->fcs = L2CAP_FCS_NONE;
2140 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002141 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002142
2143 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2144 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2145 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002146 break;
2147
2148 case L2CAP_MODE_STREAMING:
2149 rfc.mode = L2CAP_MODE_STREAMING;
2150 rfc.txwin_size = 0;
2151 rfc.max_transmit = 0;
2152 rfc.retrans_timeout = 0;
2153 rfc.monitor_timeout = 0;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002154
2155 size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2156 L2CAP_EXT_HDR_SIZE -
2157 L2CAP_SDULEN_SIZE -
2158 L2CAP_FCS_SIZE);
2159 rfc.max_pdu_size = cpu_to_le16(size);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002160
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002161 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2162 (unsigned long) &rfc);
2163
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002164 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2165 l2cap_add_opt_efs(&ptr, chan);
2166
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002167 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002168 break;
2169
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002170 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002171 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002172 chan->fcs = L2CAP_FCS_NONE;
2173 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002174 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002175 break;
2176 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002178 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002179 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180
2181 return ptr - data;
2182}
2183
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002184static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002186 struct l2cap_conf_rsp *rsp = data;
2187 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002188 void *req = chan->conf_req;
2189 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002190 int type, hint, olen;
2191 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002192 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002193 struct l2cap_conf_efs efs;
2194 u8 remote_efs = 0;
Marcel Holtmann861d6882007-10-20 13:37:06 +02002195 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002196 u16 result = L2CAP_CONF_SUCCESS;
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002197 u16 size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002199 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002200
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002201 while (len >= L2CAP_CONF_OPT_SIZE) {
2202 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002204 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002205 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002206
2207 switch (type) {
2208 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002209 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002210 break;
2211
2212 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002213 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002214 break;
2215
2216 case L2CAP_CONF_QOS:
2217 break;
2218
Marcel Holtmann6464f352007-10-20 13:39:51 +02002219 case L2CAP_CONF_RFC:
2220 if (olen == sizeof(rfc))
2221 memcpy(&rfc, (void *) val, olen);
2222 break;
2223
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002224 case L2CAP_CONF_FCS:
2225 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002226 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002227 break;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002228
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002229 case L2CAP_CONF_EFS:
2230 remote_efs = 1;
2231 if (olen == sizeof(efs))
2232 memcpy(&efs, (void *) val, olen);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002233 break;
2234
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002235 case L2CAP_CONF_EWS:
2236 if (!enable_hs)
2237 return -ECONNREFUSED;
2238
2239 set_bit(FLAG_EXT_CTRL, &chan->flags);
2240 set_bit(CONF_EWS_RECV, &chan->conf_state);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03002241 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002242 chan->remote_tx_win = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002243 break;
2244
2245 default:
2246 if (hint)
2247 break;
2248
2249 result = L2CAP_CONF_UNKNOWN;
2250 *((u8 *) ptr++) = type;
2251 break;
2252 }
2253 }
2254
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002255 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002256 goto done;
2257
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002258 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002259 case L2CAP_MODE_STREAMING:
2260 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002261 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002262 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002263 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002264 break;
2265 }
2266
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002267 if (remote_efs) {
2268 if (__l2cap_efs_supported(chan))
2269 set_bit(FLAG_EFS_ENABLE, &chan->flags);
2270 else
2271 return -ECONNREFUSED;
2272 }
2273
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002274 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002275 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002276
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002277 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002278 }
2279
2280done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002281 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002282 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002283 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002284
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002285 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002286 return -ECONNREFUSED;
2287
2288 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2289 sizeof(rfc), (unsigned long) &rfc);
2290 }
2291
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002292 if (result == L2CAP_CONF_SUCCESS) {
2293 /* Configure output options and let the other side know
2294 * which ones we don't like. */
2295
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002296 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2297 result = L2CAP_CONF_UNACCEPT;
2298 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002299 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002300 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002301 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002302 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002303
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002304 if (remote_efs) {
2305 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2306 efs.stype != L2CAP_SERV_NOTRAFIC &&
2307 efs.stype != chan->local_stype) {
2308
2309 result = L2CAP_CONF_UNACCEPT;
2310
2311 if (chan->num_conf_req >= 1)
2312 return -ECONNREFUSED;
2313
2314 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002315 sizeof(efs),
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002316 (unsigned long) &efs);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002317 } else {
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002318 /* Send PENDING Conf Rsp */
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002319 result = L2CAP_CONF_PENDING;
2320 set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002321 }
2322 }
2323
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002324 switch (rfc.mode) {
2325 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002326 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002327 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002328 break;
2329
2330 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002331 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2332 chan->remote_tx_win = rfc.txwin_size;
2333 else
2334 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2335
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002336 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002337
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002338 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2339 chan->conn->mtu -
2340 L2CAP_EXT_HDR_SIZE -
2341 L2CAP_SDULEN_SIZE -
2342 L2CAP_FCS_SIZE);
2343 rfc.max_pdu_size = cpu_to_le16(size);
2344 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002345
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002346 rfc.retrans_timeout =
2347 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2348 rfc.monitor_timeout =
2349 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002350
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002351 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002352
2353 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2354 sizeof(rfc), (unsigned long) &rfc);
2355
Andrei Emeltchenko42dceae2011-10-17 14:35:30 +03002356 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2357 chan->remote_id = efs.id;
2358 chan->remote_stype = efs.stype;
2359 chan->remote_msdu = le16_to_cpu(efs.msdu);
2360 chan->remote_flush_to =
2361 le32_to_cpu(efs.flush_to);
2362 chan->remote_acc_lat =
2363 le32_to_cpu(efs.acc_lat);
2364 chan->remote_sdu_itime =
2365 le32_to_cpu(efs.sdu_itime);
2366 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2367 sizeof(efs), (unsigned long) &efs);
2368 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002369 break;
2370
2371 case L2CAP_MODE_STREAMING:
Andrei Emeltchenkoc8f79162011-10-17 12:19:59 +03002372 size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2373 chan->conn->mtu -
2374 L2CAP_EXT_HDR_SIZE -
2375 L2CAP_SDULEN_SIZE -
2376 L2CAP_FCS_SIZE);
2377 rfc.max_pdu_size = cpu_to_le16(size);
2378 chan->remote_mps = size;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002379
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002380 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002381
2382 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2383 sizeof(rfc), (unsigned long) &rfc);
2384
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002385 break;
2386
2387 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002388 result = L2CAP_CONF_UNACCEPT;
2389
2390 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002391 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002392 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002393
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002394 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002395 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002396 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002397 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002398 rsp->result = cpu_to_le16(result);
2399 rsp->flags = cpu_to_le16(0x0000);
2400
2401 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402}
2403
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002404static 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 -03002405{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002406 struct l2cap_conf_req *req = data;
2407 void *ptr = req->data;
2408 int type, olen;
2409 unsigned long val;
Mat Martineau36e999a2011-12-08 17:23:21 -08002410 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002411 struct l2cap_conf_efs efs;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002412
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002413 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002414
2415 while (len >= L2CAP_CONF_OPT_SIZE) {
2416 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2417
2418 switch (type) {
2419 case L2CAP_CONF_MTU:
2420 if (val < L2CAP_DEFAULT_MIN_MTU) {
2421 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002422 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002423 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002424 chan->imtu = val;
2425 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002426 break;
2427
2428 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002429 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002430 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002431 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002432 break;
2433
2434 case L2CAP_CONF_RFC:
2435 if (olen == sizeof(rfc))
2436 memcpy(&rfc, (void *)val, olen);
2437
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002438 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002439 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002440 return -ECONNREFUSED;
2441
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002442 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002443
2444 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2445 sizeof(rfc), (unsigned long) &rfc);
2446 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002447
2448 case L2CAP_CONF_EWS:
2449 chan->tx_win = min_t(u16, val,
2450 L2CAP_DEFAULT_EXT_WINDOW);
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002451 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2452 chan->tx_win);
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002453 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002454
2455 case L2CAP_CONF_EFS:
2456 if (olen == sizeof(efs))
2457 memcpy(&efs, (void *)val, olen);
2458
2459 if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
2460 efs.stype != L2CAP_SERV_NOTRAFIC &&
2461 efs.stype != chan->local_stype)
2462 return -ECONNREFUSED;
2463
2464 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
2465 sizeof(efs), (unsigned long) &efs);
2466 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002467 }
2468 }
2469
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002470 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002471 return -ECONNREFUSED;
2472
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002473 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002474
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002475 if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002476 switch (rfc.mode) {
2477 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002478 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2479 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2480 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002481
2482 if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
2483 chan->local_msdu = le16_to_cpu(efs.msdu);
2484 chan->local_sdu_itime =
2485 le32_to_cpu(efs.sdu_itime);
2486 chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
2487 chan->local_flush_to =
2488 le32_to_cpu(efs.flush_to);
2489 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002490 break;
Andrei Emeltchenko66af7aa2011-11-07 14:20:33 +02002491
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002492 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002493 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002494 }
2495 }
2496
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002497 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002498 req->flags = cpu_to_le16(0x0000);
2499
2500 return ptr - data;
2501}
2502
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002503static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504{
2505 struct l2cap_conf_rsp *rsp = data;
2506 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002508 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002510 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002511 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002512 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513
2514 return ptr - data;
2515}
2516
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002517void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002518{
2519 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002520 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002521 u8 buf[128];
2522
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002523 rsp.scid = cpu_to_le16(chan->dcid);
2524 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002525 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2526 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2527 l2cap_send_cmd(conn, chan->ident,
2528 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2529
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002530 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002531 return;
2532
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002533 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2534 l2cap_build_conf_req(chan, buf), buf);
2535 chan->num_conf_req++;
2536}
2537
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002538static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002539{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002540 int type, olen;
2541 unsigned long val;
2542 struct l2cap_conf_rfc rfc;
2543
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002544 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002545
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002546 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002547 return;
2548
2549 while (len >= L2CAP_CONF_OPT_SIZE) {
2550 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2551
2552 switch (type) {
2553 case L2CAP_CONF_RFC:
2554 if (olen == sizeof(rfc))
2555 memcpy(&rfc, (void *)val, olen);
2556 goto done;
2557 }
2558 }
2559
Mat Martineau36e999a2011-12-08 17:23:21 -08002560 /* Use sane default values in case a misbehaving remote device
2561 * did not send an RFC option.
2562 */
2563 rfc.mode = chan->mode;
2564 rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
2565 rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
2566 rfc.max_pdu_size = cpu_to_le16(chan->imtu);
2567
2568 BT_ERR("Expected RFC option was not found, using defaults");
2569
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002570done:
2571 switch (rfc.mode) {
2572 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002573 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2574 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2575 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002576 break;
2577 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002578 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002579 }
2580}
2581
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002582static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2583{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002584 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002585
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002586 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002587 return 0;
2588
2589 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2590 cmd->ident == conn->info_ident) {
Ulisses Furquim371fd832011-12-21 20:02:36 -02002591 __cancel_delayed_work(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002592
2593 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002594 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002595
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002596 l2cap_conn_start(conn);
2597 }
2598
2599 return 0;
2600}
2601
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2603{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2605 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002606 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002607 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002608 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609
2610 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002611 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612
2613 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2614
2615 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002616 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2617 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 result = L2CAP_CR_BAD_PSM;
2619 goto sendresp;
2620 }
2621
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002622 parent = pchan->sk;
2623
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002624 lock_sock(parent);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002625
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002626 /* Check if the ACL is secure enough (if not SDP) */
2627 if (psm != cpu_to_le16(0x0001) &&
2628 !hci_conn_check_link_mode(conn->hcon)) {
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02002629 conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002630 result = L2CAP_CR_SEC_BLOCK;
2631 goto response;
2632 }
2633
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634 result = L2CAP_CR_NO_MEM;
2635
2636 /* Check for backlog size */
2637 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002638 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639 goto response;
2640 }
2641
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002642 chan = pchan->ops->new_connection(pchan->data);
2643 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644 goto response;
2645
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002646 sk = chan->sk;
2647
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002649 if (__l2cap_get_chan_by_dcid(conn, scid)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002651 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652 goto response;
2653 }
2654
2655 hci_conn_hold(conn->hcon);
2656
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657 bacpy(&bt_sk(sk)->src, conn->src);
2658 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002659 chan->psm = psm;
2660 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002662 bt_accept_enqueue(parent, sk);
2663
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02002664 l2cap_chan_add(conn, chan);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002665
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002666 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002668 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002670 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671
Marcel Holtmann984947d2009-02-06 23:35:19 +01002672 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovand45fc422011-11-05 19:54:24 -02002673 if (l2cap_chan_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002674 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002675 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002676 result = L2CAP_CR_PEND;
2677 status = L2CAP_CS_AUTHOR_PEND;
2678 parent->sk_data_ready(parent, 0);
2679 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002680 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002681 result = L2CAP_CR_SUCCESS;
2682 status = L2CAP_CS_NO_INFO;
2683 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002684 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002685 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002686 result = L2CAP_CR_PEND;
2687 status = L2CAP_CS_AUTHEN_PEND;
2688 }
2689 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002690 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002691 result = L2CAP_CR_PEND;
2692 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693 }
2694
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695response:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002696 release_sock(parent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697
2698sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002699 rsp.scid = cpu_to_le16(scid);
2700 rsp.dcid = cpu_to_le16(dcid);
2701 rsp.result = cpu_to_le16(result);
2702 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002704
2705 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2706 struct l2cap_info_req info;
2707 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2708
2709 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2710 conn->info_ident = l2cap_get_ident(conn);
2711
Gustavo F. Padovan030013d2011-12-20 10:57:28 -02002712 schedule_delayed_work(&conn->info_timer,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002713 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2714
2715 l2cap_send_cmd(conn, conn->info_ident,
2716 L2CAP_INFO_REQ, sizeof(info), &info);
2717 }
2718
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002719 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002720 result == L2CAP_CR_SUCCESS) {
2721 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002722 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002723 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002724 l2cap_build_conf_req(chan, buf), buf);
2725 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002726 }
2727
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 return 0;
2729}
2730
2731static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2732{
2733 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2734 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002735 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736 struct sock *sk;
2737 u8 req[128];
2738
2739 scid = __le16_to_cpu(rsp->scid);
2740 dcid = __le16_to_cpu(rsp->dcid);
2741 result = __le16_to_cpu(rsp->result);
2742 status = __le16_to_cpu(rsp->status);
2743
2744 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2745
2746 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002747 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002748 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002749 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002751 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002752 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002753 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754 }
2755
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002756 sk = chan->sk;
2757
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758 switch (result) {
2759 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002760 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002761 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002762 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002763 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002764
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002765 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002766 break;
2767
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002769 l2cap_build_conf_req(chan, req), req);
2770 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 break;
2772
2773 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002774 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 break;
2776
2777 default:
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002778 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779 break;
2780 }
2781
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002782 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783 return 0;
2784}
2785
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002786static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002787{
2788 /* FCS is enabled only in ERTM or streaming mode, if one or both
2789 * sides request it.
2790 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002791 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002792 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002793 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002794 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002795}
2796
Al Viro88219a02007-07-29 00:17:25 -07002797static 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 -07002798{
2799 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2800 u16 dcid, flags;
2801 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002802 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002804 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805
2806 dcid = __le16_to_cpu(req->dcid);
2807 flags = __le16_to_cpu(req->flags);
2808
2809 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2810
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002811 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002812 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813 return -ENOENT;
2814
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002815 sk = chan->sk;
2816
David S. Miller033b1142011-07-21 13:38:42 -07002817 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002818 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002819
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002820 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2821 rej.scid = cpu_to_le16(chan->scid);
2822 rej.dcid = cpu_to_le16(chan->dcid);
2823
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002824 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2825 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002826 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002827 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002828
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002829 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002830 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002831 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002832 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002833 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002834 L2CAP_CONF_REJECT, flags), rsp);
2835 goto unlock;
2836 }
2837
2838 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002839 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2840 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841
2842 if (flags & 0x0001) {
2843 /* Incomplete config. Send empty response. */
2844 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002845 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002846 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847 goto unlock;
2848 }
2849
2850 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002851 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002852 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002853 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002855 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002857 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002858 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002859
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002860 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002861 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002862
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002863 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002864 goto unlock;
2865
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002866 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002867 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002868
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002869 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002870
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002871 chan->next_tx_seq = 0;
2872 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002873 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002874 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002875 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002876
Linus Torvalds1da177e2005-04-16 15:20:36 -07002877 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002878 goto unlock;
2879 }
2880
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002881 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002882 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002884 l2cap_build_conf_req(chan, buf), buf);
2885 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886 }
2887
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002888 /* Got Conf Rsp PENDING from remote side and asume we sent
2889 Conf Rsp PENDING in the code above */
2890 if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
2891 test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2892
2893 /* check compatibility */
2894
2895 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2896 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2897
2898 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002899 l2cap_build_conf_rsp(chan, rsp,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002900 L2CAP_CONF_SUCCESS, 0x0000), rsp);
2901 }
2902
Linus Torvalds1da177e2005-04-16 15:20:36 -07002903unlock:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03002904 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905 return 0;
2906}
2907
2908static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2909{
2910 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2911 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002912 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002914 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915
2916 scid = __le16_to_cpu(rsp->scid);
2917 flags = __le16_to_cpu(rsp->flags);
2918 result = __le16_to_cpu(rsp->result);
2919
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002920 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2921 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002922
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002923 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002924 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925 return 0;
2926
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002927 sk = chan->sk;
2928
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929 switch (result) {
2930 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002931 l2cap_conf_rfc_get(chan, rsp->data, len);
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002932 clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933 break;
2934
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002935 case L2CAP_CONF_PENDING:
2936 set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
2937
2938 if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
2939 char buf[64];
2940
2941 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2942 buf, &result);
2943 if (len < 0) {
2944 l2cap_send_disconn_req(conn, chan, ECONNRESET);
2945 goto done;
2946 }
2947
2948 /* check compatibility */
2949
2950 clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
2951 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
2952
2953 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovan3e6b3b92011-11-01 14:06:23 -02002954 l2cap_build_conf_rsp(chan, buf,
Andrei Emeltchenko0e8b2072011-10-17 14:35:32 +03002955 L2CAP_CONF_SUCCESS, 0x0000), buf);
2956 }
2957 goto done;
2958
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002960 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002961 char req[64];
2962
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002963 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002964 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002965 goto done;
2966 }
2967
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002968 /* throw out any old stored conf requests */
2969 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002970 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2971 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002972 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002973 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002974 goto done;
2975 }
2976
2977 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2978 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002979 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002980 if (result != L2CAP_CONF_SUCCESS)
2981 goto done;
2982 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983 }
2984
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002985 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002986 sk->sk_err = ECONNRESET;
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01002987 __set_chan_timer(chan,
2988 msecs_to_jiffies(L2CAP_DISC_REJ_TIMEOUT));
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002989 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990 goto done;
2991 }
2992
2993 if (flags & 0x01)
2994 goto done;
2995
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002996 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002998 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002999 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003000
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003001 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003002 chan->next_tx_seq = 0;
3003 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03003004 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003005 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003006 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03003007
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008 l2cap_chan_ready(sk);
3009 }
3010
3011done:
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003012 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013 return 0;
3014}
3015
3016static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3017{
3018 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
3019 struct l2cap_disconn_rsp rsp;
3020 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003021 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022 struct sock *sk;
3023
3024 scid = __le16_to_cpu(req->scid);
3025 dcid = __le16_to_cpu(req->dcid);
3026
3027 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
3028
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003029 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003030 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031 return 0;
3032
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003033 sk = chan->sk;
3034
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003035 rsp.dcid = cpu_to_le16(chan->scid);
3036 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
3038
3039 sk->sk_shutdown = SHUTDOWN_MASK;
3040
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003041 l2cap_chan_del(chan, ECONNRESET);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003042 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003044 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045 return 0;
3046}
3047
3048static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3049{
3050 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
3051 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003052 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053 struct sock *sk;
3054
3055 scid = __le16_to_cpu(rsp->scid);
3056 dcid = __le16_to_cpu(rsp->dcid);
3057
3058 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
3059
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003060 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003061 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062 return 0;
3063
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003064 sk = chan->sk;
3065
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003066 l2cap_chan_del(chan, 0);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03003067 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03003069 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070 return 0;
3071}
3072
3073static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3074{
3075 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076 u16 type;
3077
3078 type = __le16_to_cpu(req->type);
3079
3080 BT_DBG("type 0x%4.4x", type);
3081
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003082 if (type == L2CAP_IT_FEAT_MASK) {
3083 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003084 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003085 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3086 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
3087 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003088 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003089 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
3090 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003091 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03003092 feat_mask |= L2CAP_FEAT_EXT_FLOW
3093 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03003094
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003095 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003096 l2cap_send_cmd(conn, cmd->ident,
3097 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003098 } else if (type == L2CAP_IT_FIXED_CHAN) {
3099 u8 buf[12];
3100 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
Mat Martineau50a147c2011-11-02 16:18:34 -07003101
3102 if (enable_hs)
3103 l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
3104 else
3105 l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
3106
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003107 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3108 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Andrei Emeltchenkoc6337ea2011-10-20 17:02:44 +03003109 memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003110 l2cap_send_cmd(conn, cmd->ident,
3111 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02003112 } else {
3113 struct l2cap_info_rsp rsp;
3114 rsp.type = cpu_to_le16(type);
3115 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
3116 l2cap_send_cmd(conn, cmd->ident,
3117 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
3118 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119
3120 return 0;
3121}
3122
3123static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
3124{
3125 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
3126 u16 type, result;
3127
3128 type = __le16_to_cpu(rsp->type);
3129 result = __le16_to_cpu(rsp->result);
3130
3131 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
3132
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02003133 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
3134 if (cmd->ident != conn->info_ident ||
3135 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3136 return 0;
3137
Ulisses Furquim371fd832011-12-21 20:02:36 -02003138 __cancel_delayed_work(&conn->info_timer);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003139
Ville Tervoadb08ed2010-08-04 09:43:33 +03003140 if (result != L2CAP_IR_SUCCESS) {
3141 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3142 conn->info_ident = 0;
3143
3144 l2cap_conn_start(conn);
3145
3146 return 0;
3147 }
3148
Marcel Holtmann984947d2009-02-06 23:35:19 +01003149 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07003150 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003151
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07003152 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003153 struct l2cap_info_req req;
3154 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3155
3156 conn->info_ident = l2cap_get_ident(conn);
3157
3158 l2cap_send_cmd(conn, conn->info_ident,
3159 L2CAP_INFO_REQ, sizeof(req), &req);
3160 } else {
3161 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
3162 conn->info_ident = 0;
3163
3164 l2cap_conn_start(conn);
3165 }
3166 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01003167 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003168 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01003169
3170 l2cap_conn_start(conn);
3171 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02003172
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173 return 0;
3174}
3175
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003176static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3177 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3178 void *data)
3179{
3180 struct l2cap_create_chan_req *req = data;
3181 struct l2cap_create_chan_rsp rsp;
3182 u16 psm, scid;
3183
3184 if (cmd_len != sizeof(*req))
3185 return -EPROTO;
3186
3187 if (!enable_hs)
3188 return -EINVAL;
3189
3190 psm = le16_to_cpu(req->psm);
3191 scid = le16_to_cpu(req->scid);
3192
3193 BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3194
3195 /* Placeholder: Always reject */
3196 rsp.dcid = 0;
3197 rsp.scid = cpu_to_le16(scid);
3198 rsp.result = L2CAP_CR_NO_MEM;
3199 rsp.status = L2CAP_CS_NO_INFO;
3200
3201 l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3202 sizeof(rsp), &rsp);
3203
3204 return 0;
3205}
3206
3207static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3208 struct l2cap_cmd_hdr *cmd, void *data)
3209{
3210 BT_DBG("conn %p", conn);
3211
3212 return l2cap_connect_rsp(conn, cmd, data);
3213}
3214
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003215static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
3216 u16 icid, u16 result)
3217{
3218 struct l2cap_move_chan_rsp rsp;
3219
3220 BT_DBG("icid %d, result %d", icid, result);
3221
3222 rsp.icid = cpu_to_le16(icid);
3223 rsp.result = cpu_to_le16(result);
3224
3225 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
3226}
3227
3228static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
3229 struct l2cap_chan *chan, u16 icid, u16 result)
3230{
3231 struct l2cap_move_chan_cfm cfm;
3232 u8 ident;
3233
3234 BT_DBG("icid %d, result %d", icid, result);
3235
3236 ident = l2cap_get_ident(conn);
3237 if (chan)
3238 chan->ident = ident;
3239
3240 cfm.icid = cpu_to_le16(icid);
3241 cfm.result = cpu_to_le16(result);
3242
3243 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
3244}
3245
3246static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
3247 u16 icid)
3248{
3249 struct l2cap_move_chan_cfm_rsp rsp;
3250
3251 BT_DBG("icid %d", icid);
3252
3253 rsp.icid = cpu_to_le16(icid);
3254 l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
3255}
3256
3257static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
3258 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3259{
3260 struct l2cap_move_chan_req *req = data;
3261 u16 icid = 0;
3262 u16 result = L2CAP_MR_NOT_ALLOWED;
3263
3264 if (cmd_len != sizeof(*req))
3265 return -EPROTO;
3266
3267 icid = le16_to_cpu(req->icid);
3268
3269 BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
3270
3271 if (!enable_hs)
3272 return -EINVAL;
3273
3274 /* Placeholder: Always refuse */
3275 l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
3276
3277 return 0;
3278}
3279
3280static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
3281 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3282{
3283 struct l2cap_move_chan_rsp *rsp = data;
3284 u16 icid, result;
3285
3286 if (cmd_len != sizeof(*rsp))
3287 return -EPROTO;
3288
3289 icid = le16_to_cpu(rsp->icid);
3290 result = le16_to_cpu(rsp->result);
3291
3292 BT_DBG("icid %d, result %d", icid, result);
3293
3294 /* Placeholder: Always unconfirmed */
3295 l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
3296
3297 return 0;
3298}
3299
3300static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
3301 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3302{
3303 struct l2cap_move_chan_cfm *cfm = data;
3304 u16 icid, result;
3305
3306 if (cmd_len != sizeof(*cfm))
3307 return -EPROTO;
3308
3309 icid = le16_to_cpu(cfm->icid);
3310 result = le16_to_cpu(cfm->result);
3311
3312 BT_DBG("icid %d, result %d", icid, result);
3313
3314 l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
3315
3316 return 0;
3317}
3318
3319static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
3320 struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
3321{
3322 struct l2cap_move_chan_cfm_rsp *rsp = data;
3323 u16 icid;
3324
3325 if (cmd_len != sizeof(*rsp))
3326 return -EPROTO;
3327
3328 icid = le16_to_cpu(rsp->icid);
3329
3330 BT_DBG("icid %d", icid);
3331
3332 return 0;
3333}
3334
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003335static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02003336 u16 to_multiplier)
3337{
3338 u16 max_latency;
3339
3340 if (min > max || min < 6 || max > 3200)
3341 return -EINVAL;
3342
3343 if (to_multiplier < 10 || to_multiplier > 3200)
3344 return -EINVAL;
3345
3346 if (max >= to_multiplier * 8)
3347 return -EINVAL;
3348
3349 max_latency = (to_multiplier * 8 / max) - 1;
3350 if (latency > 499 || latency > max_latency)
3351 return -EINVAL;
3352
3353 return 0;
3354}
3355
3356static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3357 struct l2cap_cmd_hdr *cmd, u8 *data)
3358{
3359 struct hci_conn *hcon = conn->hcon;
3360 struct l2cap_conn_param_update_req *req;
3361 struct l2cap_conn_param_update_rsp rsp;
3362 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003363 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003364
3365 if (!(hcon->link_mode & HCI_LM_MASTER))
3366 return -EINVAL;
3367
3368 cmd_len = __le16_to_cpu(cmd->len);
3369 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3370 return -EPROTO;
3371
3372 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003373 min = __le16_to_cpu(req->min);
3374 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003375 latency = __le16_to_cpu(req->latency);
3376 to_multiplier = __le16_to_cpu(req->to_multiplier);
3377
3378 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3379 min, max, latency, to_multiplier);
3380
3381 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003382
3383 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3384 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003385 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3386 else
3387 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3388
3389 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3390 sizeof(rsp), &rsp);
3391
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003392 if (!err)
3393 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3394
Claudio Takahaside731152011-02-11 19:28:55 -02003395 return 0;
3396}
3397
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003398static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3399 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3400{
3401 int err = 0;
3402
3403 switch (cmd->code) {
3404 case L2CAP_COMMAND_REJ:
3405 l2cap_command_rej(conn, cmd, data);
3406 break;
3407
3408 case L2CAP_CONN_REQ:
3409 err = l2cap_connect_req(conn, cmd, data);
3410 break;
3411
3412 case L2CAP_CONN_RSP:
3413 err = l2cap_connect_rsp(conn, cmd, data);
3414 break;
3415
3416 case L2CAP_CONF_REQ:
3417 err = l2cap_config_req(conn, cmd, cmd_len, data);
3418 break;
3419
3420 case L2CAP_CONF_RSP:
3421 err = l2cap_config_rsp(conn, cmd, data);
3422 break;
3423
3424 case L2CAP_DISCONN_REQ:
3425 err = l2cap_disconnect_req(conn, cmd, data);
3426 break;
3427
3428 case L2CAP_DISCONN_RSP:
3429 err = l2cap_disconnect_rsp(conn, cmd, data);
3430 break;
3431
3432 case L2CAP_ECHO_REQ:
3433 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3434 break;
3435
3436 case L2CAP_ECHO_RSP:
3437 break;
3438
3439 case L2CAP_INFO_REQ:
3440 err = l2cap_information_req(conn, cmd, data);
3441 break;
3442
3443 case L2CAP_INFO_RSP:
3444 err = l2cap_information_rsp(conn, cmd, data);
3445 break;
3446
Mat Martineauf94ff6f2011-11-02 16:18:32 -07003447 case L2CAP_CREATE_CHAN_REQ:
3448 err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3449 break;
3450
3451 case L2CAP_CREATE_CHAN_RSP:
3452 err = l2cap_create_channel_rsp(conn, cmd, data);
3453 break;
3454
Mat Martineau8d5a04a2011-11-02 16:18:35 -07003455 case L2CAP_MOVE_CHAN_REQ:
3456 err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
3457 break;
3458
3459 case L2CAP_MOVE_CHAN_RSP:
3460 err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
3461 break;
3462
3463 case L2CAP_MOVE_CHAN_CFM:
3464 err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
3465 break;
3466
3467 case L2CAP_MOVE_CHAN_CFM_RSP:
3468 err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
3469 break;
3470
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003471 default:
3472 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3473 err = -EINVAL;
3474 break;
3475 }
3476
3477 return err;
3478}
3479
3480static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3481 struct l2cap_cmd_hdr *cmd, u8 *data)
3482{
3483 switch (cmd->code) {
3484 case L2CAP_COMMAND_REJ:
3485 return 0;
3486
3487 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003488 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003489
3490 case L2CAP_CONN_PARAM_UPDATE_RSP:
3491 return 0;
3492
3493 default:
3494 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3495 return -EINVAL;
3496 }
3497}
3498
3499static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3500 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501{
3502 u8 *data = skb->data;
3503 int len = skb->len;
3504 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003505 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506
3507 l2cap_raw_recv(conn, skb);
3508
3509 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003510 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003511 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3512 data += L2CAP_CMD_HDR_SIZE;
3513 len -= L2CAP_CMD_HDR_SIZE;
3514
Al Viro88219a02007-07-29 00:17:25 -07003515 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003516
Al Viro88219a02007-07-29 00:17:25 -07003517 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 -07003518
Al Viro88219a02007-07-29 00:17:25 -07003519 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520 BT_DBG("corrupted command");
3521 break;
3522 }
3523
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003524 if (conn->hcon->type == LE_LINK)
3525 err = l2cap_le_sig_cmd(conn, &cmd, data);
3526 else
3527 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003528
3529 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003530 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003531
3532 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533
3534 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003535 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003536 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3537 }
3538
Al Viro88219a02007-07-29 00:17:25 -07003539 data += cmd_len;
3540 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003541 }
3542
3543 kfree_skb(skb);
3544}
3545
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003546static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003547{
3548 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003549 int hdr_size;
3550
3551 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3552 hdr_size = L2CAP_EXT_HDR_SIZE;
3553 else
3554 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003555
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003556 if (chan->fcs == L2CAP_FCS_CRC16) {
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003557 skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003558 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3559 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3560
3561 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003562 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003563 }
3564 return 0;
3565}
3566
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003567static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003568{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003569 u32 control = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003570
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003571 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003572
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003573 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003574
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003575 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003576 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003577 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003578 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003579 }
3580
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003581 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003582 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003583
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003584 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003585
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003586 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003587 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003588 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003589 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003590 }
3591}
3592
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003593static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003594{
3595 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003596 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003597
3598 bt_cb(skb)->tx_seq = tx_seq;
3599 bt_cb(skb)->sar = sar;
3600
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003601 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003602
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003603 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003604
Szymon Janc039d9572011-11-16 09:32:19 +01003605 while (next_skb) {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003606 if (bt_cb(next_skb)->tx_seq == tx_seq)
3607 return -EINVAL;
3608
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003609 next_tx_seq_offset = __seq_offset(chan,
3610 bt_cb(next_skb)->tx_seq, chan->buffer_seq);
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003611
3612 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003613 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003614 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003615 }
3616
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003617 if (skb_queue_is_last(&chan->srej_q, next_skb))
Szymon Janc039d9572011-11-16 09:32:19 +01003618 next_skb = NULL;
3619 else
3620 next_skb = skb_queue_next(&chan->srej_q, next_skb);
3621 }
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003622
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003623 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003624
3625 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003626}
3627
Mat Martineau84084a32011-07-22 14:54:00 -07003628static void append_skb_frag(struct sk_buff *skb,
3629 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003630{
Mat Martineau84084a32011-07-22 14:54:00 -07003631 /* skb->len reflects data in skb as well as all fragments
3632 * skb->data_len reflects only data in fragments
3633 */
3634 if (!skb_has_frag_list(skb))
3635 skb_shinfo(skb)->frag_list = new_frag;
3636
3637 new_frag->next = NULL;
3638
3639 (*last_frag)->next = new_frag;
3640 *last_frag = new_frag;
3641
3642 skb->len += new_frag->len;
3643 skb->data_len += new_frag->len;
3644 skb->truesize += new_frag->truesize;
3645}
3646
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003647static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
Mat Martineau84084a32011-07-22 14:54:00 -07003648{
3649 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003650
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003651 switch (__get_ctrl_sar(chan, control)) {
3652 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003653 if (chan->sdu)
3654 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003655
Mat Martineau84084a32011-07-22 14:54:00 -07003656 err = chan->ops->recv(chan->data, skb);
3657 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003658
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003659 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003660 if (chan->sdu)
3661 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003662
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003663 chan->sdu_len = get_unaligned_le16(skb->data);
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03003664 skb_pull(skb, L2CAP_SDULEN_SIZE);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003665
Mat Martineau84084a32011-07-22 14:54:00 -07003666 if (chan->sdu_len > chan->imtu) {
3667 err = -EMSGSIZE;
3668 break;
3669 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003670
Mat Martineau84084a32011-07-22 14:54:00 -07003671 if (skb->len >= chan->sdu_len)
3672 break;
3673
3674 chan->sdu = skb;
3675 chan->sdu_last_frag = skb;
3676
3677 skb = NULL;
3678 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003679 break;
3680
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003681 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003682 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003683 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003684
Mat Martineau84084a32011-07-22 14:54:00 -07003685 append_skb_frag(chan->sdu, skb,
3686 &chan->sdu_last_frag);
3687 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003688
Mat Martineau84084a32011-07-22 14:54:00 -07003689 if (chan->sdu->len >= chan->sdu_len)
3690 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003691
Mat Martineau84084a32011-07-22 14:54:00 -07003692 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003693 break;
3694
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003695 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003696 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003697 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003698
Mat Martineau84084a32011-07-22 14:54:00 -07003699 append_skb_frag(chan->sdu, skb,
3700 &chan->sdu_last_frag);
3701 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003702
Mat Martineau84084a32011-07-22 14:54:00 -07003703 if (chan->sdu->len != chan->sdu_len)
3704 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003705
Mat Martineau84084a32011-07-22 14:54:00 -07003706 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003707
Mat Martineau84084a32011-07-22 14:54:00 -07003708 if (!err) {
3709 /* Reassembly complete */
3710 chan->sdu = NULL;
3711 chan->sdu_last_frag = NULL;
3712 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003713 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003714 break;
3715 }
3716
Mat Martineau84084a32011-07-22 14:54:00 -07003717 if (err) {
3718 kfree_skb(skb);
3719 kfree_skb(chan->sdu);
3720 chan->sdu = NULL;
3721 chan->sdu_last_frag = NULL;
3722 chan->sdu_len = 0;
3723 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003724
Mat Martineau84084a32011-07-22 14:54:00 -07003725 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003726}
3727
Mat Martineau26f880d2011-07-07 09:39:01 -07003728static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003729{
Mat Martineau26f880d2011-07-07 09:39:01 -07003730 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003731
Mat Martineau26f880d2011-07-07 09:39:01 -07003732 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3733
Szymon Janc77f918b2012-01-11 10:59:48 +01003734 __set_ack_timer(chan);
Mat Martineau26f880d2011-07-07 09:39:01 -07003735}
3736
3737static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3738{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003739 u32 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003740
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003741 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003742 goto done;
3743
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003744 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003745 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003746 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003747 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003748 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003749
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003750 __clear_retrans_timer(chan);
3751 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003752
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003753 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003754
3755done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003756 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3757 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003758
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003759 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003760}
3761
Mat Martineaue3281402011-07-07 09:39:02 -07003762void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003763{
Mat Martineaue3281402011-07-07 09:39:02 -07003764 if (chan->mode == L2CAP_MODE_ERTM) {
3765 if (busy)
3766 l2cap_ertm_enter_local_busy(chan);
3767 else
3768 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003769 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003770}
3771
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003772static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003773{
3774 struct sk_buff *skb;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003775 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003776
Mat Martineaue3281402011-07-07 09:39:02 -07003777 while ((skb = skb_peek(&chan->srej_q)) &&
3778 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3779 int err;
3780
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003781 if (bt_cb(skb)->tx_seq != tx_seq)
3782 break;
3783
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003784 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003785 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003786 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003787
3788 if (err < 0) {
3789 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3790 break;
3791 }
3792
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003793 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
3794 tx_seq = __next_seq(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003795 }
3796}
3797
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003798static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003799{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003800 struct srej_list *l, *tmp;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003801 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003802
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003803 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003804 if (l->tx_seq == tx_seq) {
3805 list_del(&l->list);
3806 kfree(l);
3807 return;
3808 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003809 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003810 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003811 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003812 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003813 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003814 }
3815}
3816
Szymon Jancaef89f22011-11-16 09:32:18 +01003817static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003818{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003819 struct srej_list *new;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003820 u32 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003821
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003822 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003823 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003824 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003825 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003826
3827 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Szymon Jancaef89f22011-11-16 09:32:18 +01003828 if (!new)
3829 return -ENOMEM;
3830
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003831 new->tx_seq = chan->expected_tx_seq;
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003832
3833 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3834
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003835 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003836 }
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003837
3838 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Szymon Jancaef89f22011-11-16 09:32:18 +01003839
3840 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003841}
3842
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003843static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003844{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003845 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003846 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003847 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003848 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003849 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003850 int err = 0;
3851
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003852 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%8.8x", chan, skb->len,
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003853 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003854
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003855 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003856 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003857 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003858 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003859 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003860 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003861 }
3862
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003863 chan->expected_ack_seq = req_seq;
3864 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003865
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003866 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003867
3868 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003869 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003870 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003871 goto drop;
3872 }
3873
Szymon Janc77f918b2012-01-11 10:59:48 +01003874 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3875 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
3876 l2cap_send_ack(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003877 goto drop;
Szymon Janc77f918b2012-01-11 10:59:48 +01003878 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003879
Mat Martineau02f1b642011-06-29 14:35:19 -07003880 if (tx_seq == chan->expected_tx_seq)
3881 goto expected;
3882
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003883 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003884 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003885
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003886 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003887 struct srej_list, list);
3888 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003889 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003890 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003891
3892 list_del(&first->list);
3893 kfree(first);
3894
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003895 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003896 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003897 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003898 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003899 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003900 }
3901 } else {
3902 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003903
3904 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003905 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003906 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003907
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003908 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003909 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003910 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003911 return 0;
3912 }
3913 }
Szymon Jancaef89f22011-11-16 09:32:18 +01003914
3915 err = l2cap_send_srejframe(chan, tx_seq);
3916 if (err < 0) {
3917 l2cap_send_disconn_req(chan->conn, chan, -err);
3918 return err;
3919 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003920 }
3921 } else {
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003922 expected_tx_seq_offset = __seq_offset(chan,
3923 chan->expected_tx_seq, chan->buffer_seq);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003924
3925 /* duplicated tx_seq */
3926 if (tx_seq_offset < expected_tx_seq_offset)
3927 goto drop;
3928
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003929 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003930
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003931 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003932
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003933 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003934 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003935
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003936 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003937 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003938
Szymon Janc0ef3ef02012-01-11 10:59:46 +01003939 /* Set P-bit only if there are some I-frames to ack. */
3940 if (__clear_ack_timer(chan))
3941 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003942
Szymon Jancaef89f22011-11-16 09:32:18 +01003943 err = l2cap_send_srejframe(chan, tx_seq);
3944 if (err < 0) {
3945 l2cap_send_disconn_req(chan->conn, chan, -err);
3946 return err;
3947 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003948 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003949 return 0;
3950
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003951expected:
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003952 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003953
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003954 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003955 bt_cb(skb)->tx_seq = tx_seq;
3956 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003957 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003958 return 0;
3959 }
3960
Mat Martineau84084a32011-07-22 14:54:00 -07003961 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Andrei Emeltchenko836be932011-10-17 12:19:57 +03003962 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
3963
Mat Martineaue3281402011-07-07 09:39:02 -07003964 if (err < 0) {
3965 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3966 return err;
3967 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003968
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003969 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003970 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003971 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003972 }
3973
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003974
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003975 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3976 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003977 l2cap_send_ack(chan);
Gustavo F. Padovan4d611e42011-06-23 19:30:48 -03003978 else
3979 __set_ack_timer(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003980
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003981 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003982
3983drop:
3984 kfree_skb(skb);
3985 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003986}
3987
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003988static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003989{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03003990 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003991 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003992
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003993 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003994 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003995
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003996 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003997 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3998 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3999 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004000 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004001 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004002
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004003 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004004 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004005 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004006 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03004007 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004008
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004009 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004010 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004011
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004012 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004013 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004014
4015 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004016 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004017 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004018 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004019
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004020 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4021 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004022 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02004023 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004024 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004025 }
4026}
4027
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004028static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004029{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004030 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004031
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004032 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004033
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004034 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004035
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004036 chan->expected_ack_seq = tx_seq;
4037 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004038
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004039 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004040 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004041 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004042 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004043 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004044
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004045 if (test_bit(CONN_WAIT_F, &chan->conn_state))
4046 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004047 }
4048}
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004049static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004050{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004051 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004052
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004053 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004054
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004055 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004056
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004057 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004058 chan->expected_ack_seq = tx_seq;
4059 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004060
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004061 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004062 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004063
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004064 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03004065
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004066 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004067 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004068 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004069 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004070 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004071 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004072 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004073 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004074 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004075 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004076 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004077 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004078 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004079 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004080 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004081 }
4082 }
4083}
4084
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004085static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004086{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004087 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004088
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004089 BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03004090
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004091 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03004092 chan->expected_ack_seq = tx_seq;
4093 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004094
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004095 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004096 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03004097
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004098 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004099 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004100 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004101 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004102 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004103 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03004104
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03004105 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004106 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004107 } else {
4108 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4109 l2cap_send_sframe(chan, rx_control);
4110 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004111}
4112
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004113static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03004114{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004115 BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004116
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03004117 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004118 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004119 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03004120 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03004121 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03004122 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03004123 }
4124
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004125 switch (__get_ctrl_super(chan, rx_control)) {
4126 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004127 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004128 break;
4129
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004130 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004131 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03004132 break;
4133
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004134 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004135 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03004136 break;
4137
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03004138 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004139 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004140 break;
4141 }
4142
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03004143 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004144 return 0;
4145}
4146
Szymon Janccad8f1d2012-01-23 10:06:05 +01004147static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004148{
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004149 u32 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004150 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004151 int len, next_tx_seq_offset, req_seq_offset;
4152
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004153 control = __get_control(chan, skb->data);
4154 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004155 len = skb->len;
4156
4157 /*
4158 * We can just drop the corrupted I-frame here.
4159 * Receiver will miss it and start proper recovery
4160 * procedures and ask retransmission.
4161 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004162 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004163 goto drop;
4164
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004165 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004166 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004167
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004168 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004169 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004170
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004171 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004172 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004173 goto drop;
4174 }
4175
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03004176 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004177
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004178 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4179
4180 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4181 chan->expected_ack_seq);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004182
4183 /* check for invalid req-seq */
4184 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004185 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004186 goto drop;
4187 }
4188
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004189 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004190 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004191 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004192 goto drop;
4193 }
4194
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004195 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004196 } else {
4197 if (len != 0) {
4198 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03004199 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004200 goto drop;
4201 }
4202
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03004203 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004204 }
4205
4206 return 0;
4207
4208drop:
4209 kfree_skb(skb);
4210 return 0;
4211}
4212
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
4214{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004215 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07004216 struct sock *sk = NULL;
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004217 u32 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004218 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03004219 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004220
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004221 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004222 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004223 BT_DBG("unknown cid 0x%4.4x", cid);
4224 goto drop;
4225 }
4226
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004227 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004228
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03004229 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004231 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232 goto drop;
4233
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004234 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004235 case L2CAP_MODE_BASIC:
4236 /* If socket recv buffers overflows we drop data here
4237 * which is *bad* because L2CAP has to be reliable.
4238 * But we don't have any other choice. L2CAP doesn't
4239 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004240
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004241 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004242 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004243
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004244 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004245 goto done;
4246 break;
4247
4248 case L2CAP_MODE_ERTM:
Andrei Emeltchenko5ef8cb92012-01-13 17:21:42 +02004249 l2cap_ertm_data_rcv(chan, skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004250
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02004251 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004252
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004253 case L2CAP_MODE_STREAMING:
Andrei Emeltchenko88843ab2011-10-17 12:19:56 +03004254 control = __get_control(chan, skb->data);
4255 skb_pull(skb, __ctrl_size(chan));
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004256 len = skb->len;
4257
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004258 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03004259 goto drop;
4260
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03004261 if (__is_sar_start(chan, control))
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004262 len -= L2CAP_SDULEN_SIZE;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004263
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03004264 if (chan->fcs == L2CAP_FCS_CRC16)
Andrei Emeltchenko03a51212011-10-17 12:19:58 +03004265 len -= L2CAP_FCS_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03004266
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03004267 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004268 goto drop;
4269
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03004270 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004271
Mat Martineau84084a32011-07-22 14:54:00 -07004272 if (chan->expected_tx_seq != tx_seq) {
4273 /* Frame(s) missing - must discard partial SDU */
4274 kfree_skb(chan->sdu);
4275 chan->sdu = NULL;
4276 chan->sdu_last_frag = NULL;
4277 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004278
Mat Martineau84084a32011-07-22 14:54:00 -07004279 /* TODO: Notify userland of missing data */
4280 }
4281
Andrei Emeltchenko836be932011-10-17 12:19:57 +03004282 chan->expected_tx_seq = __next_seq(chan, tx_seq);
Mat Martineau84084a32011-07-22 14:54:00 -07004283
4284 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
4285 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03004286
4287 goto done;
4288
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004289 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004290 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004291 break;
4292 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293
4294drop:
4295 kfree_skb(skb);
4296
4297done:
Marcel Holtmann01394182006-07-03 10:02:46 +02004298 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004299 release_sock(sk);
Marcel Holtmann01394182006-07-03 10:02:46 +02004300
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301 return 0;
4302}
4303
Al Viro8e036fc2007-07-29 00:16:36 -07004304static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004306 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004307 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004309 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
4310 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311 goto drop;
4312
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004313 sk = chan->sk;
4314
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004315 lock_sock(sk);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00004316
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317 BT_DBG("sk %p, len %d", sk, skb->len);
4318
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004319 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004320 goto drop;
4321
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004322 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323 goto drop;
4324
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004325 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326 goto done;
4327
4328drop:
4329 kfree_skb(skb);
4330
4331done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004332 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004333 release_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334 return 0;
4335}
4336
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004337static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
4338{
David S. Miller6dcae1e2011-05-16 23:09:26 -04004339 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004340 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004341
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004342 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4343 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004344 goto drop;
4345
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004346 sk = chan->sk;
4347
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004348 lock_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004349
4350 BT_DBG("sk %p, len %d", sk, skb->len);
4351
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004352 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004353 goto drop;
4354
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03004355 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004356 goto drop;
4357
Gustavo F. Padovan23070492011-05-16 17:57:22 -03004358 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004359 goto done;
4360
4361drop:
4362 kfree_skb(skb);
4363
4364done:
4365 if (sk)
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004366 release_sock(sk);
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004367 return 0;
4368}
4369
Linus Torvalds1da177e2005-04-16 15:20:36 -07004370static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4371{
4372 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004373 u16 cid, len;
4374 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375
4376 skb_pull(skb, L2CAP_HDR_SIZE);
4377 cid = __le16_to_cpu(lh->cid);
4378 len = __le16_to_cpu(lh->len);
4379
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004380 if (len != skb->len) {
4381 kfree_skb(skb);
4382 return;
4383 }
4384
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4386
4387 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004388 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004389 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004390 l2cap_sig_channel(conn, skb);
4391 break;
4392
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004393 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004394 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004395 skb_pull(skb, 2);
4396 l2cap_conless_channel(conn, psm, skb);
4397 break;
4398
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004399 case L2CAP_CID_LE_DATA:
4400 l2cap_att_channel(conn, cid, skb);
4401 break;
4402
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004403 case L2CAP_CID_SMP:
4404 if (smp_sig_channel(conn, skb))
4405 l2cap_conn_del(conn->hcon, EACCES);
4406 break;
4407
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408 default:
4409 l2cap_data_channel(conn, cid, skb);
4410 break;
4411 }
4412}
4413
4414/* ---- L2CAP interface with lower layer (HCI) ---- */
4415
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004416int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417{
4418 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004419 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4422
4423 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004424 read_lock(&chan_list_lock);
4425 list_for_each_entry(c, &chan_list, global_l) {
4426 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004427
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004428 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429 continue;
4430
4431 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004432 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004433 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004434 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004436 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4437 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004438 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004439 lm2 |= HCI_LM_MASTER;
4440 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004441 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004442 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443
4444 return exact ? lm1 : lm2;
4445}
4446
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004447int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004448{
Marcel Holtmann01394182006-07-03 10:02:46 +02004449 struct l2cap_conn *conn;
4450
Linus Torvalds1da177e2005-04-16 15:20:36 -07004451 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4452
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454 conn = l2cap_conn_add(hcon, status);
4455 if (conn)
4456 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004457 } else
Joe Perchese1750722011-06-29 18:18:29 -07004458 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004459
4460 return 0;
4461}
4462
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004463int l2cap_disconn_ind(struct hci_conn *hcon)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004464{
4465 struct l2cap_conn *conn = hcon->l2cap_data;
4466
4467 BT_DBG("hcon %p", hcon);
4468
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004469 if (!conn)
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +02004470 return HCI_ERROR_REMOTE_USER_TERM;
Marcel Holtmann2950f212009-02-12 14:02:50 +01004471 return conn->disc_reason;
4472}
4473
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004474int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475{
4476 BT_DBG("hcon %p reason %d", hcon, reason);
4477
Joe Perchese1750722011-06-29 18:18:29 -07004478 l2cap_conn_del(hcon, bt_to_errno(reason));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004479 return 0;
4480}
4481
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004482static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004483{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004484 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004485 return;
4486
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004487 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004488 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004489 __clear_chan_timer(chan);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004490 __set_chan_timer(chan,
4491 msecs_to_jiffies(L2CAP_ENC_TIMEOUT));
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004492 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004493 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004494 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004495 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004496 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004497 }
4498}
4499
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004500int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004501{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004502 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004503 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004504
Marcel Holtmann01394182006-07-03 10:02:46 +02004505 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004506 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004507
Linus Torvalds1da177e2005-04-16 15:20:36 -07004508 BT_DBG("conn %p", conn);
4509
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004510 if (hcon->type == LE_LINK) {
4511 smp_distribute_keys(conn, 0);
Ulisses Furquim371fd832011-12-21 20:02:36 -02004512 __cancel_delayed_work(&conn->security_timer);
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004513 }
4514
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02004515 rcu_read_lock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004516
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02004517 list_for_each_entry_rcu(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004518 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004519
Linus Torvalds1da177e2005-04-16 15:20:36 -07004520 bh_lock_sock(sk);
4521
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004522 BT_DBG("chan->scid %d", chan->scid);
4523
4524 if (chan->scid == L2CAP_CID_LE_DATA) {
4525 if (!status && encrypt) {
4526 chan->sec_level = hcon->sec_level;
4527 l2cap_chan_ready(sk);
4528 }
4529
4530 bh_unlock_sock(sk);
4531 continue;
4532 }
4533
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004534 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004535 bh_unlock_sock(sk);
4536 continue;
4537 }
4538
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004539 if (!status && (chan->state == BT_CONNECTED ||
4540 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004541 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004542 bh_unlock_sock(sk);
4543 continue;
4544 }
4545
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004546 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004547 if (!status) {
4548 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004549 req.scid = cpu_to_le16(chan->scid);
4550 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004551
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004552 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004553 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004554
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004555 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004556 L2CAP_CONN_REQ, sizeof(req), &req);
4557 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004558 __clear_chan_timer(chan);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004559 __set_chan_timer(chan,
4560 msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004561 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004562 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004563 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004564 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004565
4566 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004567 if (bt_sk(sk)->defer_setup) {
4568 struct sock *parent = bt_sk(sk)->parent;
4569 res = L2CAP_CR_PEND;
4570 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004571 if (parent)
4572 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004573 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004574 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004575 res = L2CAP_CR_SUCCESS;
4576 stat = L2CAP_CS_NO_INFO;
4577 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004578 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004579 l2cap_state_change(chan, BT_DISCONN);
Andrzej Kaczmarekb83ddfe2012-01-04 12:10:42 +01004580 __set_chan_timer(chan,
4581 msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004582 res = L2CAP_CR_SEC_BLOCK;
4583 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004584 }
4585
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004586 rsp.scid = cpu_to_le16(chan->dcid);
4587 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004588 rsp.result = cpu_to_le16(res);
4589 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004590 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4591 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004592 }
4593
Linus Torvalds1da177e2005-04-16 15:20:36 -07004594 bh_unlock_sock(sk);
4595 }
4596
Gustavo F. Padovan3d57dc62011-12-17 10:56:45 -02004597 rcu_read_unlock();
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004598
Linus Torvalds1da177e2005-04-16 15:20:36 -07004599 return 0;
4600}
4601
Ulisses Furquim686ebf22011-12-21 10:11:33 -02004602int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004603{
4604 struct l2cap_conn *conn = hcon->l2cap_data;
4605
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004606 if (!conn)
4607 conn = l2cap_conn_add(hcon, 0);
4608
4609 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004610 goto drop;
4611
4612 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4613
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004614 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004615 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004616 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004617 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004618 int len;
4619
4620 if (conn->rx_len) {
4621 BT_ERR("Unexpected start frame (len %d)", skb->len);
4622 kfree_skb(conn->rx_skb);
4623 conn->rx_skb = NULL;
4624 conn->rx_len = 0;
4625 l2cap_conn_unreliable(conn, ECOMM);
4626 }
4627
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004628 /* Start fragment always begin with Basic L2CAP header */
4629 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004630 BT_ERR("Frame is too short (len %d)", skb->len);
4631 l2cap_conn_unreliable(conn, ECOMM);
4632 goto drop;
4633 }
4634
4635 hdr = (struct l2cap_hdr *) skb->data;
4636 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004637 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004638
4639 if (len == skb->len) {
4640 /* Complete frame received */
4641 l2cap_recv_frame(conn, skb);
4642 return 0;
4643 }
4644
4645 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4646
4647 if (skb->len > len) {
4648 BT_ERR("Frame is too long (len %d, expected len %d)",
4649 skb->len, len);
4650 l2cap_conn_unreliable(conn, ECOMM);
4651 goto drop;
4652 }
4653
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004654 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004655
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004656 if (chan && chan->sk) {
4657 struct sock *sk = chan->sk;
4658
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004659 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004660 BT_ERR("Frame exceeding recv MTU (len %d, "
4661 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004662 chan->imtu);
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004663 release_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004664 l2cap_conn_unreliable(conn, ECOMM);
4665 goto drop;
4666 }
Gustavo F. Padovanaa2ac882011-06-24 01:53:01 -03004667 release_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004668 }
4669
Linus Torvalds1da177e2005-04-16 15:20:36 -07004670 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004671 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4672 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004673 goto drop;
4674
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004675 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004676 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004677 conn->rx_len = len - skb->len;
4678 } else {
4679 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4680
4681 if (!conn->rx_len) {
4682 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4683 l2cap_conn_unreliable(conn, ECOMM);
4684 goto drop;
4685 }
4686
4687 if (skb->len > conn->rx_len) {
4688 BT_ERR("Fragment is too long (len %d, expected %d)",
4689 skb->len, conn->rx_len);
4690 kfree_skb(conn->rx_skb);
4691 conn->rx_skb = NULL;
4692 conn->rx_len = 0;
4693 l2cap_conn_unreliable(conn, ECOMM);
4694 goto drop;
4695 }
4696
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004697 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004698 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004699 conn->rx_len -= skb->len;
4700
4701 if (!conn->rx_len) {
4702 /* Complete frame received */
4703 l2cap_recv_frame(conn, conn->rx_skb);
4704 conn->rx_skb = NULL;
4705 }
4706 }
4707
4708drop:
4709 kfree_skb(skb);
4710 return 0;
4711}
4712
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004713static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004714{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004715 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004716
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004717 read_lock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004718
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004719 list_for_each_entry(c, &chan_list, global_l) {
4720 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004721
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004722 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 +01004723 batostr(&bt_sk(sk)->src),
4724 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004725 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004726 c->scid, c->dcid, c->imtu, c->omtu,
4727 c->sec_level, c->mode);
Andrei Emeltchenko61e1b4b2012-01-19 11:19:50 +02004728 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004729
Gustavo F. Padovan333055f2011-12-22 15:14:39 -02004730 read_unlock(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004731
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004732 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004733}
4734
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004735static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4736{
4737 return single_open(file, l2cap_debugfs_show, inode->i_private);
4738}
4739
4740static const struct file_operations l2cap_debugfs_fops = {
4741 .open = l2cap_debugfs_open,
4742 .read = seq_read,
4743 .llseek = seq_lseek,
4744 .release = single_release,
4745};
4746
4747static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004748
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004749int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004750{
4751 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004752
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004753 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004754 if (err < 0)
4755 return err;
4756
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004757 if (bt_debugfs) {
4758 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4759 bt_debugfs, NULL, &l2cap_debugfs_fops);
4760 if (!l2cap_debugfs)
4761 BT_ERR("Failed to create L2CAP debug file");
4762 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004763
Linus Torvalds1da177e2005-04-16 15:20:36 -07004764 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004765}
4766
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004767void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004768{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004769 debugfs_remove(l2cap_debugfs);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004770 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004771}
4772
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004773module_param(disable_ertm, bool, 0644);
4774MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");