blob: 5ea94a1eecf2f9a4338aa116d645b03b77fa7bd6 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
7 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation;
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
16 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090017 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090022 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
23 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 SOFTWARE IS DISCLAIMED.
25*/
26
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020027/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30
31#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080032#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
34#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/poll.h>
38#include <linux/fcntl.h>
39#include <linux/init.h>
40#include <linux/interrupt.h>
41#include <linux/socket.h>
42#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080044#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010045#include <linux/debugfs.h>
46#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030047#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030048#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/sock.h>
50
51#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
Anderson Brigliab501d6a2011-06-07 18:46:31 -030057#include <net/bluetooth/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020059int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020060
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070061static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010062static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Johannes Bergb5ad8b72011-06-01 08:54:45 +020064static LIST_HEAD(chan_list);
65static DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
Linus Torvalds1da177e2005-04-16 15:20:36 -070067static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
68 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030069static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
70 void *data);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -030071static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030072static void l2cap_send_disconn_req(struct l2cap_conn *conn,
73 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030075static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
76
Marcel Holtmann01394182006-07-03 10:02:46 +020077/* ---- L2CAP channels ---- */
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -030078
79static inline void chan_hold(struct l2cap_chan *c)
80{
81 atomic_inc(&c->refcnt);
82}
83
84static inline void chan_put(struct l2cap_chan *c)
85{
86 if (atomic_dec_and_test(&c->refcnt))
87 kfree(c);
88}
89
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030090static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020091{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030092 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030093
94 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030095 if (c->dcid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030096 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020097 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030098 return NULL;
99
Marcel Holtmann01394182006-07-03 10:02:46 +0200100}
101
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300102static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200103{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300104 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300105
106 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300107 if (c->scid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300108 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200109 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300110 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200111}
112
113/* Find channel with given SCID.
114 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300115static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200116{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300117 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300118
119 read_lock(&conn->chan_lock);
120 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300121 if (c)
122 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300123 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300124 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200125}
126
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300127static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200128{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300129 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300130
131 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300132 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300133 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200134 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300135 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200136}
137
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300138static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200139{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300140 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300141
142 read_lock(&conn->chan_lock);
143 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300144 if (c)
145 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300146 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300147 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200148}
149
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300150static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300151{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300152 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300153
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300154 list_for_each_entry(c, &chan_list, global_l) {
155 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300156 goto found;
157 }
158
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300159 c = NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300160found:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300161 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300162}
163
164int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
165{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300166 int err;
167
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300168 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300169
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300170 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300171 err = -EADDRINUSE;
172 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300173 }
174
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300175 if (psm) {
176 chan->psm = psm;
177 chan->sport = psm;
178 err = 0;
179 } else {
180 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300181
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300182 err = -EINVAL;
183 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300184 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300185 chan->psm = cpu_to_le16(p);
186 chan->sport = cpu_to_le16(p);
187 err = 0;
188 break;
189 }
190 }
191
192done:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300193 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300194 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300195}
196
197int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
198{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300199 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300200
201 chan->scid = scid;
202
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300203 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300204
205 return 0;
206}
207
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300208static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200209{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300210 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200211
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300212 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300213 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200214 return cid;
215 }
216
217 return 0;
218}
219
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300220static void l2cap_set_timer(struct l2cap_chan *chan, struct timer_list *timer, long timeout)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300221{
Mat Martineau774e5652011-06-29 14:35:20 -0700222 BT_DBG("chan %p state %d timeout %ld", chan->sk, chan->state, timeout);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300223
Mat Martineau942ecc92011-06-29 14:35:21 -0700224 if (!mod_timer(timer, jiffies + msecs_to_jiffies(timeout)))
Mat Martineau774e5652011-06-29 14:35:20 -0700225 chan_hold(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300226}
227
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300228static void l2cap_clear_timer(struct l2cap_chan *chan, struct timer_list *timer)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300229{
Mat Martineau774e5652011-06-29 14:35:20 -0700230 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300231
Mat Martineau774e5652011-06-29 14:35:20 -0700232 if (timer_pending(timer) && del_timer(timer))
233 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300234}
235
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300236static void l2cap_state_change(struct l2cap_chan *chan, int state)
237{
238 chan->state = state;
239 chan->ops->state_change(chan->data, state);
240}
241
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300242static void l2cap_chan_timeout(unsigned long arg)
243{
244 struct l2cap_chan *chan = (struct l2cap_chan *) arg;
245 struct sock *sk = chan->sk;
246 int reason;
247
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300248 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300249
250 bh_lock_sock(sk);
251
252 if (sock_owned_by_user(sk)) {
253 /* sk is owned by user. Try again later */
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -0200254 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300255 bh_unlock_sock(sk);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300256 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300257 return;
258 }
259
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300260 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300261 reason = ECONNREFUSED;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300262 else if (chan->state == BT_CONNECT &&
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300263 chan->sec_level != BT_SECURITY_SDP)
264 reason = ECONNREFUSED;
265 else
266 reason = ETIMEDOUT;
267
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300268 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300269
270 bh_unlock_sock(sk);
271
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300272 chan->ops->close(chan->data);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300273 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300274}
275
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300276struct l2cap_chan *l2cap_chan_create(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200277{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300278 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200279
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300280 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
281 if (!chan)
282 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200283
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300284 chan->sk = sk;
285
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300286 write_lock_bh(&chan_list_lock);
287 list_add(&chan->global_l, &chan_list);
288 write_unlock_bh(&chan_list_lock);
289
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300290 setup_timer(&chan->chan_timer, l2cap_chan_timeout, (unsigned long) chan);
291
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300292 chan->state = BT_OPEN;
293
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300294 atomic_set(&chan->refcnt, 1);
295
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300296 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200297}
298
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300299void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300300{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300301 write_lock_bh(&chan_list_lock);
302 list_del(&chan->global_l);
303 write_unlock_bh(&chan_list_lock);
304
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300305 chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300306}
307
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300308static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200309{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300310 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300311 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200312
Marcel Holtmann2950f212009-02-12 14:02:50 +0100313 conn->disc_reason = 0x13;
314
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300315 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200316
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300317 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
Ville Tervob62f3282011-02-10 22:38:50 -0300318 if (conn->hcon->type == LE_LINK) {
319 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300320 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300321 chan->scid = L2CAP_CID_LE_DATA;
322 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300323 } else {
324 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300325 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300326 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300327 }
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300328 } else if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200329 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300330 chan->scid = L2CAP_CID_CONN_LESS;
331 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300332 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200333 } else {
334 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300335 chan->scid = L2CAP_CID_SIGNALING;
336 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300337 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200338 }
339
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300340 chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300341
342 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200343}
344
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900345/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200346 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300347static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200348{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300349 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300350 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200351 struct sock *parent = bt_sk(sk)->parent;
352
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300353 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200354
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300355 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200356
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900357 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300358 /* Delete from channel list */
359 write_lock_bh(&conn->chan_lock);
360 list_del(&chan->list);
361 write_unlock_bh(&conn->chan_lock);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300362 chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300363
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300364 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200365 hci_conn_put(conn->hcon);
366 }
367
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300368 l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200369 sock_set_flag(sk, SOCK_ZAPPED);
370
371 if (err)
372 sk->sk_err = err;
373
374 if (parent) {
375 bt_accept_unlink(sk);
376 parent->sk_data_ready(parent, 0);
377 } else
378 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300379
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300380 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
381 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300382 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300383
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300384 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300385
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300386 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300387 struct srej_list *l, *tmp;
388
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300389 __clear_retrans_timer(chan);
390 __clear_monitor_timer(chan);
391 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300392
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300393 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300394
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300395 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300396 list_del(&l->list);
397 kfree(l);
398 }
399 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200400}
401
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300402static void l2cap_chan_cleanup_listen(struct sock *parent)
403{
404 struct sock *sk;
405
406 BT_DBG("parent %p", parent);
407
408 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300409 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300410 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300411 __clear_chan_timer(chan);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300412 lock_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300413 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300414 release_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300415 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300416 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300417}
418
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300419void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300420{
421 struct l2cap_conn *conn = chan->conn;
422 struct sock *sk = chan->sk;
423
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300424 BT_DBG("chan %p state %d socket %p", chan, chan->state, sk->sk_socket);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300425
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300426 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300427 case BT_LISTEN:
428 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300429
430 l2cap_state_change(chan, BT_CLOSED);
431 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300432 break;
433
434 case BT_CONNECTED:
435 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300436 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300437 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300438 __clear_chan_timer(chan);
439 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300440 l2cap_send_disconn_req(conn, chan, reason);
441 } else
442 l2cap_chan_del(chan, reason);
443 break;
444
445 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300446 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300447 conn->hcon->type == ACL_LINK) {
448 struct l2cap_conn_rsp rsp;
449 __u16 result;
450
451 if (bt_sk(sk)->defer_setup)
452 result = L2CAP_CR_SEC_BLOCK;
453 else
454 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300455 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300456
457 rsp.scid = cpu_to_le16(chan->dcid);
458 rsp.dcid = cpu_to_le16(chan->scid);
459 rsp.result = cpu_to_le16(result);
460 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
461 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
462 sizeof(rsp), &rsp);
463 }
464
465 l2cap_chan_del(chan, reason);
466 break;
467
468 case BT_CONNECT:
469 case BT_DISCONN:
470 l2cap_chan_del(chan, reason);
471 break;
472
473 default:
474 sock_set_flag(sk, SOCK_ZAPPED);
475 break;
476 }
477}
478
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300479static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530480{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300481 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300482 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530483 case BT_SECURITY_HIGH:
484 return HCI_AT_DEDICATED_BONDING_MITM;
485 case BT_SECURITY_MEDIUM:
486 return HCI_AT_DEDICATED_BONDING;
487 default:
488 return HCI_AT_NO_BONDING;
489 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300490 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300491 if (chan->sec_level == BT_SECURITY_LOW)
492 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530493
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300494 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530495 return HCI_AT_NO_BONDING_MITM;
496 else
497 return HCI_AT_NO_BONDING;
498 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300499 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530500 case BT_SECURITY_HIGH:
501 return HCI_AT_GENERAL_BONDING_MITM;
502 case BT_SECURITY_MEDIUM:
503 return HCI_AT_GENERAL_BONDING;
504 default:
505 return HCI_AT_NO_BONDING;
506 }
507 }
508}
509
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200510/* Service level security */
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300511static inline int l2cap_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200512{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300513 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100514 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200515
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300516 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100517
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300518 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200519}
520
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200521static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200522{
523 u8 id;
524
525 /* Get next available identificator.
526 * 1 - 128 are used by kernel.
527 * 129 - 199 are reserved.
528 * 200 - 254 are used by utilities like l2ping, etc.
529 */
530
531 spin_lock_bh(&conn->lock);
532
533 if (++conn->tx_ident > 128)
534 conn->tx_ident = 1;
535
536 id = conn->tx_ident;
537
538 spin_unlock_bh(&conn->lock);
539
540 return id;
541}
542
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300543static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200544{
545 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200546 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200547
548 BT_DBG("code 0x%2.2x", code);
549
550 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300551 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200552
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200553 if (lmp_no_flush_capable(conn->hcon->hdev))
554 flags = ACL_START_NO_FLUSH;
555 else
556 flags = ACL_START;
557
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700558 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
559
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200560 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200561}
562
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300563static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300564{
565 struct sk_buff *skb;
566 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300567 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300568 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200569 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300570
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300571 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300572 return;
573
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300574 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300575 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300576
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300577 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300578
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300579 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300580 control |= L2CAP_CTRL_FRAME_TYPE;
581
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300582 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300583 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300584
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300585 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300586 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300587
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300588 skb = bt_skb_alloc(count, GFP_ATOMIC);
589 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300590 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300591
592 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300593 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300594 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300595 put_unaligned_le16(control, skb_put(skb, 2));
596
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300597 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300598 u16 fcs = crc16(0, (u8 *)lh, count - 2);
599 put_unaligned_le16(fcs, skb_put(skb, 2));
600 }
601
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200602 if (lmp_no_flush_capable(conn->hcon->hdev))
603 flags = ACL_START_NO_FLUSH;
604 else
605 flags = ACL_START;
606
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700607 bt_cb(skb)->force_active = chan->force_active;
608
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300609 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300610}
611
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300612static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300613{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300614 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300615 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300616 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300617 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300618 control |= L2CAP_SUPER_RCV_READY;
619
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300620 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300621
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300622 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300623}
624
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300625static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300626{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300627 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300628}
629
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300630static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200631{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300632 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200633
634 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100635 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
636 return;
637
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300638 if (l2cap_check_security(chan) &&
639 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200640 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300641 req.scid = cpu_to_le16(chan->scid);
642 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200643
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300644 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300645 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200646
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300647 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
648 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200649 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200650 } else {
651 struct l2cap_info_req req;
652 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
653
654 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
655 conn->info_ident = l2cap_get_ident(conn);
656
657 mod_timer(&conn->info_timer, jiffies +
658 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
659
660 l2cap_send_cmd(conn, conn->info_ident,
661 L2CAP_INFO_REQ, sizeof(req), &req);
662 }
663}
664
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300665static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
666{
667 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300668 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300669 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
670
671 switch (mode) {
672 case L2CAP_MODE_ERTM:
673 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
674 case L2CAP_MODE_STREAMING:
675 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
676 default:
677 return 0x00;
678 }
679}
680
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300681static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300682{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300683 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300684 struct l2cap_disconn_req req;
685
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300686 if (!conn)
687 return;
688
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300689 sk = chan->sk;
690
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300691 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300692 __clear_retrans_timer(chan);
693 __clear_monitor_timer(chan);
694 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300695 }
696
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300697 req.dcid = cpu_to_le16(chan->dcid);
698 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300699 l2cap_send_cmd(conn, l2cap_get_ident(conn),
700 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300701
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300702 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300703 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300704}
705
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200707static void l2cap_conn_start(struct l2cap_conn *conn)
708{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300709 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200710
711 BT_DBG("conn %p", conn);
712
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300713 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200714
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300715 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300716 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300717
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200718 bh_lock_sock(sk);
719
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300720 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200721 bh_unlock_sock(sk);
722 continue;
723 }
724
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300725 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300726 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300727
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300728 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300729 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300730 bh_unlock_sock(sk);
731 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200732 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300733
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300734 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
735 && test_bit(CONF_STATE2_DEVICE,
736 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300737 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300738 * so release the lock */
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300739 read_unlock(&conn->chan_lock);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300740 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300741 read_lock(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300742 bh_unlock_sock(sk);
743 continue;
744 }
745
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300746 req.scid = cpu_to_le16(chan->scid);
747 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300748
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300749 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300750 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300751
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300752 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
753 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300754
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300755 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200756 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300757 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300758 rsp.scid = cpu_to_le16(chan->dcid);
759 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200760
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300761 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100762 if (bt_sk(sk)->defer_setup) {
763 struct sock *parent = bt_sk(sk)->parent;
764 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
765 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000766 if (parent)
767 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100768
769 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300770 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100771 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
772 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
773 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200774 } else {
775 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
776 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
777 }
778
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300779 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
780 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300781
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300782 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300783 rsp.result != L2CAP_CR_SUCCESS) {
784 bh_unlock_sock(sk);
785 continue;
786 }
787
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300788 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300789 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300790 l2cap_build_conf_req(chan, buf), buf);
791 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200792 }
793
794 bh_unlock_sock(sk);
795 }
796
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300797 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200798}
799
Ville Tervob62f3282011-02-10 22:38:50 -0300800/* Find socket with cid and source bdaddr.
801 * Returns closest match, locked.
802 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300803static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300804{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300805 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300806
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300807 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300808
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300809 list_for_each_entry(c, &chan_list, global_l) {
810 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300811
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300812 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300813 continue;
814
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300815 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300816 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300817 if (!bacmp(&bt_sk(sk)->src, src)) {
818 read_unlock(&chan_list_lock);
819 return c;
820 }
Ville Tervob62f3282011-02-10 22:38:50 -0300821
822 /* Closest match */
823 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300824 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300825 }
826 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300827
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300828 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300829
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300830 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300831}
832
833static void l2cap_le_conn_ready(struct l2cap_conn *conn)
834{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300835 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300836 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300837
838 BT_DBG("");
839
840 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300841 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300842 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300843 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300844 return;
845
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300846 parent = pchan->sk;
847
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300848 bh_lock_sock(parent);
849
Ville Tervob62f3282011-02-10 22:38:50 -0300850 /* Check for backlog size */
851 if (sk_acceptq_is_full(parent)) {
852 BT_DBG("backlog full %d", parent->sk_ack_backlog);
853 goto clean;
854 }
855
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300856 chan = pchan->ops->new_connection(pchan->data);
857 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300858 goto clean;
859
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300860 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300861
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300862 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300863
864 hci_conn_hold(conn->hcon);
865
Ville Tervob62f3282011-02-10 22:38:50 -0300866 bacpy(&bt_sk(sk)->src, conn->src);
867 bacpy(&bt_sk(sk)->dst, conn->dst);
868
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300869 bt_accept_enqueue(parent, sk);
870
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300871 __l2cap_chan_add(conn, chan);
872
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300873 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300874
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300875 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300876 parent->sk_data_ready(parent, 0);
877
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300878 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300879
880clean:
881 bh_unlock_sock(parent);
882}
883
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300884static void l2cap_chan_ready(struct sock *sk)
885{
886 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
887 struct sock *parent = bt_sk(sk)->parent;
888
889 BT_DBG("sk %p, parent %p", sk, parent);
890
891 chan->conf_state = 0;
892 __clear_chan_timer(chan);
893
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300894 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300895 sk->sk_state_change(sk);
896
897 if (parent)
898 parent->sk_data_ready(parent, 0);
899}
900
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200901static void l2cap_conn_ready(struct l2cap_conn *conn)
902{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300903 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200904
905 BT_DBG("conn %p", conn);
906
Ville Tervob62f3282011-02-10 22:38:50 -0300907 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
908 l2cap_le_conn_ready(conn);
909
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300910 if (conn->hcon->out && conn->hcon->type == LE_LINK)
911 smp_conn_security(conn, conn->hcon->pending_sec_level);
912
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300913 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200914
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300915 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300916 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300917
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200918 bh_lock_sock(sk);
919
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300920 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300921 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300922 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300923
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300924 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300925 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300926 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200927 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300928
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300929 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300930 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200931
932 bh_unlock_sock(sk);
933 }
934
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300935 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200936}
937
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200938/* Notify sockets that we cannot guaranty reliability anymore */
939static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
940{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300941 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200942
943 BT_DBG("conn %p", conn);
944
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300945 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200946
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300947 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300948 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300949
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300950 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200951 sk->sk_err = err;
952 }
953
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300954 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200955}
956
957static void l2cap_info_timeout(unsigned long arg)
958{
959 struct l2cap_conn *conn = (void *) arg;
960
Marcel Holtmann984947d2009-02-06 23:35:19 +0100961 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100962 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100963
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200964 l2cap_conn_start(conn);
965}
966
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300967static void l2cap_conn_del(struct hci_conn *hcon, int err)
968{
969 struct l2cap_conn *conn = hcon->l2cap_data;
970 struct l2cap_chan *chan, *l;
971 struct sock *sk;
972
973 if (!conn)
974 return;
975
976 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
977
978 kfree_skb(conn->rx_skb);
979
980 /* Kill channels */
981 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
982 sk = chan->sk;
983 bh_lock_sock(sk);
984 l2cap_chan_del(chan, err);
985 bh_unlock_sock(sk);
986 chan->ops->close(chan->data);
987 }
988
989 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
990 del_timer_sync(&conn->info_timer);
991
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300992 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) {
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300993 del_timer(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300994 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300995 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300996
997 hcon->l2cap_data = NULL;
998 kfree(conn);
999}
1000
1001static void security_timeout(unsigned long arg)
1002{
1003 struct l2cap_conn *conn = (void *) arg;
1004
1005 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1006}
1007
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1009{
Marcel Holtmann01394182006-07-03 10:02:46 +02001010 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011
Marcel Holtmann01394182006-07-03 10:02:46 +02001012 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 return conn;
1014
Marcel Holtmann01394182006-07-03 10:02:46 +02001015 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1016 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018
1019 hcon->l2cap_data = conn;
1020 conn->hcon = hcon;
1021
Marcel Holtmann01394182006-07-03 10:02:46 +02001022 BT_DBG("hcon %p conn %p", hcon, conn);
1023
Ville Tervoacd7d372011-02-10 22:38:49 -03001024 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1025 conn->mtu = hcon->hdev->le_mtu;
1026 else
1027 conn->mtu = hcon->hdev->acl_mtu;
1028
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 conn->src = &hcon->hdev->bdaddr;
1030 conn->dst = &hcon->dst;
1031
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001032 conn->feat_mask = 0;
1033
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001035 rwlock_init(&conn->chan_lock);
1036
1037 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001039 if (hcon->type == LE_LINK)
1040 setup_timer(&conn->security_timer, security_timeout,
1041 (unsigned long) conn);
1042 else
Ville Tervob62f3282011-02-10 22:38:50 -03001043 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +00001044 (unsigned long) conn);
1045
Marcel Holtmann2950f212009-02-12 14:02:50 +01001046 conn->disc_reason = 0x13;
1047
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 return conn;
1049}
1050
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001051static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001053 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001054 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001055 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056}
1057
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059
1060/* Find socket with psm and source bdaddr.
1061 * Returns closest match.
1062 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001063static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001065 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001067 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001068
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001069 list_for_each_entry(c, &chan_list, global_l) {
1070 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001071
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001072 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 continue;
1074
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001075 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001077 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001078 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001079 return c;
1080 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081
1082 /* Closest match */
1083 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001084 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 }
1086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001088 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001089
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001090 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091}
1092
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001093int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001095 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 bdaddr_t *src = &bt_sk(sk)->src;
1097 bdaddr_t *dst = &bt_sk(sk)->dst;
1098 struct l2cap_conn *conn;
1099 struct hci_conn *hcon;
1100 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001101 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001102 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001104 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001105 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001107 hdev = hci_get_route(dst, src);
1108 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 return -EHOSTUNREACH;
1110
1111 hci_dev_lock_bh(hdev);
1112
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001113 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001114
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001115 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001116 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001117 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001118 else
1119 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001120 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001121
Ville Tervo30e76272011-02-22 16:10:53 -03001122 if (IS_ERR(hcon)) {
1123 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001125 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126
1127 conn = l2cap_conn_add(hcon, 0);
1128 if (!conn) {
1129 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001130 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 goto done;
1132 }
1133
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 /* Update source addr of the socket */
1135 bacpy(src, conn->src);
1136
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001137 l2cap_chan_add(conn, chan);
1138
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001139 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001140 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141
1142 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001143 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001144 __clear_chan_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001145 if (l2cap_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001146 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001147 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001148 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 }
1150
Ville Tervo30e76272011-02-22 16:10:53 -03001151 err = 0;
1152
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153done:
1154 hci_dev_unlock_bh(hdev);
1155 hci_dev_put(hdev);
1156 return err;
1157}
1158
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001159int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001160{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001161 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001162 DECLARE_WAITQUEUE(wait, current);
1163 int err = 0;
1164 int timeo = HZ/5;
1165
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001166 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001167 set_current_state(TASK_INTERRUPTIBLE);
1168 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001169 if (!timeo)
1170 timeo = HZ/5;
1171
1172 if (signal_pending(current)) {
1173 err = sock_intr_errno(timeo);
1174 break;
1175 }
1176
1177 release_sock(sk);
1178 timeo = schedule_timeout(timeo);
1179 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001180 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001181
1182 err = sock_error(sk);
1183 if (err)
1184 break;
1185 }
1186 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001187 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001188 return err;
1189}
1190
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001191static void l2cap_monitor_timeout(unsigned long arg)
1192{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001193 struct l2cap_chan *chan = (void *) arg;
1194 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001195
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001196 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001197
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001198 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001199 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001200 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001201 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001202 return;
1203 }
1204
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001205 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001206 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001207
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001208 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001209 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001210}
1211
1212static void l2cap_retrans_timeout(unsigned long arg)
1213{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001214 struct l2cap_chan *chan = (void *) arg;
1215 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001216
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001217 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001218
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001219 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001220 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001221 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001222
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001223 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001224
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001225 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001226 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001227}
1228
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001229static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001230{
1231 struct sk_buff *skb;
1232
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001233 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001234 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001235 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001236 break;
1237
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001238 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001239 kfree_skb(skb);
1240
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001241 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001242 }
1243
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001244 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001245 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001246}
1247
Szymon Janc67c9e842011-07-28 16:24:33 +02001248static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001249{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001250 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001251 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001252
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001253 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001254
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001255 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001256 flags = ACL_START_NO_FLUSH;
1257 else
1258 flags = ACL_START;
1259
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -07001260 bt_cb(skb)->force_active = chan->force_active;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001261 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001262}
1263
Szymon Janc67c9e842011-07-28 16:24:33 +02001264static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001265{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001266 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001267 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001268
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001269 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001270 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001271 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001272 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001273
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001274 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001275 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1276 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001277 }
1278
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001279 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001280
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001281 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001282 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001283}
1284
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001285static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001286{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001287 struct sk_buff *skb, *tx_skb;
1288 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001289
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001290 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001291 if (!skb)
1292 return;
1293
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001294 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001295 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001296 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001297
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001298 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001299 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001300
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001301 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001302
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001303 if (chan->remote_max_tx &&
1304 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001305 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001306 return;
1307 }
1308
1309 tx_skb = skb_clone(skb, GFP_ATOMIC);
1310 bt_cb(skb)->retries++;
1311 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001312 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001313
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001314 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001315 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001316
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001317 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001318 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001319
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001320 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1321
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001322 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001323 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1324 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1325 }
1326
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001327 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001328}
1329
Szymon Janc67c9e842011-07-28 16:24:33 +02001330static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001331{
1332 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001333 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001334 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001335
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001336 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001337 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001338
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001339 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001340
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001341 if (chan->remote_max_tx &&
1342 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001343 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001344 break;
1345 }
1346
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001347 tx_skb = skb_clone(skb, GFP_ATOMIC);
1348
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001349 bt_cb(skb)->retries++;
1350
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001351 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001352 control &= L2CAP_CTRL_SAR;
1353
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001354 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001355 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001356
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001357 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1358 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001359 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1360
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001361
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001362 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001363 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1364 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1365 }
1366
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001367 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001368
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001369 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001370
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001371 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1372 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001373
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301374 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001375 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301376
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001377 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001378
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001379 if (skb_queue_is_last(&chan->tx_q, skb))
1380 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001381 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001382 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001383
1384 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001385 }
1386
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001387 return nsent;
1388}
1389
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001390static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001391{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001392 int ret;
1393
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001394 if (!skb_queue_empty(&chan->tx_q))
1395 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001396
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001397 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001398 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001399 return ret;
1400}
1401
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001402static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001403{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001404 u16 control = 0;
1405
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001406 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001407
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001408 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001409 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001410 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001411 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001412 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001413 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001414
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001415 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001416 return;
1417
1418 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001419 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001420}
1421
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001422static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001423{
1424 struct srej_list *tail;
1425 u16 control;
1426
1427 control = L2CAP_SUPER_SELECT_REJECT;
1428 control |= L2CAP_CTRL_FINAL;
1429
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001430 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001431 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1432
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001433 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001434}
1435
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001436static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001438 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001439 struct sk_buff **frag;
1440 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001442 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001443 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
1445 sent += count;
1446 len -= count;
1447
1448 /* Continuation fragments (no L2CAP header) */
1449 frag = &skb_shinfo(skb)->frag_list;
1450 while (len) {
1451 count = min_t(unsigned int, conn->mtu, len);
1452
1453 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1454 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001455 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001456 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1457 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458
1459 sent += count;
1460 len -= count;
1461
1462 frag = &(*frag)->next;
1463 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
1465 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001466}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
Szymon Janc67c9e842011-07-28 16:24:33 +02001468static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001469{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001470 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001471 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001472 struct sk_buff *skb;
1473 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1474 struct l2cap_hdr *lh;
1475
1476 BT_DBG("sk %p len %d", sk, (int)len);
1477
1478 count = min_t(unsigned int, (conn->mtu - hlen), len);
1479 skb = bt_skb_send_alloc(sk, count + hlen,
1480 msg->msg_flags & MSG_DONTWAIT, &err);
1481 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001482 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001483
1484 /* Create L2CAP header */
1485 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001486 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001487 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001488 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001489
1490 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1491 if (unlikely(err < 0)) {
1492 kfree_skb(skb);
1493 return ERR_PTR(err);
1494 }
1495 return skb;
1496}
1497
Szymon Janc67c9e842011-07-28 16:24:33 +02001498static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001499{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001500 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001501 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001502 struct sk_buff *skb;
1503 int err, count, hlen = L2CAP_HDR_SIZE;
1504 struct l2cap_hdr *lh;
1505
1506 BT_DBG("sk %p len %d", sk, (int)len);
1507
1508 count = min_t(unsigned int, (conn->mtu - hlen), len);
1509 skb = bt_skb_send_alloc(sk, count + hlen,
1510 msg->msg_flags & MSG_DONTWAIT, &err);
1511 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001512 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001513
1514 /* Create L2CAP header */
1515 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001516 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001517 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1518
1519 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1520 if (unlikely(err < 0)) {
1521 kfree_skb(skb);
1522 return ERR_PTR(err);
1523 }
1524 return skb;
1525}
1526
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001527static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1528 struct msghdr *msg, size_t len,
1529 u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001530{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001531 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001532 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001533 struct sk_buff *skb;
1534 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1535 struct l2cap_hdr *lh;
1536
1537 BT_DBG("sk %p len %d", sk, (int)len);
1538
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001539 if (!conn)
1540 return ERR_PTR(-ENOTCONN);
1541
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001542 if (sdulen)
1543 hlen += 2;
1544
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001545 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001546 hlen += 2;
1547
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001548 count = min_t(unsigned int, (conn->mtu - hlen), len);
1549 skb = bt_skb_send_alloc(sk, count + hlen,
1550 msg->msg_flags & MSG_DONTWAIT, &err);
1551 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001552 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001553
1554 /* Create L2CAP header */
1555 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001556 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001557 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1558 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001559 if (sdulen)
1560 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001561
1562 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1563 if (unlikely(err < 0)) {
1564 kfree_skb(skb);
1565 return ERR_PTR(err);
1566 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001567
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001568 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001569 put_unaligned_le16(0, skb_put(skb, 2));
1570
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001571 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001572 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573}
1574
Szymon Janc67c9e842011-07-28 16:24:33 +02001575static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001576{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001577 struct sk_buff *skb;
1578 struct sk_buff_head sar_queue;
1579 u16 control;
1580 size_t size = 0;
1581
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001582 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001583 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001584 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001585 if (IS_ERR(skb))
1586 return PTR_ERR(skb);
1587
1588 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001589 len -= chan->remote_mps;
1590 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001591
1592 while (len > 0) {
1593 size_t buflen;
1594
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001595 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001596 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001597 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001598 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001599 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001600 buflen = len;
1601 }
1602
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001603 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001604 if (IS_ERR(skb)) {
1605 skb_queue_purge(&sar_queue);
1606 return PTR_ERR(skb);
1607 }
1608
1609 __skb_queue_tail(&sar_queue, skb);
1610 len -= buflen;
1611 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001612 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001613 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1614 if (chan->tx_send_head == NULL)
1615 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001616
1617 return size;
1618}
1619
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001620int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1621{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001622 struct sk_buff *skb;
1623 u16 control;
1624 int err;
1625
1626 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001627 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001628 skb = l2cap_create_connless_pdu(chan, msg, len);
1629 if (IS_ERR(skb))
1630 return PTR_ERR(skb);
1631
1632 l2cap_do_send(chan, skb);
1633 return len;
1634 }
1635
1636 switch (chan->mode) {
1637 case L2CAP_MODE_BASIC:
1638 /* Check outgoing MTU */
1639 if (len > chan->omtu)
1640 return -EMSGSIZE;
1641
1642 /* Create a basic PDU */
1643 skb = l2cap_create_basic_pdu(chan, msg, len);
1644 if (IS_ERR(skb))
1645 return PTR_ERR(skb);
1646
1647 l2cap_do_send(chan, skb);
1648 err = len;
1649 break;
1650
1651 case L2CAP_MODE_ERTM:
1652 case L2CAP_MODE_STREAMING:
1653 /* Entire SDU fits into one PDU */
1654 if (len <= chan->remote_mps) {
1655 control = L2CAP_SDU_UNSEGMENTED;
1656 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1657 0);
1658 if (IS_ERR(skb))
1659 return PTR_ERR(skb);
1660
1661 __skb_queue_tail(&chan->tx_q, skb);
1662
1663 if (chan->tx_send_head == NULL)
1664 chan->tx_send_head = skb;
1665
1666 } else {
1667 /* Segment SDU into multiples PDUs */
1668 err = l2cap_sar_segment_sdu(chan, msg, len);
1669 if (err < 0)
1670 return err;
1671 }
1672
1673 if (chan->mode == L2CAP_MODE_STREAMING) {
1674 l2cap_streaming_send(chan);
1675 err = len;
1676 break;
1677 }
1678
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001679 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1680 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001681 err = len;
1682 break;
1683 }
1684
1685 err = l2cap_ertm_send(chan);
1686 if (err >= 0)
1687 err = len;
1688
1689 break;
1690
1691 default:
1692 BT_DBG("bad state %1.1x", chan->mode);
1693 err = -EBADFD;
1694 }
1695
1696 return err;
1697}
1698
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699/* Copy frame to all raw sockets on that connection */
1700static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1701{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001703 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704
1705 BT_DBG("conn %p", conn);
1706
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001707 read_lock(&conn->chan_lock);
1708 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001709 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001710 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 continue;
1712
1713 /* Don't send frame to the socket it came from */
1714 if (skb->sk == sk)
1715 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001716 nskb = skb_clone(skb, GFP_ATOMIC);
1717 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 continue;
1719
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001720 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 kfree_skb(nskb);
1722 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001723 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724}
1725
1726/* ---- L2CAP signalling commands ---- */
1727static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1728 u8 code, u8 ident, u16 dlen, void *data)
1729{
1730 struct sk_buff *skb, **frag;
1731 struct l2cap_cmd_hdr *cmd;
1732 struct l2cap_hdr *lh;
1733 int len, count;
1734
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001735 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1736 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737
1738 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1739 count = min_t(unsigned int, conn->mtu, len);
1740
1741 skb = bt_skb_alloc(count, GFP_ATOMIC);
1742 if (!skb)
1743 return NULL;
1744
1745 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001746 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001747
1748 if (conn->hcon->type == LE_LINK)
1749 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1750 else
1751 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752
1753 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1754 cmd->code = code;
1755 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001756 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757
1758 if (dlen) {
1759 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1760 memcpy(skb_put(skb, count), data, count);
1761 data += count;
1762 }
1763
1764 len -= skb->len;
1765
1766 /* Continuation fragments (no L2CAP header) */
1767 frag = &skb_shinfo(skb)->frag_list;
1768 while (len) {
1769 count = min_t(unsigned int, conn->mtu, len);
1770
1771 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1772 if (!*frag)
1773 goto fail;
1774
1775 memcpy(skb_put(*frag, count), data, count);
1776
1777 len -= count;
1778 data += count;
1779
1780 frag = &(*frag)->next;
1781 }
1782
1783 return skb;
1784
1785fail:
1786 kfree_skb(skb);
1787 return NULL;
1788}
1789
1790static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1791{
1792 struct l2cap_conf_opt *opt = *ptr;
1793 int len;
1794
1795 len = L2CAP_CONF_OPT_SIZE + opt->len;
1796 *ptr += len;
1797
1798 *type = opt->type;
1799 *olen = opt->len;
1800
1801 switch (opt->len) {
1802 case 1:
1803 *val = *((u8 *) opt->val);
1804 break;
1805
1806 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001807 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 break;
1809
1810 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001811 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 break;
1813
1814 default:
1815 *val = (unsigned long) opt->val;
1816 break;
1817 }
1818
1819 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1820 return len;
1821}
1822
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1824{
1825 struct l2cap_conf_opt *opt = *ptr;
1826
1827 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1828
1829 opt->type = type;
1830 opt->len = len;
1831
1832 switch (len) {
1833 case 1:
1834 *((u8 *) opt->val) = val;
1835 break;
1836
1837 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001838 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839 break;
1840
1841 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001842 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 break;
1844
1845 default:
1846 memcpy(opt->val, (void *) val, len);
1847 break;
1848 }
1849
1850 *ptr += L2CAP_CONF_OPT_SIZE + len;
1851}
1852
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001853static void l2cap_ack_timeout(unsigned long arg)
1854{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001855 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001856
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001857 bh_lock_sock(chan->sk);
1858 l2cap_send_ack(chan);
1859 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001860}
1861
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001862static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001863{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001864 struct sock *sk = chan->sk;
1865
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001866 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001867 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001868 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001869 chan->num_acked = 0;
1870 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001871
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001872 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1873 (unsigned long) chan);
1874 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1875 (unsigned long) chan);
1876 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001877
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001878 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001879
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001880 INIT_LIST_HEAD(&chan->srej_l);
1881
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001882
1883 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001884}
1885
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001886static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1887{
1888 switch (mode) {
1889 case L2CAP_MODE_STREAMING:
1890 case L2CAP_MODE_ERTM:
1891 if (l2cap_mode_supported(mode, remote_feat_mask))
1892 return mode;
1893 /* fall through */
1894 default:
1895 return L2CAP_MODE_BASIC;
1896 }
1897}
1898
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03001899static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001902 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 void *ptr = req->data;
1904
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001905 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001907 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001908 goto done;
1909
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001910 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001911 case L2CAP_MODE_STREAMING:
1912 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001913 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001914 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001915
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001916 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001917 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001918 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001919 break;
1920 }
1921
1922done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001923 if (chan->imtu != L2CAP_DEFAULT_MTU)
1924 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001925
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001926 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001927 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001928 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1929 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001930 break;
1931
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001932 rfc.mode = L2CAP_MODE_BASIC;
1933 rfc.txwin_size = 0;
1934 rfc.max_transmit = 0;
1935 rfc.retrans_timeout = 0;
1936 rfc.monitor_timeout = 0;
1937 rfc.max_pdu_size = 0;
1938
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001939 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1940 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001941 break;
1942
1943 case L2CAP_MODE_ERTM:
1944 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001945 rfc.txwin_size = chan->tx_win;
1946 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001947 rfc.retrans_timeout = 0;
1948 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001949 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001950 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1951 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001952
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001953 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1954 (unsigned long) &rfc);
1955
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001956 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001957 break;
1958
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001959 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001960 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001961 chan->fcs = L2CAP_FCS_NONE;
1962 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001963 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001964 break;
1965
1966 case L2CAP_MODE_STREAMING:
1967 rfc.mode = L2CAP_MODE_STREAMING;
1968 rfc.txwin_size = 0;
1969 rfc.max_transmit = 0;
1970 rfc.retrans_timeout = 0;
1971 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001972 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001973 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1974 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001975
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001976 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1977 (unsigned long) &rfc);
1978
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001979 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001980 break;
1981
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001982 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001983 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001984 chan->fcs = L2CAP_FCS_NONE;
1985 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001986 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001987 break;
1988 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001990 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001991 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992
1993 return ptr - data;
1994}
1995
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001996static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001998 struct l2cap_conf_rsp *rsp = data;
1999 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002000 void *req = chan->conf_req;
2001 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002002 int type, hint, olen;
2003 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002004 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002005 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002006 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002008 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002009
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002010 while (len >= L2CAP_CONF_OPT_SIZE) {
2011 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002013 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002014 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002015
2016 switch (type) {
2017 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002018 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002019 break;
2020
2021 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002022 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002023 break;
2024
2025 case L2CAP_CONF_QOS:
2026 break;
2027
Marcel Holtmann6464f352007-10-20 13:39:51 +02002028 case L2CAP_CONF_RFC:
2029 if (olen == sizeof(rfc))
2030 memcpy(&rfc, (void *) val, olen);
2031 break;
2032
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002033 case L2CAP_CONF_FCS:
2034 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002035 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002036
2037 break;
2038
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002039 default:
2040 if (hint)
2041 break;
2042
2043 result = L2CAP_CONF_UNKNOWN;
2044 *((u8 *) ptr++) = type;
2045 break;
2046 }
2047 }
2048
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002049 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002050 goto done;
2051
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002052 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002053 case L2CAP_MODE_STREAMING:
2054 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002055 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002056 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002057 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002058 break;
2059 }
2060
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002061 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002062 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002063
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002064 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002065 }
2066
2067done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002068 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002069 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002070 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002071
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002072 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002073 return -ECONNREFUSED;
2074
2075 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2076 sizeof(rfc), (unsigned long) &rfc);
2077 }
2078
2079
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002080 if (result == L2CAP_CONF_SUCCESS) {
2081 /* Configure output options and let the other side know
2082 * which ones we don't like. */
2083
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002084 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2085 result = L2CAP_CONF_UNACCEPT;
2086 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002087 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002088 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002089 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002090 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002091
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002092 switch (rfc.mode) {
2093 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002094 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002095 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002096 break;
2097
2098 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002099 chan->remote_tx_win = rfc.txwin_size;
2100 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002101
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002102 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2103 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002104
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002105 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002106
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002107 rfc.retrans_timeout =
2108 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2109 rfc.monitor_timeout =
2110 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002111
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002112 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002113
2114 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2115 sizeof(rfc), (unsigned long) &rfc);
2116
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002117 break;
2118
2119 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002120 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2121 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002122
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002123 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002124
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002125 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002126
2127 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2128 sizeof(rfc), (unsigned long) &rfc);
2129
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002130 break;
2131
2132 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002133 result = L2CAP_CONF_UNACCEPT;
2134
2135 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002136 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002137 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002138
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002139 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002140 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002141 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002142 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002143 rsp->result = cpu_to_le16(result);
2144 rsp->flags = cpu_to_le16(0x0000);
2145
2146 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147}
2148
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002149static 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 -03002150{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002151 struct l2cap_conf_req *req = data;
2152 void *ptr = req->data;
2153 int type, olen;
2154 unsigned long val;
2155 struct l2cap_conf_rfc rfc;
2156
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002157 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002158
2159 while (len >= L2CAP_CONF_OPT_SIZE) {
2160 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2161
2162 switch (type) {
2163 case L2CAP_CONF_MTU:
2164 if (val < L2CAP_DEFAULT_MIN_MTU) {
2165 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002166 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002167 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002168 chan->imtu = val;
2169 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002170 break;
2171
2172 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002173 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002174 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002175 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002176 break;
2177
2178 case L2CAP_CONF_RFC:
2179 if (olen == sizeof(rfc))
2180 memcpy(&rfc, (void *)val, olen);
2181
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002182 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002183 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002184 return -ECONNREFUSED;
2185
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002186 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002187
2188 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2189 sizeof(rfc), (unsigned long) &rfc);
2190 break;
2191 }
2192 }
2193
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002194 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002195 return -ECONNREFUSED;
2196
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002197 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002198
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002199 if (*result == L2CAP_CONF_SUCCESS) {
2200 switch (rfc.mode) {
2201 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002202 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2203 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2204 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002205 break;
2206 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002207 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002208 }
2209 }
2210
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002211 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002212 req->flags = cpu_to_le16(0x0000);
2213
2214 return ptr - data;
2215}
2216
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002217static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218{
2219 struct l2cap_conf_rsp *rsp = data;
2220 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002222 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002224 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002225 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002226 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227
2228 return ptr - data;
2229}
2230
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002231void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002232{
2233 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002234 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002235 u8 buf[128];
2236
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002237 rsp.scid = cpu_to_le16(chan->dcid);
2238 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002239 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2240 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2241 l2cap_send_cmd(conn, chan->ident,
2242 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2243
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002244 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002245 return;
2246
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002247 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2248 l2cap_build_conf_req(chan, buf), buf);
2249 chan->num_conf_req++;
2250}
2251
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002252static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002253{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002254 int type, olen;
2255 unsigned long val;
2256 struct l2cap_conf_rfc rfc;
2257
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002258 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002259
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002260 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002261 return;
2262
2263 while (len >= L2CAP_CONF_OPT_SIZE) {
2264 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2265
2266 switch (type) {
2267 case L2CAP_CONF_RFC:
2268 if (olen == sizeof(rfc))
2269 memcpy(&rfc, (void *)val, olen);
2270 goto done;
2271 }
2272 }
2273
2274done:
2275 switch (rfc.mode) {
2276 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002277 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2278 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2279 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002280 break;
2281 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002282 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002283 }
2284}
2285
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002286static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2287{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002288 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002289
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002290 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002291 return 0;
2292
2293 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2294 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002295 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002296
2297 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002298 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002299
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002300 l2cap_conn_start(conn);
2301 }
2302
2303 return 0;
2304}
2305
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2307{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2309 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002310 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002311 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002312 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313
2314 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002315 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316
2317 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2318
2319 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002320 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2321 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 result = L2CAP_CR_BAD_PSM;
2323 goto sendresp;
2324 }
2325
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002326 parent = pchan->sk;
2327
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002328 bh_lock_sock(parent);
2329
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002330 /* Check if the ACL is secure enough (if not SDP) */
2331 if (psm != cpu_to_le16(0x0001) &&
2332 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002333 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002334 result = L2CAP_CR_SEC_BLOCK;
2335 goto response;
2336 }
2337
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 result = L2CAP_CR_NO_MEM;
2339
2340 /* Check for backlog size */
2341 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002342 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343 goto response;
2344 }
2345
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002346 chan = pchan->ops->new_connection(pchan->data);
2347 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 goto response;
2349
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002350 sk = chan->sk;
2351
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002352 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353
2354 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002355 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2356 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002358 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 goto response;
2360 }
2361
2362 hci_conn_hold(conn->hcon);
2363
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364 bacpy(&bt_sk(sk)->src, conn->src);
2365 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002366 chan->psm = psm;
2367 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002369 bt_accept_enqueue(parent, sk);
2370
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002371 __l2cap_chan_add(conn, chan);
2372
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002373 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002375 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002377 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378
Marcel Holtmann984947d2009-02-06 23:35:19 +01002379 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002380 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002381 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002382 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002383 result = L2CAP_CR_PEND;
2384 status = L2CAP_CS_AUTHOR_PEND;
2385 parent->sk_data_ready(parent, 0);
2386 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002387 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002388 result = L2CAP_CR_SUCCESS;
2389 status = L2CAP_CS_NO_INFO;
2390 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002391 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002392 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002393 result = L2CAP_CR_PEND;
2394 status = L2CAP_CS_AUTHEN_PEND;
2395 }
2396 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002397 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002398 result = L2CAP_CR_PEND;
2399 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 }
2401
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002402 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403
2404response:
2405 bh_unlock_sock(parent);
2406
2407sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002408 rsp.scid = cpu_to_le16(scid);
2409 rsp.dcid = cpu_to_le16(dcid);
2410 rsp.result = cpu_to_le16(result);
2411 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002413
2414 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2415 struct l2cap_info_req info;
2416 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2417
2418 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2419 conn->info_ident = l2cap_get_ident(conn);
2420
2421 mod_timer(&conn->info_timer, jiffies +
2422 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2423
2424 l2cap_send_cmd(conn, conn->info_ident,
2425 L2CAP_INFO_REQ, sizeof(info), &info);
2426 }
2427
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002428 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002429 result == L2CAP_CR_SUCCESS) {
2430 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002431 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002432 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002433 l2cap_build_conf_req(chan, buf), buf);
2434 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002435 }
2436
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437 return 0;
2438}
2439
2440static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2441{
2442 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2443 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002444 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 struct sock *sk;
2446 u8 req[128];
2447
2448 scid = __le16_to_cpu(rsp->scid);
2449 dcid = __le16_to_cpu(rsp->dcid);
2450 result = __le16_to_cpu(rsp->result);
2451 status = __le16_to_cpu(rsp->status);
2452
2453 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2454
2455 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002456 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002457 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002458 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002460 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002461 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002462 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 }
2464
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002465 sk = chan->sk;
2466
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 switch (result) {
2468 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002469 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002470 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002471 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002472 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002473
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002474 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002475 break;
2476
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002478 l2cap_build_conf_req(chan, req), req);
2479 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 break;
2481
2482 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002483 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484 break;
2485
2486 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002487 /* don't delete l2cap channel if sk is owned by user */
2488 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002489 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002490 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02002491 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002492 break;
2493 }
2494
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002495 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496 break;
2497 }
2498
2499 bh_unlock_sock(sk);
2500 return 0;
2501}
2502
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002503static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002504{
2505 /* FCS is enabled only in ERTM or streaming mode, if one or both
2506 * sides request it.
2507 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002508 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002509 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002510 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002511 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002512}
2513
Al Viro88219a02007-07-29 00:17:25 -07002514static 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 -07002515{
2516 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2517 u16 dcid, flags;
2518 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002519 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002521 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522
2523 dcid = __le16_to_cpu(req->dcid);
2524 flags = __le16_to_cpu(req->flags);
2525
2526 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2527
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002528 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002529 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530 return -ENOENT;
2531
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002532 sk = chan->sk;
2533
David S. Miller033b1142011-07-21 13:38:42 -07002534 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002535 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002536
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002537 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2538 rej.scid = cpu_to_le16(chan->scid);
2539 rej.dcid = cpu_to_le16(chan->dcid);
2540
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002541 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2542 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002543 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002544 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002545
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002546 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002547 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002548 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002549 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002550 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002551 L2CAP_CONF_REJECT, flags), rsp);
2552 goto unlock;
2553 }
2554
2555 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002556 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2557 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558
2559 if (flags & 0x0001) {
2560 /* Incomplete config. Send empty response. */
2561 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002562 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002563 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564 goto unlock;
2565 }
2566
2567 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002568 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002569 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002570 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002572 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002574 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002575 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002576
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002577 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002578 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002579
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002580 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002581 goto unlock;
2582
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002583 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002584 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002585
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002586 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002587
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002588 chan->next_tx_seq = 0;
2589 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002590 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002591 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002592 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002593
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002595 goto unlock;
2596 }
2597
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002598 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002599 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002601 l2cap_build_conf_req(chan, buf), buf);
2602 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603 }
2604
2605unlock:
2606 bh_unlock_sock(sk);
2607 return 0;
2608}
2609
2610static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2611{
2612 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2613 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002614 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002616 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617
2618 scid = __le16_to_cpu(rsp->scid);
2619 flags = __le16_to_cpu(rsp->flags);
2620 result = __le16_to_cpu(rsp->result);
2621
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002622 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2623 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002625 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002626 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 return 0;
2628
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002629 sk = chan->sk;
2630
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631 switch (result) {
2632 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002633 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634 break;
2635
2636 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002637 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002638 char req[64];
2639
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002640 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002641 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002642 goto done;
2643 }
2644
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002645 /* throw out any old stored conf requests */
2646 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002647 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2648 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002649 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002650 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002651 goto done;
2652 }
2653
2654 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2655 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002656 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002657 if (result != L2CAP_CONF_SUCCESS)
2658 goto done;
2659 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660 }
2661
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002662 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002663 sk->sk_err = ECONNRESET;
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02002664 __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002665 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666 goto done;
2667 }
2668
2669 if (flags & 0x01)
2670 goto done;
2671
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002672 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002674 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002675 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002676
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002677 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002678 chan->next_tx_seq = 0;
2679 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002680 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002681 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002682 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002683
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 l2cap_chan_ready(sk);
2685 }
2686
2687done:
2688 bh_unlock_sock(sk);
2689 return 0;
2690}
2691
2692static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2693{
2694 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2695 struct l2cap_disconn_rsp rsp;
2696 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002697 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698 struct sock *sk;
2699
2700 scid = __le16_to_cpu(req->scid);
2701 dcid = __le16_to_cpu(req->dcid);
2702
2703 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2704
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002705 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002706 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707 return 0;
2708
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002709 sk = chan->sk;
2710
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002711 rsp.dcid = cpu_to_le16(chan->scid);
2712 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2714
2715 sk->sk_shutdown = SHUTDOWN_MASK;
2716
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002717 /* don't delete l2cap channel if sk is owned by user */
2718 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002719 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002720 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02002721 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002722 bh_unlock_sock(sk);
2723 return 0;
2724 }
2725
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002726 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727 bh_unlock_sock(sk);
2728
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002729 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 return 0;
2731}
2732
2733static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2734{
2735 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2736 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002737 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738 struct sock *sk;
2739
2740 scid = __le16_to_cpu(rsp->scid);
2741 dcid = __le16_to_cpu(rsp->dcid);
2742
2743 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2744
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002745 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002746 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747 return 0;
2748
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002749 sk = chan->sk;
2750
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002751 /* don't delete l2cap channel if sk is owned by user */
2752 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002753 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002754 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02002755 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002756 bh_unlock_sock(sk);
2757 return 0;
2758 }
2759
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002760 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 bh_unlock_sock(sk);
2762
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002763 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 return 0;
2765}
2766
2767static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2768{
2769 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 u16 type;
2771
2772 type = __le16_to_cpu(req->type);
2773
2774 BT_DBG("type 0x%4.4x", type);
2775
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002776 if (type == L2CAP_IT_FEAT_MASK) {
2777 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002778 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002779 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2780 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2781 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002782 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002783 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2784 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002785 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002786 l2cap_send_cmd(conn, cmd->ident,
2787 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002788 } else if (type == L2CAP_IT_FIXED_CHAN) {
2789 u8 buf[12];
2790 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2791 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2792 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2793 memcpy(buf + 4, l2cap_fixed_chan, 8);
2794 l2cap_send_cmd(conn, cmd->ident,
2795 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002796 } else {
2797 struct l2cap_info_rsp rsp;
2798 rsp.type = cpu_to_le16(type);
2799 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2800 l2cap_send_cmd(conn, cmd->ident,
2801 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2802 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803
2804 return 0;
2805}
2806
2807static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2808{
2809 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2810 u16 type, result;
2811
2812 type = __le16_to_cpu(rsp->type);
2813 result = __le16_to_cpu(rsp->result);
2814
2815 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2816
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002817 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2818 if (cmd->ident != conn->info_ident ||
2819 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2820 return 0;
2821
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002822 del_timer(&conn->info_timer);
2823
Ville Tervoadb08ed2010-08-04 09:43:33 +03002824 if (result != L2CAP_IR_SUCCESS) {
2825 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2826 conn->info_ident = 0;
2827
2828 l2cap_conn_start(conn);
2829
2830 return 0;
2831 }
2832
Marcel Holtmann984947d2009-02-06 23:35:19 +01002833 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002834 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002835
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002836 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002837 struct l2cap_info_req req;
2838 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2839
2840 conn->info_ident = l2cap_get_ident(conn);
2841
2842 l2cap_send_cmd(conn, conn->info_ident,
2843 L2CAP_INFO_REQ, sizeof(req), &req);
2844 } else {
2845 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2846 conn->info_ident = 0;
2847
2848 l2cap_conn_start(conn);
2849 }
2850 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002851 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002852 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002853
2854 l2cap_conn_start(conn);
2855 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002856
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857 return 0;
2858}
2859
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002860static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002861 u16 to_multiplier)
2862{
2863 u16 max_latency;
2864
2865 if (min > max || min < 6 || max > 3200)
2866 return -EINVAL;
2867
2868 if (to_multiplier < 10 || to_multiplier > 3200)
2869 return -EINVAL;
2870
2871 if (max >= to_multiplier * 8)
2872 return -EINVAL;
2873
2874 max_latency = (to_multiplier * 8 / max) - 1;
2875 if (latency > 499 || latency > max_latency)
2876 return -EINVAL;
2877
2878 return 0;
2879}
2880
2881static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2882 struct l2cap_cmd_hdr *cmd, u8 *data)
2883{
2884 struct hci_conn *hcon = conn->hcon;
2885 struct l2cap_conn_param_update_req *req;
2886 struct l2cap_conn_param_update_rsp rsp;
2887 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002888 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002889
2890 if (!(hcon->link_mode & HCI_LM_MASTER))
2891 return -EINVAL;
2892
2893 cmd_len = __le16_to_cpu(cmd->len);
2894 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2895 return -EPROTO;
2896
2897 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002898 min = __le16_to_cpu(req->min);
2899 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002900 latency = __le16_to_cpu(req->latency);
2901 to_multiplier = __le16_to_cpu(req->to_multiplier);
2902
2903 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2904 min, max, latency, to_multiplier);
2905
2906 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002907
2908 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2909 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002910 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2911 else
2912 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2913
2914 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2915 sizeof(rsp), &rsp);
2916
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002917 if (!err)
2918 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2919
Claudio Takahaside731152011-02-11 19:28:55 -02002920 return 0;
2921}
2922
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002923static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2924 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2925{
2926 int err = 0;
2927
2928 switch (cmd->code) {
2929 case L2CAP_COMMAND_REJ:
2930 l2cap_command_rej(conn, cmd, data);
2931 break;
2932
2933 case L2CAP_CONN_REQ:
2934 err = l2cap_connect_req(conn, cmd, data);
2935 break;
2936
2937 case L2CAP_CONN_RSP:
2938 err = l2cap_connect_rsp(conn, cmd, data);
2939 break;
2940
2941 case L2CAP_CONF_REQ:
2942 err = l2cap_config_req(conn, cmd, cmd_len, data);
2943 break;
2944
2945 case L2CAP_CONF_RSP:
2946 err = l2cap_config_rsp(conn, cmd, data);
2947 break;
2948
2949 case L2CAP_DISCONN_REQ:
2950 err = l2cap_disconnect_req(conn, cmd, data);
2951 break;
2952
2953 case L2CAP_DISCONN_RSP:
2954 err = l2cap_disconnect_rsp(conn, cmd, data);
2955 break;
2956
2957 case L2CAP_ECHO_REQ:
2958 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2959 break;
2960
2961 case L2CAP_ECHO_RSP:
2962 break;
2963
2964 case L2CAP_INFO_REQ:
2965 err = l2cap_information_req(conn, cmd, data);
2966 break;
2967
2968 case L2CAP_INFO_RSP:
2969 err = l2cap_information_rsp(conn, cmd, data);
2970 break;
2971
2972 default:
2973 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2974 err = -EINVAL;
2975 break;
2976 }
2977
2978 return err;
2979}
2980
2981static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2982 struct l2cap_cmd_hdr *cmd, u8 *data)
2983{
2984 switch (cmd->code) {
2985 case L2CAP_COMMAND_REJ:
2986 return 0;
2987
2988 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002989 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002990
2991 case L2CAP_CONN_PARAM_UPDATE_RSP:
2992 return 0;
2993
2994 default:
2995 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2996 return -EINVAL;
2997 }
2998}
2999
3000static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3001 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002{
3003 u8 *data = skb->data;
3004 int len = skb->len;
3005 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003006 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007
3008 l2cap_raw_recv(conn, skb);
3009
3010 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003011 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3013 data += L2CAP_CMD_HDR_SIZE;
3014 len -= L2CAP_CMD_HDR_SIZE;
3015
Al Viro88219a02007-07-29 00:17:25 -07003016 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017
Al Viro88219a02007-07-29 00:17:25 -07003018 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 -07003019
Al Viro88219a02007-07-29 00:17:25 -07003020 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021 BT_DBG("corrupted command");
3022 break;
3023 }
3024
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003025 if (conn->hcon->type == LE_LINK)
3026 err = l2cap_le_sig_cmd(conn, &cmd, data);
3027 else
3028 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029
3030 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003031 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003032
3033 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034
3035 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003036 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3038 }
3039
Al Viro88219a02007-07-29 00:17:25 -07003040 data += cmd_len;
3041 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003042 }
3043
3044 kfree_skb(skb);
3045}
3046
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003047static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003048{
3049 u16 our_fcs, rcv_fcs;
3050 int hdr_size = L2CAP_HDR_SIZE + 2;
3051
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003052 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003053 skb_trim(skb, skb->len - 2);
3054 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3055 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3056
3057 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003058 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003059 }
3060 return 0;
3061}
3062
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003063static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003064{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003065 u16 control = 0;
3066
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003067 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003068
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003069 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003070
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003071 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003072 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003073 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003074 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003075 }
3076
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003077 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003078 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003079
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003080 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003081
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003082 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003083 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003084 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003085 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003086 }
3087}
3088
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003089static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u8 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003090{
3091 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003092 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003093
3094 bt_cb(skb)->tx_seq = tx_seq;
3095 bt_cb(skb)->sar = sar;
3096
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003097 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003098 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003099 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003100 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003101 }
3102
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003103 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003104 if (tx_seq_offset < 0)
3105 tx_seq_offset += 64;
3106
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003107 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003108 if (bt_cb(next_skb)->tx_seq == tx_seq)
3109 return -EINVAL;
3110
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003111 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003112 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003113 if (next_tx_seq_offset < 0)
3114 next_tx_seq_offset += 64;
3115
3116 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003117 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003118 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003119 }
3120
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003121 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003122 break;
3123
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003124 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003125
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003126 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003127
3128 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003129}
3130
Mat Martineau84084a32011-07-22 14:54:00 -07003131static void append_skb_frag(struct sk_buff *skb,
3132 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003133{
Mat Martineau84084a32011-07-22 14:54:00 -07003134 /* skb->len reflects data in skb as well as all fragments
3135 * skb->data_len reflects only data in fragments
3136 */
3137 if (!skb_has_frag_list(skb))
3138 skb_shinfo(skb)->frag_list = new_frag;
3139
3140 new_frag->next = NULL;
3141
3142 (*last_frag)->next = new_frag;
3143 *last_frag = new_frag;
3144
3145 skb->len += new_frag->len;
3146 skb->data_len += new_frag->len;
3147 skb->truesize += new_frag->truesize;
3148}
3149
3150static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
3151{
3152 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003153
3154 switch (control & L2CAP_CTRL_SAR) {
3155 case L2CAP_SDU_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003156 if (chan->sdu)
3157 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003158
Mat Martineau84084a32011-07-22 14:54:00 -07003159 err = chan->ops->recv(chan->data, skb);
3160 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003161
3162 case L2CAP_SDU_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003163 if (chan->sdu)
3164 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003165
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003166 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003167 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003168
Mat Martineau84084a32011-07-22 14:54:00 -07003169 if (chan->sdu_len > chan->imtu) {
3170 err = -EMSGSIZE;
3171 break;
3172 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003173
Mat Martineau84084a32011-07-22 14:54:00 -07003174 if (skb->len >= chan->sdu_len)
3175 break;
3176
3177 chan->sdu = skb;
3178 chan->sdu_last_frag = skb;
3179
3180 skb = NULL;
3181 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003182 break;
3183
3184 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003185 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003186 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003187
Mat Martineau84084a32011-07-22 14:54:00 -07003188 append_skb_frag(chan->sdu, skb,
3189 &chan->sdu_last_frag);
3190 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003191
Mat Martineau84084a32011-07-22 14:54:00 -07003192 if (chan->sdu->len >= chan->sdu_len)
3193 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003194
Mat Martineau84084a32011-07-22 14:54:00 -07003195 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003196 break;
3197
3198 case L2CAP_SDU_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003199 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003200 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003201
Mat Martineau84084a32011-07-22 14:54:00 -07003202 append_skb_frag(chan->sdu, skb,
3203 &chan->sdu_last_frag);
3204 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003205
Mat Martineau84084a32011-07-22 14:54:00 -07003206 if (chan->sdu->len != chan->sdu_len)
3207 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003208
Mat Martineau84084a32011-07-22 14:54:00 -07003209 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003210
Mat Martineau84084a32011-07-22 14:54:00 -07003211 if (!err) {
3212 /* Reassembly complete */
3213 chan->sdu = NULL;
3214 chan->sdu_last_frag = NULL;
3215 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003216 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003217 break;
3218 }
3219
Mat Martineau84084a32011-07-22 14:54:00 -07003220 if (err) {
3221 kfree_skb(skb);
3222 kfree_skb(chan->sdu);
3223 chan->sdu = NULL;
3224 chan->sdu_last_frag = NULL;
3225 chan->sdu_len = 0;
3226 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003227
Mat Martineau84084a32011-07-22 14:54:00 -07003228 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003229}
3230
Mat Martineau26f880d2011-07-07 09:39:01 -07003231static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003232{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003233 u16 control;
3234
Mat Martineau26f880d2011-07-07 09:39:01 -07003235 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003236
Mat Martineau26f880d2011-07-07 09:39:01 -07003237 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3238
3239 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3240 control |= L2CAP_SUPER_RCV_NOT_READY;
3241 l2cap_send_sframe(chan, control);
3242
3243 set_bit(CONN_RNR_SENT, &chan->conn_state);
3244
3245 __clear_ack_timer(chan);
3246}
3247
3248static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3249{
3250 u16 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003251
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003252 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003253 goto done;
3254
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003255 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003256 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003257 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003258 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003259
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003260 __clear_retrans_timer(chan);
3261 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003262
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003263 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003264
3265done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003266 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3267 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003268
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003269 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003270}
3271
Mat Martineaue3281402011-07-07 09:39:02 -07003272void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003273{
Mat Martineaue3281402011-07-07 09:39:02 -07003274 if (chan->mode == L2CAP_MODE_ERTM) {
3275 if (busy)
3276 l2cap_ertm_enter_local_busy(chan);
3277 else
3278 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003279 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003280}
3281
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003282static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003283{
3284 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003285 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003286
Mat Martineaue3281402011-07-07 09:39:02 -07003287 while ((skb = skb_peek(&chan->srej_q)) &&
3288 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3289 int err;
3290
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003291 if (bt_cb(skb)->tx_seq != tx_seq)
3292 break;
3293
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003294 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003295 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Mat Martineau84084a32011-07-22 14:54:00 -07003296 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003297
3298 if (err < 0) {
3299 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3300 break;
3301 }
3302
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003303 chan->buffer_seq_srej =
3304 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003305 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003306 }
3307}
3308
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003309static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003310{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003311 struct srej_list *l, *tmp;
3312 u16 control;
3313
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003314 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003315 if (l->tx_seq == tx_seq) {
3316 list_del(&l->list);
3317 kfree(l);
3318 return;
3319 }
3320 control = L2CAP_SUPER_SELECT_REJECT;
3321 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003322 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003323 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003324 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003325 }
3326}
3327
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003328static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003329{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003330 struct srej_list *new;
3331 u16 control;
3332
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003333 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003334 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003335 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003336 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003337
3338 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003339 new->tx_seq = chan->expected_tx_seq;
3340 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003341 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003342 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003343 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003344}
3345
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003346static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003347{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003348 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003349 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003350 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003351 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003352 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003353 int err = 0;
3354
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003355 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3356 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003357
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003358 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003359 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003360 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003361 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003362 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003363 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003364 }
3365
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003366 chan->expected_ack_seq = req_seq;
3367 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003368
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003369 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003370 if (tx_seq_offset < 0)
3371 tx_seq_offset += 64;
3372
3373 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003374 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003375 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003376 goto drop;
3377 }
3378
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003379 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003380 goto drop;
3381
Mat Martineau02f1b642011-06-29 14:35:19 -07003382 if (tx_seq == chan->expected_tx_seq)
3383 goto expected;
3384
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003385 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003386 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003387
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003388 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003389 struct srej_list, list);
3390 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003391 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003392 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003393
3394 list_del(&first->list);
3395 kfree(first);
3396
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003397 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003398 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003399 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003400 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003401 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003402 }
3403 } else {
3404 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003405
3406 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003407 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003408 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003409
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003410 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003411 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003412 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003413 return 0;
3414 }
3415 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003416 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003417 }
3418 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003419 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003420 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003421 if (expected_tx_seq_offset < 0)
3422 expected_tx_seq_offset += 64;
3423
3424 /* duplicated tx_seq */
3425 if (tx_seq_offset < expected_tx_seq_offset)
3426 goto drop;
3427
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003428 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003429
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003430 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003431
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003432 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003433 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003434
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003435 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003436 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003437
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003438 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003439
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003440 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003441
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003442 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003443 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003444 return 0;
3445
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003446expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003447 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003448
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003449 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003450 bt_cb(skb)->tx_seq = tx_seq;
3451 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003452 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003453 return 0;
3454 }
3455
Mat Martineau84084a32011-07-22 14:54:00 -07003456 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Mat Martineaufadd1922011-07-07 09:39:03 -07003457 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Mat Martineaue3281402011-07-07 09:39:02 -07003458 if (err < 0) {
3459 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3460 return err;
3461 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003462
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003463 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003464 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003465 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003466 }
3467
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003468 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003469
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003470 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3471 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003472 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003473
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003474 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003475
3476drop:
3477 kfree_skb(skb);
3478 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003479}
3480
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003481static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003482{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003483 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003484 rx_control);
3485
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003486 chan->expected_ack_seq = __get_reqseq(rx_control);
3487 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003488
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003489 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003490 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3491 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3492 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003493 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003494 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003495
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003496 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003497 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003498 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003499 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003500 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003501
3502 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003503 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003504
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003505 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003506 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003507
3508 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003509 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003510 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003511 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003512
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003513 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3514 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003515 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003516 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003517 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003518 }
3519}
3520
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003521static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003522{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003523 u8 tx_seq = __get_reqseq(rx_control);
3524
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003525 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003526
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003527 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003528
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003529 chan->expected_ack_seq = tx_seq;
3530 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003531
3532 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003533 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003534 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003535 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003536 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003537
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003538 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3539 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003540 }
3541}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003542static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003543{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003544 u8 tx_seq = __get_reqseq(rx_control);
3545
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003546 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003547
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003548 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003549
3550 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003551 chan->expected_ack_seq = tx_seq;
3552 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003553
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003554 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003555 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003556
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003557 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003558
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003559 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003560 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003561 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003562 }
3563 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003564 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003565 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003566 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003567 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003568 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003569 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003570 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003571 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003572 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003573 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003574 }
3575 }
3576}
3577
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003578static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003579{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003580 u8 tx_seq = __get_reqseq(rx_control);
3581
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003582 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003583
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003584 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003585 chan->expected_ack_seq = tx_seq;
3586 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003587
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003588 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003589 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003590
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003591 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003592 __clear_retrans_timer(chan);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003593 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003594 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003595 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003596 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003597
3598 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003599 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003600 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003601 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003602}
3603
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003604static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003605{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003606 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003607
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003608 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003609 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003610 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003611 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003612 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003613 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003614 }
3615
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003616 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3617 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003618 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003619 break;
3620
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003621 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003622 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003623 break;
3624
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003625 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003626 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003627 break;
3628
3629 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003630 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003631 break;
3632 }
3633
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003634 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003635 return 0;
3636}
3637
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003638static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3639{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003640 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003641 u16 control;
3642 u8 req_seq;
3643 int len, next_tx_seq_offset, req_seq_offset;
3644
3645 control = get_unaligned_le16(skb->data);
3646 skb_pull(skb, 2);
3647 len = skb->len;
3648
3649 /*
3650 * We can just drop the corrupted I-frame here.
3651 * Receiver will miss it and start proper recovery
3652 * procedures and ask retransmission.
3653 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003654 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003655 goto drop;
3656
3657 if (__is_sar_start(control) && __is_iframe(control))
3658 len -= 2;
3659
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003660 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003661 len -= 2;
3662
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003663 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003664 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003665 goto drop;
3666 }
3667
3668 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003669 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003670 if (req_seq_offset < 0)
3671 req_seq_offset += 64;
3672
3673 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003674 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003675 if (next_tx_seq_offset < 0)
3676 next_tx_seq_offset += 64;
3677
3678 /* check for invalid req-seq */
3679 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003680 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003681 goto drop;
3682 }
3683
3684 if (__is_iframe(control)) {
3685 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003686 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003687 goto drop;
3688 }
3689
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003690 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003691 } else {
3692 if (len != 0) {
3693 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003694 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003695 goto drop;
3696 }
3697
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003698 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003699 }
3700
3701 return 0;
3702
3703drop:
3704 kfree_skb(skb);
3705 return 0;
3706}
3707
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3709{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003710 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003711 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003712 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003713 u8 tx_seq;
3714 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003716 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003717 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718 BT_DBG("unknown cid 0x%4.4x", cid);
3719 goto drop;
3720 }
3721
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003722 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003723
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003724 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003726 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727 goto drop;
3728
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003729 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003730 case L2CAP_MODE_BASIC:
3731 /* If socket recv buffers overflows we drop data here
3732 * which is *bad* because L2CAP has to be reliable.
3733 * But we don't have any other choice. L2CAP doesn't
3734 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003736 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003737 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003738
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003739 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003740 goto done;
3741 break;
3742
3743 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003744 if (!sock_owned_by_user(sk)) {
3745 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003746 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003747 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003748 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003749 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003750
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003751 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003752
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003753 case L2CAP_MODE_STREAMING:
3754 control = get_unaligned_le16(skb->data);
3755 skb_pull(skb, 2);
3756 len = skb->len;
3757
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003758 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003759 goto drop;
3760
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003761 if (__is_sar_start(control))
3762 len -= 2;
3763
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003764 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003765 len -= 2;
3766
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003767 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003768 goto drop;
3769
3770 tx_seq = __get_txseq(control);
3771
Mat Martineau84084a32011-07-22 14:54:00 -07003772 if (chan->expected_tx_seq != tx_seq) {
3773 /* Frame(s) missing - must discard partial SDU */
3774 kfree_skb(chan->sdu);
3775 chan->sdu = NULL;
3776 chan->sdu_last_frag = NULL;
3777 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003778
Mat Martineau84084a32011-07-22 14:54:00 -07003779 /* TODO: Notify userland of missing data */
3780 }
3781
3782 chan->expected_tx_seq = (tx_seq + 1) % 64;
3783
3784 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
3785 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003786
3787 goto done;
3788
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003789 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003790 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003791 break;
3792 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003793
3794drop:
3795 kfree_skb(skb);
3796
3797done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003798 if (sk)
3799 bh_unlock_sock(sk);
3800
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801 return 0;
3802}
3803
Al Viro8e036fc2007-07-29 00:16:36 -07003804static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003805{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003806 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003807 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003809 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3810 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003811 goto drop;
3812
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003813 sk = chan->sk;
3814
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003815 bh_lock_sock(sk);
3816
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817 BT_DBG("sk %p, len %d", sk, skb->len);
3818
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003819 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003820 goto drop;
3821
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003822 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003823 goto drop;
3824
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003825 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826 goto done;
3827
3828drop:
3829 kfree_skb(skb);
3830
3831done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003832 if (sk)
3833 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003834 return 0;
3835}
3836
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003837static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3838{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003839 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003840 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003841
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003842 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3843 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003844 goto drop;
3845
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003846 sk = chan->sk;
3847
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003848 bh_lock_sock(sk);
3849
3850 BT_DBG("sk %p, len %d", sk, skb->len);
3851
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003852 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003853 goto drop;
3854
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003855 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003856 goto drop;
3857
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003858 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003859 goto done;
3860
3861drop:
3862 kfree_skb(skb);
3863
3864done:
3865 if (sk)
3866 bh_unlock_sock(sk);
3867 return 0;
3868}
3869
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3871{
3872 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003873 u16 cid, len;
3874 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875
3876 skb_pull(skb, L2CAP_HDR_SIZE);
3877 cid = __le16_to_cpu(lh->cid);
3878 len = __le16_to_cpu(lh->len);
3879
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003880 if (len != skb->len) {
3881 kfree_skb(skb);
3882 return;
3883 }
3884
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3886
3887 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003888 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003889 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890 l2cap_sig_channel(conn, skb);
3891 break;
3892
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003893 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003894 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895 skb_pull(skb, 2);
3896 l2cap_conless_channel(conn, psm, skb);
3897 break;
3898
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003899 case L2CAP_CID_LE_DATA:
3900 l2cap_att_channel(conn, cid, skb);
3901 break;
3902
Anderson Brigliab501d6a2011-06-07 18:46:31 -03003903 case L2CAP_CID_SMP:
3904 if (smp_sig_channel(conn, skb))
3905 l2cap_conn_del(conn->hcon, EACCES);
3906 break;
3907
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908 default:
3909 l2cap_data_channel(conn, cid, skb);
3910 break;
3911 }
3912}
3913
3914/* ---- L2CAP interface with lower layer (HCI) ---- */
3915
3916static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3917{
3918 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003919 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920
3921 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003922 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923
3924 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3925
3926 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003927 read_lock(&chan_list_lock);
3928 list_for_each_entry(c, &chan_list, global_l) {
3929 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003930
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003931 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932 continue;
3933
3934 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003935 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003936 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003937 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003939 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3940 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003941 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003942 lm2 |= HCI_LM_MASTER;
3943 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003945 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946
3947 return exact ? lm1 : lm2;
3948}
3949
3950static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3951{
Marcel Holtmann01394182006-07-03 10:02:46 +02003952 struct l2cap_conn *conn;
3953
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3955
Ville Tervoacd7d372011-02-10 22:38:49 -03003956 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003957 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958
3959 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960 conn = l2cap_conn_add(hcon, status);
3961 if (conn)
3962 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003963 } else
Joe Perchese1750722011-06-29 18:18:29 -07003964 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965
3966 return 0;
3967}
3968
Marcel Holtmann2950f212009-02-12 14:02:50 +01003969static int l2cap_disconn_ind(struct hci_conn *hcon)
3970{
3971 struct l2cap_conn *conn = hcon->l2cap_data;
3972
3973 BT_DBG("hcon %p", hcon);
3974
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03003975 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01003976 return 0x13;
3977
3978 return conn->disc_reason;
3979}
3980
3981static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982{
3983 BT_DBG("hcon %p reason %d", hcon, reason);
3984
Ville Tervoacd7d372011-02-10 22:38:49 -03003985 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003986 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987
Joe Perchese1750722011-06-29 18:18:29 -07003988 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003989
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990 return 0;
3991}
3992
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003993static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003994{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03003995 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003996 return;
3997
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003998 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003999 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004000 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02004001 __set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004002 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004003 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004004 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004005 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004006 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004007 }
4008}
4009
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004010static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004012 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004013 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014
Marcel Holtmann01394182006-07-03 10:02:46 +02004015 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004017
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018 BT_DBG("conn %p", conn);
4019
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004020 if (hcon->type == LE_LINK) {
4021 smp_distribute_keys(conn, 0);
4022 del_timer(&conn->security_timer);
4023 }
4024
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004025 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004027 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004028 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004029
Linus Torvalds1da177e2005-04-16 15:20:36 -07004030 bh_lock_sock(sk);
4031
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004032 BT_DBG("chan->scid %d", chan->scid);
4033
4034 if (chan->scid == L2CAP_CID_LE_DATA) {
4035 if (!status && encrypt) {
4036 chan->sec_level = hcon->sec_level;
4037 l2cap_chan_ready(sk);
4038 }
4039
4040 bh_unlock_sock(sk);
4041 continue;
4042 }
4043
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004044 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004045 bh_unlock_sock(sk);
4046 continue;
4047 }
4048
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004049 if (!status && (chan->state == BT_CONNECTED ||
4050 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004051 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004052 bh_unlock_sock(sk);
4053 continue;
4054 }
4055
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004056 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004057 if (!status) {
4058 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004059 req.scid = cpu_to_le16(chan->scid);
4060 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004061
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004062 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004063 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004064
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004065 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004066 L2CAP_CONN_REQ, sizeof(req), &req);
4067 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004068 __clear_chan_timer(chan);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02004069 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004070 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004071 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004072 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004073 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004074
4075 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004076 if (bt_sk(sk)->defer_setup) {
4077 struct sock *parent = bt_sk(sk)->parent;
4078 res = L2CAP_CR_PEND;
4079 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004080 if (parent)
4081 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004082 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004083 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004084 res = L2CAP_CR_SUCCESS;
4085 stat = L2CAP_CS_NO_INFO;
4086 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004087 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004088 l2cap_state_change(chan, BT_DISCONN);
Andrzej Kaczmarekf3f668b2011-11-07 17:19:04 -02004089 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004090 res = L2CAP_CR_SEC_BLOCK;
4091 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004092 }
4093
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004094 rsp.scid = cpu_to_le16(chan->dcid);
4095 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004096 rsp.result = cpu_to_le16(res);
4097 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004098 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4099 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100 }
4101
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102 bh_unlock_sock(sk);
4103 }
4104
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004105 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004106
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107 return 0;
4108}
4109
4110static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4111{
4112 struct l2cap_conn *conn = hcon->l2cap_data;
4113
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004114 if (!conn)
4115 conn = l2cap_conn_add(hcon, 0);
4116
4117 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118 goto drop;
4119
4120 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4121
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004122 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004124 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004125 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126 int len;
4127
4128 if (conn->rx_len) {
4129 BT_ERR("Unexpected start frame (len %d)", skb->len);
4130 kfree_skb(conn->rx_skb);
4131 conn->rx_skb = NULL;
4132 conn->rx_len = 0;
4133 l2cap_conn_unreliable(conn, ECOMM);
4134 }
4135
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004136 /* Start fragment always begin with Basic L2CAP header */
4137 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138 BT_ERR("Frame is too short (len %d)", skb->len);
4139 l2cap_conn_unreliable(conn, ECOMM);
4140 goto drop;
4141 }
4142
4143 hdr = (struct l2cap_hdr *) skb->data;
4144 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004145 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146
4147 if (len == skb->len) {
4148 /* Complete frame received */
4149 l2cap_recv_frame(conn, skb);
4150 return 0;
4151 }
4152
4153 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4154
4155 if (skb->len > len) {
4156 BT_ERR("Frame is too long (len %d, expected len %d)",
4157 skb->len, len);
4158 l2cap_conn_unreliable(conn, ECOMM);
4159 goto drop;
4160 }
4161
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004162 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004163
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004164 if (chan && chan->sk) {
4165 struct sock *sk = chan->sk;
4166
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004167 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004168 BT_ERR("Frame exceeding recv MTU (len %d, "
4169 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004170 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004171 bh_unlock_sock(sk);
4172 l2cap_conn_unreliable(conn, ECOMM);
4173 goto drop;
4174 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004175 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004176 }
4177
Linus Torvalds1da177e2005-04-16 15:20:36 -07004178 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004179 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4180 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004181 goto drop;
4182
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004183 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004184 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185 conn->rx_len = len - skb->len;
4186 } else {
4187 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4188
4189 if (!conn->rx_len) {
4190 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4191 l2cap_conn_unreliable(conn, ECOMM);
4192 goto drop;
4193 }
4194
4195 if (skb->len > conn->rx_len) {
4196 BT_ERR("Fragment is too long (len %d, expected %d)",
4197 skb->len, conn->rx_len);
4198 kfree_skb(conn->rx_skb);
4199 conn->rx_skb = NULL;
4200 conn->rx_len = 0;
4201 l2cap_conn_unreliable(conn, ECOMM);
4202 goto drop;
4203 }
4204
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004205 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004206 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207 conn->rx_len -= skb->len;
4208
4209 if (!conn->rx_len) {
4210 /* Complete frame received */
4211 l2cap_recv_frame(conn, conn->rx_skb);
4212 conn->rx_skb = NULL;
4213 }
4214 }
4215
4216drop:
4217 kfree_skb(skb);
4218 return 0;
4219}
4220
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004221static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004223 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004224
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004225 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004227 list_for_each_entry(c, &chan_list, global_l) {
4228 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004230 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 +01004231 batostr(&bt_sk(sk)->src),
4232 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004233 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004234 c->scid, c->dcid, c->imtu, c->omtu,
4235 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004236}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004237
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004238 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004239
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004240 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004241}
4242
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004243static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4244{
4245 return single_open(file, l2cap_debugfs_show, inode->i_private);
4246}
4247
4248static const struct file_operations l2cap_debugfs_fops = {
4249 .open = l2cap_debugfs_open,
4250 .read = seq_read,
4251 .llseek = seq_lseek,
4252 .release = single_release,
4253};
4254
4255static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257static struct hci_proto l2cap_hci_proto = {
4258 .name = "L2CAP",
4259 .id = HCI_PROTO_L2CAP,
4260 .connect_ind = l2cap_connect_ind,
4261 .connect_cfm = l2cap_connect_cfm,
4262 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004263 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004264 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265 .recv_acldata = l2cap_recv_acldata
4266};
4267
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004268int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269{
4270 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004271
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004272 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273 if (err < 0)
4274 return err;
4275
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276 err = hci_register_proto(&l2cap_hci_proto);
4277 if (err < 0) {
4278 BT_ERR("L2CAP protocol registration failed");
4279 bt_sock_unregister(BTPROTO_L2CAP);
4280 goto error;
4281 }
4282
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004283 if (bt_debugfs) {
4284 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4285 bt_debugfs, NULL, &l2cap_debugfs_fops);
4286 if (!l2cap_debugfs)
4287 BT_ERR("Failed to create L2CAP debug file");
4288 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289
Linus Torvalds1da177e2005-04-16 15:20:36 -07004290 return 0;
4291
4292error:
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004293 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004294 return err;
4295}
4296
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004297void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004298{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004299 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4302 BT_ERR("L2CAP protocol unregistration failed");
4303
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004304 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305}
4306
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004307module_param(disable_ertm, bool, 0644);
4308MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");