blob: 52c791ed038dd943f624e84e78315570fd29497d [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. Padovan710f9b02011-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 */
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300254 __set_chan_timer(chan, HZ / 5);
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);
766 parent->sk_data_ready(parent, 0);
767
768 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300769 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100770 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
771 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
772 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200773 } else {
774 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
775 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
776 }
777
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300778 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
779 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300780
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300781 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300782 rsp.result != L2CAP_CR_SUCCESS) {
783 bh_unlock_sock(sk);
784 continue;
785 }
786
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300787 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300788 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300789 l2cap_build_conf_req(chan, buf), buf);
790 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200791 }
792
793 bh_unlock_sock(sk);
794 }
795
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300796 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200797}
798
Ville Tervob62f3282011-02-10 22:38:50 -0300799/* Find socket with cid and source bdaddr.
800 * Returns closest match, locked.
801 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300802static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300803{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300804 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300805
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300806 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300807
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300808 list_for_each_entry(c, &chan_list, global_l) {
809 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300810
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300811 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300812 continue;
813
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300814 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300815 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300816 if (!bacmp(&bt_sk(sk)->src, src)) {
817 read_unlock(&chan_list_lock);
818 return c;
819 }
Ville Tervob62f3282011-02-10 22:38:50 -0300820
821 /* Closest match */
822 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300823 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300824 }
825 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300826
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300827 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300828
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300829 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300830}
831
832static void l2cap_le_conn_ready(struct l2cap_conn *conn)
833{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300834 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300835 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300836
837 BT_DBG("");
838
839 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300840 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300841 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300842 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300843 return;
844
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300845 parent = pchan->sk;
846
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300847 bh_lock_sock(parent);
848
Ville Tervob62f3282011-02-10 22:38:50 -0300849 /* Check for backlog size */
850 if (sk_acceptq_is_full(parent)) {
851 BT_DBG("backlog full %d", parent->sk_ack_backlog);
852 goto clean;
853 }
854
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300855 chan = pchan->ops->new_connection(pchan->data);
856 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300857 goto clean;
858
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300859 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300860
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300861 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300862
863 hci_conn_hold(conn->hcon);
864
Ville Tervob62f3282011-02-10 22:38:50 -0300865 bacpy(&bt_sk(sk)->src, conn->src);
866 bacpy(&bt_sk(sk)->dst, conn->dst);
867
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300868 bt_accept_enqueue(parent, sk);
869
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300870 __l2cap_chan_add(conn, chan);
871
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300872 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300873
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300874 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300875 parent->sk_data_ready(parent, 0);
876
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300877 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300878
879clean:
880 bh_unlock_sock(parent);
881}
882
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300883static void l2cap_chan_ready(struct sock *sk)
884{
885 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
886 struct sock *parent = bt_sk(sk)->parent;
887
888 BT_DBG("sk %p, parent %p", sk, parent);
889
890 chan->conf_state = 0;
891 __clear_chan_timer(chan);
892
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300893 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300894 sk->sk_state_change(sk);
895
896 if (parent)
897 parent->sk_data_ready(parent, 0);
898}
899
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200900static void l2cap_conn_ready(struct l2cap_conn *conn)
901{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300902 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200903
904 BT_DBG("conn %p", conn);
905
Ville Tervob62f3282011-02-10 22:38:50 -0300906 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
907 l2cap_le_conn_ready(conn);
908
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300909 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200910
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300911 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300912 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300913
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200914 bh_lock_sock(sk);
915
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300916 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300917 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300918 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300919
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300920 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300921 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300922 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200923 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300924
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300925 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300926 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200927
928 bh_unlock_sock(sk);
929 }
930
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300931 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200932}
933
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200934/* Notify sockets that we cannot guaranty reliability anymore */
935static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
936{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300937 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200938
939 BT_DBG("conn %p", conn);
940
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300941 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200942
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300943 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300944 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300945
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300946 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200947 sk->sk_err = err;
948 }
949
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300950 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200951}
952
953static void l2cap_info_timeout(unsigned long arg)
954{
955 struct l2cap_conn *conn = (void *) arg;
956
Marcel Holtmann984947d2009-02-06 23:35:19 +0100957 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100958 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100959
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200960 l2cap_conn_start(conn);
961}
962
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300963static void l2cap_conn_del(struct hci_conn *hcon, int err)
964{
965 struct l2cap_conn *conn = hcon->l2cap_data;
966 struct l2cap_chan *chan, *l;
967 struct sock *sk;
968
969 if (!conn)
970 return;
971
972 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
973
974 kfree_skb(conn->rx_skb);
975
976 /* Kill channels */
977 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
978 sk = chan->sk;
979 bh_lock_sock(sk);
980 l2cap_chan_del(chan, err);
981 bh_unlock_sock(sk);
982 chan->ops->close(chan->data);
983 }
984
985 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
986 del_timer_sync(&conn->info_timer);
987
988 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
989 del_timer(&conn->security_timer);
990
991 hcon->l2cap_data = NULL;
992 kfree(conn);
993}
994
995static void security_timeout(unsigned long arg)
996{
997 struct l2cap_conn *conn = (void *) arg;
998
999 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1000}
1001
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1003{
Marcel Holtmann01394182006-07-03 10:02:46 +02001004 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005
Marcel Holtmann01394182006-07-03 10:02:46 +02001006 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 return conn;
1008
Marcel Holtmann01394182006-07-03 10:02:46 +02001009 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1010 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012
1013 hcon->l2cap_data = conn;
1014 conn->hcon = hcon;
1015
Marcel Holtmann01394182006-07-03 10:02:46 +02001016 BT_DBG("hcon %p conn %p", hcon, conn);
1017
Ville Tervoacd7d372011-02-10 22:38:49 -03001018 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1019 conn->mtu = hcon->hdev->le_mtu;
1020 else
1021 conn->mtu = hcon->hdev->acl_mtu;
1022
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 conn->src = &hcon->hdev->bdaddr;
1024 conn->dst = &hcon->dst;
1025
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001026 conn->feat_mask = 0;
1027
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001029 rwlock_init(&conn->chan_lock);
1030
1031 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001033 if (hcon->type == LE_LINK)
1034 setup_timer(&conn->security_timer, security_timeout,
1035 (unsigned long) conn);
1036 else
Ville Tervob62f3282011-02-10 22:38:50 -03001037 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +00001038 (unsigned long) conn);
1039
Marcel Holtmann2950f212009-02-12 14:02:50 +01001040 conn->disc_reason = 0x13;
1041
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 return conn;
1043}
1044
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001045static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001047 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001048 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001049 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050}
1051
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053
1054/* Find socket with psm and source bdaddr.
1055 * Returns closest match.
1056 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001057static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001059 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001061 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001062
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001063 list_for_each_entry(c, &chan_list, global_l) {
1064 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001065
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001066 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 continue;
1068
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001069 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001071 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001072 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001073 return c;
1074 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075
1076 /* Closest match */
1077 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001078 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 }
1080 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001082 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001083
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001084 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085}
1086
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001087int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001089 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 bdaddr_t *src = &bt_sk(sk)->src;
1091 bdaddr_t *dst = &bt_sk(sk)->dst;
1092 struct l2cap_conn *conn;
1093 struct hci_conn *hcon;
1094 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001095 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001096 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001098 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001099 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001101 hdev = hci_get_route(dst, src);
1102 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 return -EHOSTUNREACH;
1104
1105 hci_dev_lock_bh(hdev);
1106
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001107 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001108
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001109 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001110 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001111 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001112 else
1113 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001114 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001115
Ville Tervo30e76272011-02-22 16:10:53 -03001116 if (IS_ERR(hcon)) {
1117 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001119 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120
1121 conn = l2cap_conn_add(hcon, 0);
1122 if (!conn) {
1123 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001124 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 goto done;
1126 }
1127
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 /* Update source addr of the socket */
1129 bacpy(src, conn->src);
1130
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001131 l2cap_chan_add(conn, chan);
1132
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001133 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001134 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
1136 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001137 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001138 __clear_chan_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001139 if (l2cap_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001140 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001141 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001142 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 }
1144
Ville Tervo30e76272011-02-22 16:10:53 -03001145 err = 0;
1146
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147done:
1148 hci_dev_unlock_bh(hdev);
1149 hci_dev_put(hdev);
1150 return err;
1151}
1152
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001153int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001154{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001155 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001156 DECLARE_WAITQUEUE(wait, current);
1157 int err = 0;
1158 int timeo = HZ/5;
1159
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001160 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001161 while ((chan->unacked_frames > 0 && chan->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001162 set_current_state(TASK_INTERRUPTIBLE);
1163
1164 if (!timeo)
1165 timeo = HZ/5;
1166
1167 if (signal_pending(current)) {
1168 err = sock_intr_errno(timeo);
1169 break;
1170 }
1171
1172 release_sock(sk);
1173 timeo = schedule_timeout(timeo);
1174 lock_sock(sk);
1175
1176 err = sock_error(sk);
1177 if (err)
1178 break;
1179 }
1180 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001181 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001182 return err;
1183}
1184
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001185static void l2cap_monitor_timeout(unsigned long arg)
1186{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001187 struct l2cap_chan *chan = (void *) arg;
1188 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001189
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001190 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001191
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001192 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001193 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001194 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001195 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001196 return;
1197 }
1198
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001199 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001200 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001201
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001202 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001203 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001204}
1205
1206static void l2cap_retrans_timeout(unsigned long arg)
1207{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001208 struct l2cap_chan *chan = (void *) arg;
1209 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001210
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001211 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001212
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001213 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001214 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001215 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001216
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001217 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001218
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001219 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001220 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001221}
1222
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001223static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001224{
1225 struct sk_buff *skb;
1226
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001227 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001228 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001229 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001230 break;
1231
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001232 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001233 kfree_skb(skb);
1234
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001235 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001236 }
1237
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001238 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001239 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001240}
1241
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001242void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001243{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001244 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001245 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001246
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001247 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001248
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001249 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001250 flags = ACL_START_NO_FLUSH;
1251 else
1252 flags = ACL_START;
1253
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -07001254 bt_cb(skb)->force_active = chan->force_active;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001255 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001256}
1257
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001258void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001259{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001260 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001261 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001262
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001263 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001264 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001265 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001266 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001267
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001268 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001269 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1270 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001271 }
1272
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001273 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001274
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001275 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001276 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001277}
1278
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001279static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001280{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001281 struct sk_buff *skb, *tx_skb;
1282 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001283
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001284 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001285 if (!skb)
1286 return;
1287
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001288 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001289 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001290 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001291
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001292 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001293 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001294
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001295 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001296
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001297 if (chan->remote_max_tx &&
1298 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001299 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001300 return;
1301 }
1302
1303 tx_skb = skb_clone(skb, GFP_ATOMIC);
1304 bt_cb(skb)->retries++;
1305 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001306 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001307
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001308 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001309 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001310
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001311 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001312 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001313
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001314 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1315
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001316 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001317 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1318 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1319 }
1320
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001321 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001322}
1323
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001324int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001325{
1326 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001327 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001328 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001329
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001330 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001331 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001332
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001333 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001334
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001335 if (chan->remote_max_tx &&
1336 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001337 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001338 break;
1339 }
1340
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001341 tx_skb = skb_clone(skb, GFP_ATOMIC);
1342
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001343 bt_cb(skb)->retries++;
1344
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001345 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001346 control &= L2CAP_CTRL_SAR;
1347
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001348 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001349 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001350
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001351 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1352 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001353 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1354
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001355
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001356 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001357 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1358 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1359 }
1360
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001361 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001362
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001363 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001364
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001365 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1366 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001367
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301368 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001369 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301370
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001371 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001372
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001373 if (skb_queue_is_last(&chan->tx_q, skb))
1374 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001375 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001376 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001377
1378 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001379 }
1380
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001381 return nsent;
1382}
1383
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001384static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001385{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001386 int ret;
1387
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001388 if (!skb_queue_empty(&chan->tx_q))
1389 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001390
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001391 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001392 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001393 return ret;
1394}
1395
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001396static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001397{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001398 u16 control = 0;
1399
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001400 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001401
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001402 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001403 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001404 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001405 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001406 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001407 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001408
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001409 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001410 return;
1411
1412 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001413 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001414}
1415
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001416static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001417{
1418 struct srej_list *tail;
1419 u16 control;
1420
1421 control = L2CAP_SUPER_SELECT_REJECT;
1422 control |= L2CAP_CTRL_FINAL;
1423
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001424 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001425 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1426
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001427 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001428}
1429
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001430static 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 -07001431{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001432 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001433 struct sk_buff **frag;
1434 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001436 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001437 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438
1439 sent += count;
1440 len -= count;
1441
1442 /* Continuation fragments (no L2CAP header) */
1443 frag = &skb_shinfo(skb)->frag_list;
1444 while (len) {
1445 count = min_t(unsigned int, conn->mtu, len);
1446
1447 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1448 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001449 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001450 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1451 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452
1453 sent += count;
1454 len -= count;
1455
1456 frag = &(*frag)->next;
1457 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458
1459 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001460}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001462struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001463{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001464 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001465 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001466 struct sk_buff *skb;
1467 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1468 struct l2cap_hdr *lh;
1469
1470 BT_DBG("sk %p len %d", sk, (int)len);
1471
1472 count = min_t(unsigned int, (conn->mtu - hlen), len);
1473 skb = bt_skb_send_alloc(sk, count + hlen,
1474 msg->msg_flags & MSG_DONTWAIT, &err);
1475 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001476 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001477
1478 /* Create L2CAP header */
1479 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001480 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001481 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001482 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001483
1484 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1485 if (unlikely(err < 0)) {
1486 kfree_skb(skb);
1487 return ERR_PTR(err);
1488 }
1489 return skb;
1490}
1491
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001492struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001493{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001494 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001495 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001496 struct sk_buff *skb;
1497 int err, count, hlen = L2CAP_HDR_SIZE;
1498 struct l2cap_hdr *lh;
1499
1500 BT_DBG("sk %p len %d", sk, (int)len);
1501
1502 count = min_t(unsigned int, (conn->mtu - hlen), len);
1503 skb = bt_skb_send_alloc(sk, count + hlen,
1504 msg->msg_flags & MSG_DONTWAIT, &err);
1505 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001506 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001507
1508 /* Create L2CAP header */
1509 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001510 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001511 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1512
1513 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1514 if (unlikely(err < 0)) {
1515 kfree_skb(skb);
1516 return ERR_PTR(err);
1517 }
1518 return skb;
1519}
1520
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001521struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001522{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001523 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001524 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001525 struct sk_buff *skb;
1526 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1527 struct l2cap_hdr *lh;
1528
1529 BT_DBG("sk %p len %d", sk, (int)len);
1530
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001531 if (!conn)
1532 return ERR_PTR(-ENOTCONN);
1533
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001534 if (sdulen)
1535 hlen += 2;
1536
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001537 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001538 hlen += 2;
1539
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001540 count = min_t(unsigned int, (conn->mtu - hlen), len);
1541 skb = bt_skb_send_alloc(sk, count + hlen,
1542 msg->msg_flags & MSG_DONTWAIT, &err);
1543 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001544 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001545
1546 /* Create L2CAP header */
1547 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001548 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001549 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1550 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001551 if (sdulen)
1552 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001553
1554 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1555 if (unlikely(err < 0)) {
1556 kfree_skb(skb);
1557 return ERR_PTR(err);
1558 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001559
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001560 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001561 put_unaligned_le16(0, skb_put(skb, 2));
1562
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001563 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001564 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565}
1566
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001567int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001568{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001569 struct sk_buff *skb;
1570 struct sk_buff_head sar_queue;
1571 u16 control;
1572 size_t size = 0;
1573
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001574 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001575 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001576 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001577 if (IS_ERR(skb))
1578 return PTR_ERR(skb);
1579
1580 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001581 len -= chan->remote_mps;
1582 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001583
1584 while (len > 0) {
1585 size_t buflen;
1586
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001587 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001588 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001589 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001590 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001591 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001592 buflen = len;
1593 }
1594
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001595 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001596 if (IS_ERR(skb)) {
1597 skb_queue_purge(&sar_queue);
1598 return PTR_ERR(skb);
1599 }
1600
1601 __skb_queue_tail(&sar_queue, skb);
1602 len -= buflen;
1603 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001604 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001605 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1606 if (chan->tx_send_head == NULL)
1607 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001608
1609 return size;
1610}
1611
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001612int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1613{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001614 struct sk_buff *skb;
1615 u16 control;
1616 int err;
1617
1618 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001619 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001620 skb = l2cap_create_connless_pdu(chan, msg, len);
1621 if (IS_ERR(skb))
1622 return PTR_ERR(skb);
1623
1624 l2cap_do_send(chan, skb);
1625 return len;
1626 }
1627
1628 switch (chan->mode) {
1629 case L2CAP_MODE_BASIC:
1630 /* Check outgoing MTU */
1631 if (len > chan->omtu)
1632 return -EMSGSIZE;
1633
1634 /* Create a basic PDU */
1635 skb = l2cap_create_basic_pdu(chan, msg, len);
1636 if (IS_ERR(skb))
1637 return PTR_ERR(skb);
1638
1639 l2cap_do_send(chan, skb);
1640 err = len;
1641 break;
1642
1643 case L2CAP_MODE_ERTM:
1644 case L2CAP_MODE_STREAMING:
1645 /* Entire SDU fits into one PDU */
1646 if (len <= chan->remote_mps) {
1647 control = L2CAP_SDU_UNSEGMENTED;
1648 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1649 0);
1650 if (IS_ERR(skb))
1651 return PTR_ERR(skb);
1652
1653 __skb_queue_tail(&chan->tx_q, skb);
1654
1655 if (chan->tx_send_head == NULL)
1656 chan->tx_send_head = skb;
1657
1658 } else {
1659 /* Segment SDU into multiples PDUs */
1660 err = l2cap_sar_segment_sdu(chan, msg, len);
1661 if (err < 0)
1662 return err;
1663 }
1664
1665 if (chan->mode == L2CAP_MODE_STREAMING) {
1666 l2cap_streaming_send(chan);
1667 err = len;
1668 break;
1669 }
1670
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001671 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1672 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001673 err = len;
1674 break;
1675 }
1676
1677 err = l2cap_ertm_send(chan);
1678 if (err >= 0)
1679 err = len;
1680
1681 break;
1682
1683 default:
1684 BT_DBG("bad state %1.1x", chan->mode);
1685 err = -EBADFD;
1686 }
1687
1688 return err;
1689}
1690
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691/* Copy frame to all raw sockets on that connection */
1692static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1693{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001695 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696
1697 BT_DBG("conn %p", conn);
1698
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001699 read_lock(&conn->chan_lock);
1700 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001701 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001702 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 continue;
1704
1705 /* Don't send frame to the socket it came from */
1706 if (skb->sk == sk)
1707 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001708 nskb = skb_clone(skb, GFP_ATOMIC);
1709 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 continue;
1711
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001712 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 kfree_skb(nskb);
1714 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001715 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716}
1717
1718/* ---- L2CAP signalling commands ---- */
1719static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1720 u8 code, u8 ident, u16 dlen, void *data)
1721{
1722 struct sk_buff *skb, **frag;
1723 struct l2cap_cmd_hdr *cmd;
1724 struct l2cap_hdr *lh;
1725 int len, count;
1726
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001727 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1728 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729
1730 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1731 count = min_t(unsigned int, conn->mtu, len);
1732
1733 skb = bt_skb_alloc(count, GFP_ATOMIC);
1734 if (!skb)
1735 return NULL;
1736
1737 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001738 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001739
1740 if (conn->hcon->type == LE_LINK)
1741 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1742 else
1743 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744
1745 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1746 cmd->code = code;
1747 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001748 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749
1750 if (dlen) {
1751 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1752 memcpy(skb_put(skb, count), data, count);
1753 data += count;
1754 }
1755
1756 len -= skb->len;
1757
1758 /* Continuation fragments (no L2CAP header) */
1759 frag = &skb_shinfo(skb)->frag_list;
1760 while (len) {
1761 count = min_t(unsigned int, conn->mtu, len);
1762
1763 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1764 if (!*frag)
1765 goto fail;
1766
1767 memcpy(skb_put(*frag, count), data, count);
1768
1769 len -= count;
1770 data += count;
1771
1772 frag = &(*frag)->next;
1773 }
1774
1775 return skb;
1776
1777fail:
1778 kfree_skb(skb);
1779 return NULL;
1780}
1781
1782static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1783{
1784 struct l2cap_conf_opt *opt = *ptr;
1785 int len;
1786
1787 len = L2CAP_CONF_OPT_SIZE + opt->len;
1788 *ptr += len;
1789
1790 *type = opt->type;
1791 *olen = opt->len;
1792
1793 switch (opt->len) {
1794 case 1:
1795 *val = *((u8 *) opt->val);
1796 break;
1797
1798 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001799 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 break;
1801
1802 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001803 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 break;
1805
1806 default:
1807 *val = (unsigned long) opt->val;
1808 break;
1809 }
1810
1811 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1812 return len;
1813}
1814
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1816{
1817 struct l2cap_conf_opt *opt = *ptr;
1818
1819 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1820
1821 opt->type = type;
1822 opt->len = len;
1823
1824 switch (len) {
1825 case 1:
1826 *((u8 *) opt->val) = val;
1827 break;
1828
1829 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001830 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 break;
1832
1833 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001834 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835 break;
1836
1837 default:
1838 memcpy(opt->val, (void *) val, len);
1839 break;
1840 }
1841
1842 *ptr += L2CAP_CONF_OPT_SIZE + len;
1843}
1844
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001845static void l2cap_ack_timeout(unsigned long arg)
1846{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001847 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001848
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001849 bh_lock_sock(chan->sk);
1850 l2cap_send_ack(chan);
1851 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001852}
1853
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001854static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001855{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001856 struct sock *sk = chan->sk;
1857
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001858 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001859 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001860 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001861 chan->num_acked = 0;
1862 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001863
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001864 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1865 (unsigned long) chan);
1866 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1867 (unsigned long) chan);
1868 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001869
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001870 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001871
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001872 INIT_LIST_HEAD(&chan->srej_l);
1873
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001874
1875 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001876}
1877
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001878static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1879{
1880 switch (mode) {
1881 case L2CAP_MODE_STREAMING:
1882 case L2CAP_MODE_ERTM:
1883 if (l2cap_mode_supported(mode, remote_feat_mask))
1884 return mode;
1885 /* fall through */
1886 default:
1887 return L2CAP_MODE_BASIC;
1888 }
1889}
1890
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001891static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001894 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 void *ptr = req->data;
1896
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001897 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001899 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001900 goto done;
1901
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001902 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001903 case L2CAP_MODE_STREAMING:
1904 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001905 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001906 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001907
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001908 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001909 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001910 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001911 break;
1912 }
1913
1914done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001915 if (chan->imtu != L2CAP_DEFAULT_MTU)
1916 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001917
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001918 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001919 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001920 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1921 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001922 break;
1923
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001924 rfc.mode = L2CAP_MODE_BASIC;
1925 rfc.txwin_size = 0;
1926 rfc.max_transmit = 0;
1927 rfc.retrans_timeout = 0;
1928 rfc.monitor_timeout = 0;
1929 rfc.max_pdu_size = 0;
1930
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001931 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1932 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001933 break;
1934
1935 case L2CAP_MODE_ERTM:
1936 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001937 rfc.txwin_size = chan->tx_win;
1938 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001939 rfc.retrans_timeout = 0;
1940 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001941 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001942 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1943 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001944
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001945 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1946 (unsigned long) &rfc);
1947
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001948 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001949 break;
1950
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001951 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001952 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001953 chan->fcs = L2CAP_FCS_NONE;
1954 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001955 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001956 break;
1957
1958 case L2CAP_MODE_STREAMING:
1959 rfc.mode = L2CAP_MODE_STREAMING;
1960 rfc.txwin_size = 0;
1961 rfc.max_transmit = 0;
1962 rfc.retrans_timeout = 0;
1963 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001964 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001965 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1966 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001967
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001968 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1969 (unsigned long) &rfc);
1970
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001971 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001972 break;
1973
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001974 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001975 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001976 chan->fcs = L2CAP_FCS_NONE;
1977 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001978 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001979 break;
1980 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001982 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001983 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984
1985 return ptr - data;
1986}
1987
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001988static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001990 struct l2cap_conf_rsp *rsp = data;
1991 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001992 void *req = chan->conf_req;
1993 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001994 int type, hint, olen;
1995 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001996 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001997 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001998 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002000 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002001
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002002 while (len >= L2CAP_CONF_OPT_SIZE) {
2003 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002005 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002006 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002007
2008 switch (type) {
2009 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002010 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002011 break;
2012
2013 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002014 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002015 break;
2016
2017 case L2CAP_CONF_QOS:
2018 break;
2019
Marcel Holtmann6464f352007-10-20 13:39:51 +02002020 case L2CAP_CONF_RFC:
2021 if (olen == sizeof(rfc))
2022 memcpy(&rfc, (void *) val, olen);
2023 break;
2024
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002025 case L2CAP_CONF_FCS:
2026 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002027 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002028
2029 break;
2030
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002031 default:
2032 if (hint)
2033 break;
2034
2035 result = L2CAP_CONF_UNKNOWN;
2036 *((u8 *) ptr++) = type;
2037 break;
2038 }
2039 }
2040
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002041 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002042 goto done;
2043
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002044 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002045 case L2CAP_MODE_STREAMING:
2046 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002047 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002048 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002049 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002050 break;
2051 }
2052
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002053 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002054 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002055
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002056 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002057 }
2058
2059done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002060 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002061 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002062 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002063
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002064 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002065 return -ECONNREFUSED;
2066
2067 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2068 sizeof(rfc), (unsigned long) &rfc);
2069 }
2070
2071
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002072 if (result == L2CAP_CONF_SUCCESS) {
2073 /* Configure output options and let the other side know
2074 * which ones we don't like. */
2075
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002076 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2077 result = L2CAP_CONF_UNACCEPT;
2078 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002079 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002080 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002081 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002082 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002083
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002084 switch (rfc.mode) {
2085 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002086 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002087 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002088 break;
2089
2090 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002091 chan->remote_tx_win = rfc.txwin_size;
2092 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002093
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002094 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2095 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002096
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002097 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002098
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002099 rfc.retrans_timeout =
2100 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2101 rfc.monitor_timeout =
2102 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002103
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002104 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002105
2106 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2107 sizeof(rfc), (unsigned long) &rfc);
2108
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002109 break;
2110
2111 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002112 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2113 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002114
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002115 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002116
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002117 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002118
2119 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2120 sizeof(rfc), (unsigned long) &rfc);
2121
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002122 break;
2123
2124 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002125 result = L2CAP_CONF_UNACCEPT;
2126
2127 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002128 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002129 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002130
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002131 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002132 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002133 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002134 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002135 rsp->result = cpu_to_le16(result);
2136 rsp->flags = cpu_to_le16(0x0000);
2137
2138 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139}
2140
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002141static 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 -03002142{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002143 struct l2cap_conf_req *req = data;
2144 void *ptr = req->data;
2145 int type, olen;
2146 unsigned long val;
2147 struct l2cap_conf_rfc rfc;
2148
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002149 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002150
2151 while (len >= L2CAP_CONF_OPT_SIZE) {
2152 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2153
2154 switch (type) {
2155 case L2CAP_CONF_MTU:
2156 if (val < L2CAP_DEFAULT_MIN_MTU) {
2157 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002158 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002159 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002160 chan->imtu = val;
2161 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002162 break;
2163
2164 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002165 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002166 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002167 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002168 break;
2169
2170 case L2CAP_CONF_RFC:
2171 if (olen == sizeof(rfc))
2172 memcpy(&rfc, (void *)val, olen);
2173
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002174 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002175 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002176 return -ECONNREFUSED;
2177
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002178 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002179
2180 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2181 sizeof(rfc), (unsigned long) &rfc);
2182 break;
2183 }
2184 }
2185
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002186 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002187 return -ECONNREFUSED;
2188
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002189 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002190
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002191 if (*result == L2CAP_CONF_SUCCESS) {
2192 switch (rfc.mode) {
2193 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002194 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2195 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2196 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002197 break;
2198 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002199 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002200 }
2201 }
2202
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002203 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002204 req->flags = cpu_to_le16(0x0000);
2205
2206 return ptr - data;
2207}
2208
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002209static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210{
2211 struct l2cap_conf_rsp *rsp = data;
2212 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002214 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002216 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002217 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002218 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219
2220 return ptr - data;
2221}
2222
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002223void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002224{
2225 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002226 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002227 u8 buf[128];
2228
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002229 rsp.scid = cpu_to_le16(chan->dcid);
2230 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002231 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2232 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2233 l2cap_send_cmd(conn, chan->ident,
2234 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2235
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002236 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002237 return;
2238
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002239 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2240 l2cap_build_conf_req(chan, buf), buf);
2241 chan->num_conf_req++;
2242}
2243
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002244static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002245{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002246 int type, olen;
2247 unsigned long val;
2248 struct l2cap_conf_rfc rfc;
2249
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002250 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002251
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002252 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002253 return;
2254
2255 while (len >= L2CAP_CONF_OPT_SIZE) {
2256 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2257
2258 switch (type) {
2259 case L2CAP_CONF_RFC:
2260 if (olen == sizeof(rfc))
2261 memcpy(&rfc, (void *)val, olen);
2262 goto done;
2263 }
2264 }
2265
2266done:
2267 switch (rfc.mode) {
2268 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002269 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2270 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2271 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002272 break;
2273 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002274 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002275 }
2276}
2277
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002278static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2279{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002280 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002281
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002282 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002283 return 0;
2284
2285 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2286 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002287 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002288
2289 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002290 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002291
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002292 l2cap_conn_start(conn);
2293 }
2294
2295 return 0;
2296}
2297
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2299{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2301 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002302 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002303 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002304 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305
2306 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002307 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308
2309 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2310
2311 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002312 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2313 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 result = L2CAP_CR_BAD_PSM;
2315 goto sendresp;
2316 }
2317
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002318 parent = pchan->sk;
2319
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002320 bh_lock_sock(parent);
2321
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002322 /* Check if the ACL is secure enough (if not SDP) */
2323 if (psm != cpu_to_le16(0x0001) &&
2324 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002325 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002326 result = L2CAP_CR_SEC_BLOCK;
2327 goto response;
2328 }
2329
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330 result = L2CAP_CR_NO_MEM;
2331
2332 /* Check for backlog size */
2333 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002334 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 goto response;
2336 }
2337
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002338 chan = pchan->ops->new_connection(pchan->data);
2339 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 goto response;
2341
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002342 sk = chan->sk;
2343
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002344 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345
2346 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002347 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2348 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002350 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 goto response;
2352 }
2353
2354 hci_conn_hold(conn->hcon);
2355
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 bacpy(&bt_sk(sk)->src, conn->src);
2357 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002358 chan->psm = psm;
2359 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002361 bt_accept_enqueue(parent, sk);
2362
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002363 __l2cap_chan_add(conn, chan);
2364
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002365 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002367 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002369 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370
Marcel Holtmann984947d2009-02-06 23:35:19 +01002371 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002372 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002373 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002374 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002375 result = L2CAP_CR_PEND;
2376 status = L2CAP_CS_AUTHOR_PEND;
2377 parent->sk_data_ready(parent, 0);
2378 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002379 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002380 result = L2CAP_CR_SUCCESS;
2381 status = L2CAP_CS_NO_INFO;
2382 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002383 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002384 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002385 result = L2CAP_CR_PEND;
2386 status = L2CAP_CS_AUTHEN_PEND;
2387 }
2388 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002389 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002390 result = L2CAP_CR_PEND;
2391 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392 }
2393
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002394 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395
2396response:
2397 bh_unlock_sock(parent);
2398
2399sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002400 rsp.scid = cpu_to_le16(scid);
2401 rsp.dcid = cpu_to_le16(dcid);
2402 rsp.result = cpu_to_le16(result);
2403 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002405
2406 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2407 struct l2cap_info_req info;
2408 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2409
2410 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2411 conn->info_ident = l2cap_get_ident(conn);
2412
2413 mod_timer(&conn->info_timer, jiffies +
2414 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2415
2416 l2cap_send_cmd(conn, conn->info_ident,
2417 L2CAP_INFO_REQ, sizeof(info), &info);
2418 }
2419
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002420 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002421 result == L2CAP_CR_SUCCESS) {
2422 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002423 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002424 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002425 l2cap_build_conf_req(chan, buf), buf);
2426 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002427 }
2428
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 return 0;
2430}
2431
2432static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2433{
2434 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2435 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002436 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437 struct sock *sk;
2438 u8 req[128];
2439
2440 scid = __le16_to_cpu(rsp->scid);
2441 dcid = __le16_to_cpu(rsp->dcid);
2442 result = __le16_to_cpu(rsp->result);
2443 status = __le16_to_cpu(rsp->status);
2444
2445 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2446
2447 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002448 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002449 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002450 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002452 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002453 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002454 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 }
2456
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002457 sk = chan->sk;
2458
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 switch (result) {
2460 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002461 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002462 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002463 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002464 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002465
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002466 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002467 break;
2468
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002470 l2cap_build_conf_req(chan, req), req);
2471 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472 break;
2473
2474 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002475 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476 break;
2477
2478 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002479 /* don't delete l2cap channel if sk is owned by user */
2480 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002481 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002482 __clear_chan_timer(chan);
2483 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002484 break;
2485 }
2486
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002487 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 break;
2489 }
2490
2491 bh_unlock_sock(sk);
2492 return 0;
2493}
2494
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002495static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002496{
2497 /* FCS is enabled only in ERTM or streaming mode, if one or both
2498 * sides request it.
2499 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002500 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002501 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002502 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002503 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002504}
2505
Al Viro88219a02007-07-29 00:17:25 -07002506static 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 -07002507{
2508 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2509 u16 dcid, flags;
2510 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002511 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002513 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514
2515 dcid = __le16_to_cpu(req->dcid);
2516 flags = __le16_to_cpu(req->flags);
2517
2518 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2519
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002520 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002521 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522 return -ENOENT;
2523
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002524 sk = chan->sk;
2525
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002526 if (chan->state != BT_CONFIG) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002527 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002528
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002529 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2530 rej.scid = cpu_to_le16(chan->scid);
2531 rej.dcid = cpu_to_le16(chan->dcid);
2532
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002533 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2534 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002535 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002536 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002537
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002538 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002539 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002540 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002541 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002542 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002543 L2CAP_CONF_REJECT, flags), rsp);
2544 goto unlock;
2545 }
2546
2547 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002548 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2549 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550
2551 if (flags & 0x0001) {
2552 /* Incomplete config. Send empty response. */
2553 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002554 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002555 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556 goto unlock;
2557 }
2558
2559 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002560 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002561 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002562 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002564 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002566 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002567 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002568
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002569 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002570 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002571
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002572 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002573 goto unlock;
2574
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002575 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002576 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002577
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002578 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002579
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002580 chan->next_tx_seq = 0;
2581 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002582 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002583 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002584 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002585
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002587 goto unlock;
2588 }
2589
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002590 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002591 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002593 l2cap_build_conf_req(chan, buf), buf);
2594 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595 }
2596
2597unlock:
2598 bh_unlock_sock(sk);
2599 return 0;
2600}
2601
2602static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2603{
2604 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2605 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002606 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002608 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609
2610 scid = __le16_to_cpu(rsp->scid);
2611 flags = __le16_to_cpu(rsp->flags);
2612 result = __le16_to_cpu(rsp->result);
2613
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002614 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2615 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002617 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002618 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619 return 0;
2620
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002621 sk = chan->sk;
2622
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623 switch (result) {
2624 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002625 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626 break;
2627
2628 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002629 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002630 char req[64];
2631
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002632 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002633 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002634 goto done;
2635 }
2636
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002637 /* throw out any old stored conf requests */
2638 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002639 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2640 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002641 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002642 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002643 goto done;
2644 }
2645
2646 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2647 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002648 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002649 if (result != L2CAP_CONF_SUCCESS)
2650 goto done;
2651 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652 }
2653
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002654 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002655 sk->sk_err = ECONNRESET;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002656 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002657 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658 goto done;
2659 }
2660
2661 if (flags & 0x01)
2662 goto done;
2663
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002664 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002666 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002667 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002668
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002669 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002670 chan->next_tx_seq = 0;
2671 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002672 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002673 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002674 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002675
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676 l2cap_chan_ready(sk);
2677 }
2678
2679done:
2680 bh_unlock_sock(sk);
2681 return 0;
2682}
2683
2684static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2685{
2686 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2687 struct l2cap_disconn_rsp rsp;
2688 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002689 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690 struct sock *sk;
2691
2692 scid = __le16_to_cpu(req->scid);
2693 dcid = __le16_to_cpu(req->dcid);
2694
2695 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2696
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002697 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002698 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699 return 0;
2700
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002701 sk = chan->sk;
2702
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002703 rsp.dcid = cpu_to_le16(chan->scid);
2704 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2706
2707 sk->sk_shutdown = SHUTDOWN_MASK;
2708
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002709 /* don't delete l2cap channel if sk is owned by user */
2710 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002711 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002712 __clear_chan_timer(chan);
2713 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002714 bh_unlock_sock(sk);
2715 return 0;
2716 }
2717
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002718 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719 bh_unlock_sock(sk);
2720
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002721 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 return 0;
2723}
2724
2725static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2726{
2727 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2728 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002729 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 struct sock *sk;
2731
2732 scid = __le16_to_cpu(rsp->scid);
2733 dcid = __le16_to_cpu(rsp->dcid);
2734
2735 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2736
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002737 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002738 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 return 0;
2740
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002741 sk = chan->sk;
2742
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002743 /* don't delete l2cap channel if sk is owned by user */
2744 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002745 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002746 __clear_chan_timer(chan);
2747 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002748 bh_unlock_sock(sk);
2749 return 0;
2750 }
2751
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002752 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753 bh_unlock_sock(sk);
2754
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002755 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756 return 0;
2757}
2758
2759static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2760{
2761 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 u16 type;
2763
2764 type = __le16_to_cpu(req->type);
2765
2766 BT_DBG("type 0x%4.4x", type);
2767
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002768 if (type == L2CAP_IT_FEAT_MASK) {
2769 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002770 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002771 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2772 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2773 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002774 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002775 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2776 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002777 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002778 l2cap_send_cmd(conn, cmd->ident,
2779 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002780 } else if (type == L2CAP_IT_FIXED_CHAN) {
2781 u8 buf[12];
2782 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2783 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2784 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2785 memcpy(buf + 4, l2cap_fixed_chan, 8);
2786 l2cap_send_cmd(conn, cmd->ident,
2787 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002788 } else {
2789 struct l2cap_info_rsp rsp;
2790 rsp.type = cpu_to_le16(type);
2791 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2792 l2cap_send_cmd(conn, cmd->ident,
2793 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2794 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795
2796 return 0;
2797}
2798
2799static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2800{
2801 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2802 u16 type, result;
2803
2804 type = __le16_to_cpu(rsp->type);
2805 result = __le16_to_cpu(rsp->result);
2806
2807 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2808
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002809 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2810 if (cmd->ident != conn->info_ident ||
2811 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2812 return 0;
2813
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002814 del_timer(&conn->info_timer);
2815
Ville Tervoadb08ed2010-08-04 09:43:33 +03002816 if (result != L2CAP_IR_SUCCESS) {
2817 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2818 conn->info_ident = 0;
2819
2820 l2cap_conn_start(conn);
2821
2822 return 0;
2823 }
2824
Marcel Holtmann984947d2009-02-06 23:35:19 +01002825 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002826 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002827
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002828 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002829 struct l2cap_info_req req;
2830 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2831
2832 conn->info_ident = l2cap_get_ident(conn);
2833
2834 l2cap_send_cmd(conn, conn->info_ident,
2835 L2CAP_INFO_REQ, sizeof(req), &req);
2836 } else {
2837 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2838 conn->info_ident = 0;
2839
2840 l2cap_conn_start(conn);
2841 }
2842 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002843 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002844 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002845
2846 l2cap_conn_start(conn);
2847 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002848
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849 return 0;
2850}
2851
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002852static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002853 u16 to_multiplier)
2854{
2855 u16 max_latency;
2856
2857 if (min > max || min < 6 || max > 3200)
2858 return -EINVAL;
2859
2860 if (to_multiplier < 10 || to_multiplier > 3200)
2861 return -EINVAL;
2862
2863 if (max >= to_multiplier * 8)
2864 return -EINVAL;
2865
2866 max_latency = (to_multiplier * 8 / max) - 1;
2867 if (latency > 499 || latency > max_latency)
2868 return -EINVAL;
2869
2870 return 0;
2871}
2872
2873static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2874 struct l2cap_cmd_hdr *cmd, u8 *data)
2875{
2876 struct hci_conn *hcon = conn->hcon;
2877 struct l2cap_conn_param_update_req *req;
2878 struct l2cap_conn_param_update_rsp rsp;
2879 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002880 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002881
2882 if (!(hcon->link_mode & HCI_LM_MASTER))
2883 return -EINVAL;
2884
2885 cmd_len = __le16_to_cpu(cmd->len);
2886 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2887 return -EPROTO;
2888
2889 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002890 min = __le16_to_cpu(req->min);
2891 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002892 latency = __le16_to_cpu(req->latency);
2893 to_multiplier = __le16_to_cpu(req->to_multiplier);
2894
2895 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2896 min, max, latency, to_multiplier);
2897
2898 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002899
2900 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2901 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002902 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2903 else
2904 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2905
2906 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2907 sizeof(rsp), &rsp);
2908
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002909 if (!err)
2910 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2911
Claudio Takahaside731152011-02-11 19:28:55 -02002912 return 0;
2913}
2914
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002915static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2916 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2917{
2918 int err = 0;
2919
2920 switch (cmd->code) {
2921 case L2CAP_COMMAND_REJ:
2922 l2cap_command_rej(conn, cmd, data);
2923 break;
2924
2925 case L2CAP_CONN_REQ:
2926 err = l2cap_connect_req(conn, cmd, data);
2927 break;
2928
2929 case L2CAP_CONN_RSP:
2930 err = l2cap_connect_rsp(conn, cmd, data);
2931 break;
2932
2933 case L2CAP_CONF_REQ:
2934 err = l2cap_config_req(conn, cmd, cmd_len, data);
2935 break;
2936
2937 case L2CAP_CONF_RSP:
2938 err = l2cap_config_rsp(conn, cmd, data);
2939 break;
2940
2941 case L2CAP_DISCONN_REQ:
2942 err = l2cap_disconnect_req(conn, cmd, data);
2943 break;
2944
2945 case L2CAP_DISCONN_RSP:
2946 err = l2cap_disconnect_rsp(conn, cmd, data);
2947 break;
2948
2949 case L2CAP_ECHO_REQ:
2950 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2951 break;
2952
2953 case L2CAP_ECHO_RSP:
2954 break;
2955
2956 case L2CAP_INFO_REQ:
2957 err = l2cap_information_req(conn, cmd, data);
2958 break;
2959
2960 case L2CAP_INFO_RSP:
2961 err = l2cap_information_rsp(conn, cmd, data);
2962 break;
2963
2964 default:
2965 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2966 err = -EINVAL;
2967 break;
2968 }
2969
2970 return err;
2971}
2972
2973static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2974 struct l2cap_cmd_hdr *cmd, u8 *data)
2975{
2976 switch (cmd->code) {
2977 case L2CAP_COMMAND_REJ:
2978 return 0;
2979
2980 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002981 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002982
2983 case L2CAP_CONN_PARAM_UPDATE_RSP:
2984 return 0;
2985
2986 default:
2987 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2988 return -EINVAL;
2989 }
2990}
2991
2992static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2993 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994{
2995 u8 *data = skb->data;
2996 int len = skb->len;
2997 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002998 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999
3000 l2cap_raw_recv(conn, skb);
3001
3002 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003003 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3005 data += L2CAP_CMD_HDR_SIZE;
3006 len -= L2CAP_CMD_HDR_SIZE;
3007
Al Viro88219a02007-07-29 00:17:25 -07003008 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009
Al Viro88219a02007-07-29 00:17:25 -07003010 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 -07003011
Al Viro88219a02007-07-29 00:17:25 -07003012 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013 BT_DBG("corrupted command");
3014 break;
3015 }
3016
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003017 if (conn->hcon->type == LE_LINK)
3018 err = l2cap_le_sig_cmd(conn, &cmd, data);
3019 else
3020 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021
3022 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003023 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003024
3025 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026
3027 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003028 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3030 }
3031
Al Viro88219a02007-07-29 00:17:25 -07003032 data += cmd_len;
3033 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034 }
3035
3036 kfree_skb(skb);
3037}
3038
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003039static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003040{
3041 u16 our_fcs, rcv_fcs;
3042 int hdr_size = L2CAP_HDR_SIZE + 2;
3043
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003044 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003045 skb_trim(skb, skb->len - 2);
3046 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3047 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3048
3049 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003050 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003051 }
3052 return 0;
3053}
3054
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003055static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003056{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003057 u16 control = 0;
3058
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003059 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003060
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003061 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003062
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003063 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003064 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003065 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003066 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003067 }
3068
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003069 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003070 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003071
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003072 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003073
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003074 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003075 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003076 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003077 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003078 }
3079}
3080
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003081static 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 -03003082{
3083 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003084 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003085
3086 bt_cb(skb)->tx_seq = tx_seq;
3087 bt_cb(skb)->sar = sar;
3088
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003089 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003090 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003091 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003092 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003093 }
3094
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003095 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003096 if (tx_seq_offset < 0)
3097 tx_seq_offset += 64;
3098
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003099 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003100 if (bt_cb(next_skb)->tx_seq == tx_seq)
3101 return -EINVAL;
3102
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003103 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003104 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003105 if (next_tx_seq_offset < 0)
3106 next_tx_seq_offset += 64;
3107
3108 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003109 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003110 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003111 }
3112
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003113 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003114 break;
3115
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003116 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003117
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003118 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003119
3120 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003121}
3122
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003123static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003124{
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003125 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003126 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003127
3128 switch (control & L2CAP_CTRL_SAR) {
3129 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003130 if (test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003131 goto drop;
3132
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003133 return chan->ops->recv(chan->data, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003134
3135 case L2CAP_SDU_START:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003136 if (test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003137 goto drop;
3138
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003139 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003140
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003141 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003142 goto disconnect;
3143
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003144 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3145 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003146 return -ENOMEM;
3147
3148 /* pull sdu_len bytes only after alloc, because of Local Busy
3149 * condition we have to be sure that this will be executed
3150 * only once, i.e., when alloc does not fail */
3151 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003152
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003153 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003154
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003155 set_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003156 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003157 break;
3158
3159 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003160 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003161 goto disconnect;
3162
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003163 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003164 goto disconnect;
3165
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003166 chan->partial_sdu_len += skb->len;
3167 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003168 goto drop;
3169
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003170 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003171
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003172 break;
3173
3174 case L2CAP_SDU_END:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003175 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003176 goto disconnect;
3177
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003178 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003179 goto disconnect;
3180
Mat Martineaufadd1922011-07-07 09:39:03 -07003181 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003182
Mat Martineaufadd1922011-07-07 09:39:03 -07003183 if (chan->partial_sdu_len > chan->imtu)
3184 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003185
Mat Martineaufadd1922011-07-07 09:39:03 -07003186 if (chan->partial_sdu_len != chan->sdu_len)
3187 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003188
Mat Martineaufadd1922011-07-07 09:39:03 -07003189 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003190
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003191 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003192 if (!_skb) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003193 return -ENOMEM;
3194 }
3195
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003196 err = chan->ops->recv(chan->data, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003197 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003198 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003199 return err;
3200 }
3201
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003202 clear_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003203
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003204 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003205 break;
3206 }
3207
3208 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003209 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003210
3211drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003212 kfree_skb(chan->sdu);
3213 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003214
3215disconnect:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003216 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003217 kfree_skb(skb);
3218 return 0;
3219}
3220
Mat Martineau26f880d2011-07-07 09:39:01 -07003221static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003222{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003223 u16 control;
3224
Mat Martineau26f880d2011-07-07 09:39:01 -07003225 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003226
Mat Martineau26f880d2011-07-07 09:39:01 -07003227 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3228
3229 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3230 control |= L2CAP_SUPER_RCV_NOT_READY;
3231 l2cap_send_sframe(chan, control);
3232
3233 set_bit(CONN_RNR_SENT, &chan->conn_state);
3234
3235 __clear_ack_timer(chan);
3236}
3237
3238static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3239{
3240 u16 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003241
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003242 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003243 goto done;
3244
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003245 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003246 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003247 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003248 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003249
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003250 __clear_retrans_timer(chan);
3251 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003252
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003253 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003254
3255done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003256 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3257 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003258
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003259 BT_DBG("chan %p, Exit local busy", chan);
Mat Martineau26f880d2011-07-07 09:39:01 -07003260}
3261
Mat Martineaue3281402011-07-07 09:39:02 -07003262void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
3263{
3264 if (chan->mode == L2CAP_MODE_ERTM) {
3265 if (busy)
3266 l2cap_ertm_enter_local_busy(chan);
3267 else
3268 l2cap_ertm_exit_local_busy(chan);
3269 }
3270}
3271
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003272static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003273{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003274 struct sk_buff *_skb;
3275 int err = -EINVAL;
3276
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003277 /*
3278 * TODO: We have to notify the userland if some data is lost with the
3279 * Streaming Mode.
3280 */
3281
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003282 switch (control & L2CAP_CTRL_SAR) {
3283 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003284 if (test_bit(CONN_SAR_SDU, &chan->conn_state)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003285 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003286 break;
3287 }
3288
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003289 err = chan->ops->recv(chan->data, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003290 if (!err)
3291 return 0;
3292
3293 break;
3294
3295 case L2CAP_SDU_START:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003296 if (test_bit(CONN_SAR_SDU, &chan->conn_state)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003297 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003298 break;
3299 }
3300
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003301 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003302 skb_pull(skb, 2);
3303
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003304 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003305 err = -EMSGSIZE;
3306 break;
3307 }
3308
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003309 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3310 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003311 err = -ENOMEM;
3312 break;
3313 }
3314
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003315 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003316
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003317 set_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003318 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003319 err = 0;
3320 break;
3321
3322 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003323 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003324 break;
3325
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003326 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003327
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003328 chan->partial_sdu_len += skb->len;
3329 if (chan->partial_sdu_len > chan->sdu_len)
3330 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003331 else
3332 err = 0;
3333
3334 break;
3335
3336 case L2CAP_SDU_END:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003337 if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003338 break;
3339
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003340 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003341
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003342 clear_bit(CONN_SAR_SDU, &chan->conn_state);
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003343 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003344
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003345 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003346 goto drop;
3347
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003348 if (chan->partial_sdu_len == chan->sdu_len) {
3349 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003350 err = chan->ops->recv(chan->data, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003351 if (err < 0)
3352 kfree_skb(_skb);
3353 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003354 err = 0;
3355
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003356drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003357 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003358 break;
3359 }
3360
3361 kfree_skb(skb);
3362 return err;
3363}
3364
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003365static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003366{
3367 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003368 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003369
Mat Martineaue3281402011-07-07 09:39:02 -07003370 while ((skb = skb_peek(&chan->srej_q)) &&
3371 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3372 int err;
3373
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003374 if (bt_cb(skb)->tx_seq != tx_seq)
3375 break;
3376
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003377 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003378 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Mat Martineaue3281402011-07-07 09:39:02 -07003379 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
3380
3381 if (err < 0) {
3382 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3383 break;
3384 }
3385
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003386 chan->buffer_seq_srej =
3387 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003388 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003389 }
3390}
3391
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003392static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003393{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003394 struct srej_list *l, *tmp;
3395 u16 control;
3396
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003397 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003398 if (l->tx_seq == tx_seq) {
3399 list_del(&l->list);
3400 kfree(l);
3401 return;
3402 }
3403 control = L2CAP_SUPER_SELECT_REJECT;
3404 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003405 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003406 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003407 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003408 }
3409}
3410
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003411static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003412{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003413 struct srej_list *new;
3414 u16 control;
3415
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003416 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003417 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003418 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003419 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003420
3421 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003422 new->tx_seq = chan->expected_tx_seq;
3423 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003424 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003425 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003426 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003427}
3428
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003429static 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 -03003430{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003431 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003432 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003433 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003434 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003435 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003436 int err = 0;
3437
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003438 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3439 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003440
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003441 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003442 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003443 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003444 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003445 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003446 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003447 }
3448
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003449 chan->expected_ack_seq = req_seq;
3450 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003451
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003452 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003453 if (tx_seq_offset < 0)
3454 tx_seq_offset += 64;
3455
3456 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003457 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003458 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003459 goto drop;
3460 }
3461
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003462 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003463 goto drop;
3464
Mat Martineau02f1b642011-06-29 14:35:19 -07003465 if (tx_seq == chan->expected_tx_seq)
3466 goto expected;
3467
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003468 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003469 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003470
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003471 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003472 struct srej_list, list);
3473 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003474 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003475 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003476
3477 list_del(&first->list);
3478 kfree(first);
3479
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003480 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003481 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003482 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003483 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003484 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003485 }
3486 } else {
3487 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003488
3489 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003490 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003491 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003492
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003493 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003494 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003495 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003496 return 0;
3497 }
3498 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003499 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003500 }
3501 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003502 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003503 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003504 if (expected_tx_seq_offset < 0)
3505 expected_tx_seq_offset += 64;
3506
3507 /* duplicated tx_seq */
3508 if (tx_seq_offset < expected_tx_seq_offset)
3509 goto drop;
3510
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003511 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003512
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003513 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003514
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003515 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003516 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003517
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003518 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003519 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003520
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003521 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003522
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003523 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003524
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003525 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003526 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003527 return 0;
3528
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003529expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003530 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003531
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003532 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003533 bt_cb(skb)->tx_seq = tx_seq;
3534 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003535 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003536 return 0;
3537 }
3538
Mat Martineaufadd1922011-07-07 09:39:03 -07003539 err = l2cap_ertm_reassembly_sdu(chan, skb, rx_control);
3540 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Mat Martineaue3281402011-07-07 09:39:02 -07003541 if (err < 0) {
3542 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3543 return err;
3544 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003545
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003546 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003547 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003548 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003549 }
3550
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003551 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003552
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003553 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3554 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003555 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003556
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003557 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003558
3559drop:
3560 kfree_skb(skb);
3561 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003562}
3563
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003564static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003565{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003566 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003567 rx_control);
3568
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003569 chan->expected_ack_seq = __get_reqseq(rx_control);
3570 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003571
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003572 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003573 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3574 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3575 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003576 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003577 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003578
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003579 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003580 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003581 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003582 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003583 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003584
3585 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003586 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003587
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003588 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003589 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003590
3591 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003592 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003593 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003594 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003595
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003596 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3597 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003598 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003599 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003600 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003601 }
3602}
3603
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003604static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003605{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003606 u8 tx_seq = __get_reqseq(rx_control);
3607
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003608 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003609
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003610 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003611
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003612 chan->expected_ack_seq = tx_seq;
3613 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003614
3615 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003616 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003617 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003618 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003619 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003620
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003621 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3622 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003623 }
3624}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003625static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003626{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003627 u8 tx_seq = __get_reqseq(rx_control);
3628
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003629 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003630
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003631 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003632
3633 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003634 chan->expected_ack_seq = tx_seq;
3635 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003636
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003637 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003638 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003639
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003640 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003641
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003642 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003643 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003644 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003645 }
3646 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003647 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003648 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003649 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003650 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003651 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003652 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003653 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003654 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003655 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003656 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003657 }
3658 }
3659}
3660
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003661static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003662{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003663 u8 tx_seq = __get_reqseq(rx_control);
3664
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003665 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003666
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003667 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003668 chan->expected_ack_seq = tx_seq;
3669 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003670
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003671 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003672 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003673
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003674 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003675 __clear_retrans_timer(chan);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003676 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003677 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003678 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003679 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003680
3681 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003682 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003683 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003684 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003685}
3686
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003687static 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 -03003688{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003689 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003690
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003691 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003692 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003693 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003694 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003695 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003696 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003697 }
3698
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003699 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3700 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003701 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003702 break;
3703
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003704 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003705 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003706 break;
3707
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003708 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003709 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003710 break;
3711
3712 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003713 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003714 break;
3715 }
3716
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003717 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003718 return 0;
3719}
3720
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003721static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3722{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003723 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003724 u16 control;
3725 u8 req_seq;
3726 int len, next_tx_seq_offset, req_seq_offset;
3727
3728 control = get_unaligned_le16(skb->data);
3729 skb_pull(skb, 2);
3730 len = skb->len;
3731
3732 /*
3733 * We can just drop the corrupted I-frame here.
3734 * Receiver will miss it and start proper recovery
3735 * procedures and ask retransmission.
3736 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003737 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003738 goto drop;
3739
3740 if (__is_sar_start(control) && __is_iframe(control))
3741 len -= 2;
3742
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003743 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003744 len -= 2;
3745
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003746 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003747 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003748 goto drop;
3749 }
3750
3751 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003752 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003753 if (req_seq_offset < 0)
3754 req_seq_offset += 64;
3755
3756 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003757 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003758 if (next_tx_seq_offset < 0)
3759 next_tx_seq_offset += 64;
3760
3761 /* check for invalid req-seq */
3762 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003763 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003764 goto drop;
3765 }
3766
3767 if (__is_iframe(control)) {
3768 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003769 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003770 goto drop;
3771 }
3772
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003773 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003774 } else {
3775 if (len != 0) {
3776 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003777 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003778 goto drop;
3779 }
3780
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003781 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003782 }
3783
3784 return 0;
3785
3786drop:
3787 kfree_skb(skb);
3788 return 0;
3789}
3790
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3792{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003793 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003794 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003795 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003796 u8 tx_seq;
3797 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003799 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003800 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801 BT_DBG("unknown cid 0x%4.4x", cid);
3802 goto drop;
3803 }
3804
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003805 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003806
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003807 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003809 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 goto drop;
3811
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003812 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003813 case L2CAP_MODE_BASIC:
3814 /* If socket recv buffers overflows we drop data here
3815 * which is *bad* because L2CAP has to be reliable.
3816 * But we don't have any other choice. L2CAP doesn't
3817 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003818
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003819 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003820 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003822 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003823 goto done;
3824 break;
3825
3826 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003827 if (!sock_owned_by_user(sk)) {
3828 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003829 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003830 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003831 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003832 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003833
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003834 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003835
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003836 case L2CAP_MODE_STREAMING:
3837 control = get_unaligned_le16(skb->data);
3838 skb_pull(skb, 2);
3839 len = skb->len;
3840
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003841 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003842 goto drop;
3843
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003844 if (__is_sar_start(control))
3845 len -= 2;
3846
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003847 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003848 len -= 2;
3849
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003850 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003851 goto drop;
3852
3853 tx_seq = __get_txseq(control);
3854
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003855 if (chan->expected_tx_seq == tx_seq)
3856 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003857 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003858 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003859
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003860 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003861
3862 goto done;
3863
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003864 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003865 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003866 break;
3867 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868
3869drop:
3870 kfree_skb(skb);
3871
3872done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003873 if (sk)
3874 bh_unlock_sock(sk);
3875
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876 return 0;
3877}
3878
Al Viro8e036fc2007-07-29 00:16:36 -07003879static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003881 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003882 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003884 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3885 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003886 goto drop;
3887
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003888 sk = chan->sk;
3889
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003890 bh_lock_sock(sk);
3891
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892 BT_DBG("sk %p, len %d", sk, skb->len);
3893
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003894 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895 goto drop;
3896
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003897 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 goto drop;
3899
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003900 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901 goto done;
3902
3903drop:
3904 kfree_skb(skb);
3905
3906done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003907 if (sk)
3908 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003909 return 0;
3910}
3911
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003912static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3913{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003914 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003915 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003916
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003917 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3918 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003919 goto drop;
3920
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003921 sk = chan->sk;
3922
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003923 bh_lock_sock(sk);
3924
3925 BT_DBG("sk %p, len %d", sk, skb->len);
3926
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003927 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003928 goto drop;
3929
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003930 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003931 goto drop;
3932
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003933 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003934 goto done;
3935
3936drop:
3937 kfree_skb(skb);
3938
3939done:
3940 if (sk)
3941 bh_unlock_sock(sk);
3942 return 0;
3943}
3944
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3946{
3947 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003948 u16 cid, len;
3949 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950
3951 skb_pull(skb, L2CAP_HDR_SIZE);
3952 cid = __le16_to_cpu(lh->cid);
3953 len = __le16_to_cpu(lh->len);
3954
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003955 if (len != skb->len) {
3956 kfree_skb(skb);
3957 return;
3958 }
3959
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3961
3962 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003963 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003964 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965 l2cap_sig_channel(conn, skb);
3966 break;
3967
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003968 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003969 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970 skb_pull(skb, 2);
3971 l2cap_conless_channel(conn, psm, skb);
3972 break;
3973
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003974 case L2CAP_CID_LE_DATA:
3975 l2cap_att_channel(conn, cid, skb);
3976 break;
3977
Anderson Brigliab501d6a2011-06-07 18:46:31 -03003978 case L2CAP_CID_SMP:
3979 if (smp_sig_channel(conn, skb))
3980 l2cap_conn_del(conn->hcon, EACCES);
3981 break;
3982
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983 default:
3984 l2cap_data_channel(conn, cid, skb);
3985 break;
3986 }
3987}
3988
3989/* ---- L2CAP interface with lower layer (HCI) ---- */
3990
3991static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3992{
3993 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003994 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995
3996 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003997 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998
3999 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4000
4001 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004002 read_lock(&chan_list_lock);
4003 list_for_each_entry(c, &chan_list, global_l) {
4004 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004005
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004006 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007 continue;
4008
4009 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004010 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004011 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004012 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004014 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4015 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004016 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004017 lm2 |= HCI_LM_MASTER;
4018 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004020 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021
4022 return exact ? lm1 : lm2;
4023}
4024
4025static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4026{
Marcel Holtmann01394182006-07-03 10:02:46 +02004027 struct l2cap_conn *conn;
4028
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4030
Ville Tervoacd7d372011-02-10 22:38:49 -03004031 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004032 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033
4034 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035 conn = l2cap_conn_add(hcon, status);
4036 if (conn)
4037 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004038 } else
Joe Perchese1750722011-06-29 18:18:29 -07004039 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004040
4041 return 0;
4042}
4043
Marcel Holtmann2950f212009-02-12 14:02:50 +01004044static int l2cap_disconn_ind(struct hci_conn *hcon)
4045{
4046 struct l2cap_conn *conn = hcon->l2cap_data;
4047
4048 BT_DBG("hcon %p", hcon);
4049
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03004050 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004051 return 0x13;
4052
4053 return conn->disc_reason;
4054}
4055
4056static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057{
4058 BT_DBG("hcon %p reason %d", hcon, reason);
4059
Ville Tervoacd7d372011-02-10 22:38:49 -03004060 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004061 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004062
Joe Perchese1750722011-06-29 18:18:29 -07004063 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004064
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065 return 0;
4066}
4067
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004068static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004069{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004070 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004071 return;
4072
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004073 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004074 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004075 __clear_chan_timer(chan);
4076 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004077 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004078 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004079 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004080 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004081 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004082 }
4083}
4084
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004085static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004087 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004088 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089
Marcel Holtmann01394182006-07-03 10:02:46 +02004090 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004092
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093 BT_DBG("conn %p", conn);
4094
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004095 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004097 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004098 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004099
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100 bh_lock_sock(sk);
4101
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004102 BT_DBG("chan->scid %d", chan->scid);
4103
4104 if (chan->scid == L2CAP_CID_LE_DATA) {
4105 if (!status && encrypt) {
4106 chan->sec_level = hcon->sec_level;
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03004107 del_timer(&conn->security_timer);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004108 l2cap_chan_ready(sk);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03004109 smp_distribute_keys(conn, 0);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004110 }
4111
4112 bh_unlock_sock(sk);
4113 continue;
4114 }
4115
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004116 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004117 bh_unlock_sock(sk);
4118 continue;
4119 }
4120
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004121 if (!status && (chan->state == BT_CONNECTED ||
4122 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004123 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004124 bh_unlock_sock(sk);
4125 continue;
4126 }
4127
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004128 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004129 if (!status) {
4130 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004131 req.scid = cpu_to_le16(chan->scid);
4132 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004133
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004134 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004135 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004136
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004137 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004138 L2CAP_CONN_REQ, sizeof(req), &req);
4139 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004140 __clear_chan_timer(chan);
4141 __set_chan_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004142 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004143 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004144 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004145 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004146
4147 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004148 if (bt_sk(sk)->defer_setup) {
4149 struct sock *parent = bt_sk(sk)->parent;
4150 res = L2CAP_CR_PEND;
4151 stat = L2CAP_CS_AUTHOR_PEND;
4152 parent->sk_data_ready(parent, 0);
4153 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004154 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004155 res = L2CAP_CR_SUCCESS;
4156 stat = L2CAP_CS_NO_INFO;
4157 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004158 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004159 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004160 __set_chan_timer(chan, HZ / 10);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004161 res = L2CAP_CR_SEC_BLOCK;
4162 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004163 }
4164
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004165 rsp.scid = cpu_to_le16(chan->dcid);
4166 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004167 rsp.result = cpu_to_le16(res);
4168 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004169 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4170 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171 }
4172
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173 bh_unlock_sock(sk);
4174 }
4175
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004176 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004177
Linus Torvalds1da177e2005-04-16 15:20:36 -07004178 return 0;
4179}
4180
4181static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4182{
4183 struct l2cap_conn *conn = hcon->l2cap_data;
4184
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004185 if (!conn)
4186 conn = l2cap_conn_add(hcon, 0);
4187
4188 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189 goto drop;
4190
4191 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4192
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004193 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004194 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004195 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004196 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004197 int len;
4198
4199 if (conn->rx_len) {
4200 BT_ERR("Unexpected start frame (len %d)", skb->len);
4201 kfree_skb(conn->rx_skb);
4202 conn->rx_skb = NULL;
4203 conn->rx_len = 0;
4204 l2cap_conn_unreliable(conn, ECOMM);
4205 }
4206
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004207 /* Start fragment always begin with Basic L2CAP header */
4208 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209 BT_ERR("Frame is too short (len %d)", skb->len);
4210 l2cap_conn_unreliable(conn, ECOMM);
4211 goto drop;
4212 }
4213
4214 hdr = (struct l2cap_hdr *) skb->data;
4215 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004216 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217
4218 if (len == skb->len) {
4219 /* Complete frame received */
4220 l2cap_recv_frame(conn, skb);
4221 return 0;
4222 }
4223
4224 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4225
4226 if (skb->len > len) {
4227 BT_ERR("Frame is too long (len %d, expected len %d)",
4228 skb->len, len);
4229 l2cap_conn_unreliable(conn, ECOMM);
4230 goto drop;
4231 }
4232
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004233 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004234
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004235 if (chan && chan->sk) {
4236 struct sock *sk = chan->sk;
4237
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004238 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004239 BT_ERR("Frame exceeding recv MTU (len %d, "
4240 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004241 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004242 bh_unlock_sock(sk);
4243 l2cap_conn_unreliable(conn, ECOMM);
4244 goto drop;
4245 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004246 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004247 }
4248
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004250 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4251 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252 goto drop;
4253
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004254 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004255 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256 conn->rx_len = len - skb->len;
4257 } else {
4258 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4259
4260 if (!conn->rx_len) {
4261 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4262 l2cap_conn_unreliable(conn, ECOMM);
4263 goto drop;
4264 }
4265
4266 if (skb->len > conn->rx_len) {
4267 BT_ERR("Fragment is too long (len %d, expected %d)",
4268 skb->len, conn->rx_len);
4269 kfree_skb(conn->rx_skb);
4270 conn->rx_skb = NULL;
4271 conn->rx_len = 0;
4272 l2cap_conn_unreliable(conn, ECOMM);
4273 goto drop;
4274 }
4275
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004276 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004277 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278 conn->rx_len -= skb->len;
4279
4280 if (!conn->rx_len) {
4281 /* Complete frame received */
4282 l2cap_recv_frame(conn, conn->rx_skb);
4283 conn->rx_skb = NULL;
4284 }
4285 }
4286
4287drop:
4288 kfree_skb(skb);
4289 return 0;
4290}
4291
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004292static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004294 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004296 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004298 list_for_each_entry(c, &chan_list, global_l) {
4299 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004301 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 +01004302 batostr(&bt_sk(sk)->src),
4303 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004304 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004305 c->scid, c->dcid, c->imtu, c->omtu,
4306 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004307}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004309 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004310
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004311 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312}
4313
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004314static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4315{
4316 return single_open(file, l2cap_debugfs_show, inode->i_private);
4317}
4318
4319static const struct file_operations l2cap_debugfs_fops = {
4320 .open = l2cap_debugfs_open,
4321 .read = seq_read,
4322 .llseek = seq_lseek,
4323 .release = single_release,
4324};
4325
4326static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004327
Linus Torvalds1da177e2005-04-16 15:20:36 -07004328static struct hci_proto l2cap_hci_proto = {
4329 .name = "L2CAP",
4330 .id = HCI_PROTO_L2CAP,
4331 .connect_ind = l2cap_connect_ind,
4332 .connect_cfm = l2cap_connect_cfm,
4333 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004334 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004335 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336 .recv_acldata = l2cap_recv_acldata
4337};
4338
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004339int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004340{
4341 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004342
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004343 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344 if (err < 0)
4345 return err;
4346
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347 err = hci_register_proto(&l2cap_hci_proto);
4348 if (err < 0) {
4349 BT_ERR("L2CAP protocol registration failed");
4350 bt_sock_unregister(BTPROTO_L2CAP);
4351 goto error;
4352 }
4353
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004354 if (bt_debugfs) {
4355 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4356 bt_debugfs, NULL, &l2cap_debugfs_fops);
4357 if (!l2cap_debugfs)
4358 BT_ERR("Failed to create L2CAP debug file");
4359 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004360
Linus Torvalds1da177e2005-04-16 15:20:36 -07004361 return 0;
4362
4363error:
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004364 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365 return err;
4366}
4367
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004368void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004370 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4373 BT_ERR("L2CAP protocol unregistration failed");
4374
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004375 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376}
4377
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004378module_param(disable_ertm, bool, 0644);
4379MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");