blob: 18a08c59f0831e3c2d3362e465bc882e753411b6 [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;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +030060int enable_hs;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020061
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070062static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010063static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Johannes Bergb5ad8b72011-06-01 08:54:45 +020065static LIST_HEAD(chan_list);
66static DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Linus Torvalds1da177e2005-04-16 15:20:36 -070068static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
69 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030070static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
71 void *data);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -030072static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030073static void l2cap_send_disconn_req(struct l2cap_conn *conn,
74 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030076static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
77
Marcel Holtmann01394182006-07-03 10:02:46 +020078/* ---- L2CAP channels ---- */
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -030079
80static inline void chan_hold(struct l2cap_chan *c)
81{
82 atomic_inc(&c->refcnt);
83}
84
85static inline void chan_put(struct l2cap_chan *c)
86{
87 if (atomic_dec_and_test(&c->refcnt))
88 kfree(c);
89}
90
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030091static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020092{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030093 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030094
95 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030096 if (c->dcid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030097 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020098 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030099 return NULL;
100
Marcel Holtmann01394182006-07-03 10:02:46 +0200101}
102
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300103static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200104{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300105 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300106
107 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300108 if (c->scid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300109 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200110 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300111 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200112}
113
114/* Find channel with given SCID.
115 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300116static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200117{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300118 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300119
120 read_lock(&conn->chan_lock);
121 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300122 if (c)
123 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300124 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300125 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200126}
127
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300128static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200129{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300130 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300131
132 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300133 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300134 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200135 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300136 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200137}
138
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300139static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200140{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300141 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300142
143 read_lock(&conn->chan_lock);
144 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300145 if (c)
146 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300147 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300148 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200149}
150
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300151static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300152{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300153 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300154
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300155 list_for_each_entry(c, &chan_list, global_l) {
156 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300157 goto found;
158 }
159
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300160 c = NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300161found:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300162 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300163}
164
165int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
166{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300167 int err;
168
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300169 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300170
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300171 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300172 err = -EADDRINUSE;
173 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300174 }
175
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300176 if (psm) {
177 chan->psm = psm;
178 chan->sport = psm;
179 err = 0;
180 } else {
181 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300182
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300183 err = -EINVAL;
184 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300185 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300186 chan->psm = cpu_to_le16(p);
187 chan->sport = cpu_to_le16(p);
188 err = 0;
189 break;
190 }
191 }
192
193done:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300194 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300195 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300196}
197
198int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
199{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300200 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300201
202 chan->scid = scid;
203
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300204 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300205
206 return 0;
207}
208
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300209static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200210{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300211 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200212
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300213 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300214 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200215 return cid;
216 }
217
218 return 0;
219}
220
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300221static void l2cap_set_timer(struct l2cap_chan *chan, struct timer_list *timer, long timeout)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300222{
Mat Martineau774e5652011-06-29 14:35:20 -0700223 BT_DBG("chan %p state %d timeout %ld", chan->sk, chan->state, timeout);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300224
Mat Martineau942ecc92011-06-29 14:35:21 -0700225 if (!mod_timer(timer, jiffies + msecs_to_jiffies(timeout)))
Mat Martineau774e5652011-06-29 14:35:20 -0700226 chan_hold(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300227}
228
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300229static void l2cap_clear_timer(struct l2cap_chan *chan, struct timer_list *timer)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300230{
Mat Martineau774e5652011-06-29 14:35:20 -0700231 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300232
Mat Martineau774e5652011-06-29 14:35:20 -0700233 if (timer_pending(timer) && del_timer(timer))
234 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300235}
236
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300237static void l2cap_state_change(struct l2cap_chan *chan, int state)
238{
239 chan->state = state;
240 chan->ops->state_change(chan->data, state);
241}
242
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300243static void l2cap_chan_timeout(unsigned long arg)
244{
245 struct l2cap_chan *chan = (struct l2cap_chan *) arg;
246 struct sock *sk = chan->sk;
247 int reason;
248
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300249 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300250
251 bh_lock_sock(sk);
252
253 if (sock_owned_by_user(sk)) {
254 /* sk is owned by user. Try again later */
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300255 __set_chan_timer(chan, HZ / 5);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300256 bh_unlock_sock(sk);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300257 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300258 return;
259 }
260
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300261 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300262 reason = ECONNREFUSED;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300263 else if (chan->state == BT_CONNECT &&
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300264 chan->sec_level != BT_SECURITY_SDP)
265 reason = ECONNREFUSED;
266 else
267 reason = ETIMEDOUT;
268
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300269 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300270
271 bh_unlock_sock(sk);
272
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300273 chan->ops->close(chan->data);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300274 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300275}
276
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300277struct l2cap_chan *l2cap_chan_create(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200278{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300279 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200280
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300281 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
282 if (!chan)
283 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200284
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300285 chan->sk = sk;
286
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300287 write_lock_bh(&chan_list_lock);
288 list_add(&chan->global_l, &chan_list);
289 write_unlock_bh(&chan_list_lock);
290
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300291 setup_timer(&chan->chan_timer, l2cap_chan_timeout, (unsigned long) chan);
292
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300293 chan->state = BT_OPEN;
294
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300295 atomic_set(&chan->refcnt, 1);
296
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300297 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200298}
299
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300300void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300301{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300302 write_lock_bh(&chan_list_lock);
303 list_del(&chan->global_l);
304 write_unlock_bh(&chan_list_lock);
305
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300306 chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300307}
308
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300309static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200310{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300311 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300312 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200313
Marcel Holtmann2950f212009-02-12 14:02:50 +0100314 conn->disc_reason = 0x13;
315
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300316 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200317
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300318 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
Ville Tervob62f3282011-02-10 22:38:50 -0300319 if (conn->hcon->type == LE_LINK) {
320 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300321 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300322 chan->scid = L2CAP_CID_LE_DATA;
323 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300324 } else {
325 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300326 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300327 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300328 }
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300329 } else if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200330 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300331 chan->scid = L2CAP_CID_CONN_LESS;
332 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300333 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200334 } else {
335 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300336 chan->scid = L2CAP_CID_SIGNALING;
337 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300338 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200339 }
340
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300341 chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300342
343 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200344}
345
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900346/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200347 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300348static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200349{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300350 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300351 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200352 struct sock *parent = bt_sk(sk)->parent;
353
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300354 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200355
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300356 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200357
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900358 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300359 /* Delete from channel list */
360 write_lock_bh(&conn->chan_lock);
361 list_del(&chan->list);
362 write_unlock_bh(&conn->chan_lock);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300363 chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300364
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300365 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200366 hci_conn_put(conn->hcon);
367 }
368
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300369 l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200370 sock_set_flag(sk, SOCK_ZAPPED);
371
372 if (err)
373 sk->sk_err = err;
374
375 if (parent) {
376 bt_accept_unlink(sk);
377 parent->sk_data_ready(parent, 0);
378 } else
379 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300380
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300381 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
382 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300383 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300384
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300385 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300386
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300387 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300388 struct srej_list *l, *tmp;
389
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300390 __clear_retrans_timer(chan);
391 __clear_monitor_timer(chan);
392 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300393
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300394 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300395
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300396 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300397 list_del(&l->list);
398 kfree(l);
399 }
400 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200401}
402
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300403static void l2cap_chan_cleanup_listen(struct sock *parent)
404{
405 struct sock *sk;
406
407 BT_DBG("parent %p", parent);
408
409 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300410 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300411 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300412 __clear_chan_timer(chan);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300413 lock_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300414 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300415 release_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300416 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300417 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300418}
419
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300420void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300421{
422 struct l2cap_conn *conn = chan->conn;
423 struct sock *sk = chan->sk;
424
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300425 BT_DBG("chan %p state %d socket %p", chan, chan->state, sk->sk_socket);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300426
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300427 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300428 case BT_LISTEN:
429 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300430
431 l2cap_state_change(chan, BT_CLOSED);
432 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300433 break;
434
435 case BT_CONNECTED:
436 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300437 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300438 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300439 __clear_chan_timer(chan);
440 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300441 l2cap_send_disconn_req(conn, chan, reason);
442 } else
443 l2cap_chan_del(chan, reason);
444 break;
445
446 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300447 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300448 conn->hcon->type == ACL_LINK) {
449 struct l2cap_conn_rsp rsp;
450 __u16 result;
451
452 if (bt_sk(sk)->defer_setup)
453 result = L2CAP_CR_SEC_BLOCK;
454 else
455 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300456 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300457
458 rsp.scid = cpu_to_le16(chan->dcid);
459 rsp.dcid = cpu_to_le16(chan->scid);
460 rsp.result = cpu_to_le16(result);
461 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
462 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
463 sizeof(rsp), &rsp);
464 }
465
466 l2cap_chan_del(chan, reason);
467 break;
468
469 case BT_CONNECT:
470 case BT_DISCONN:
471 l2cap_chan_del(chan, reason);
472 break;
473
474 default:
475 sock_set_flag(sk, SOCK_ZAPPED);
476 break;
477 }
478}
479
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300480static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530481{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300482 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300483 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530484 case BT_SECURITY_HIGH:
485 return HCI_AT_DEDICATED_BONDING_MITM;
486 case BT_SECURITY_MEDIUM:
487 return HCI_AT_DEDICATED_BONDING;
488 default:
489 return HCI_AT_NO_BONDING;
490 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300491 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300492 if (chan->sec_level == BT_SECURITY_LOW)
493 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530494
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300495 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530496 return HCI_AT_NO_BONDING_MITM;
497 else
498 return HCI_AT_NO_BONDING;
499 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300500 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530501 case BT_SECURITY_HIGH:
502 return HCI_AT_GENERAL_BONDING_MITM;
503 case BT_SECURITY_MEDIUM:
504 return HCI_AT_GENERAL_BONDING;
505 default:
506 return HCI_AT_NO_BONDING;
507 }
508 }
509}
510
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200511/* Service level security */
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300512static inline int l2cap_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200513{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300514 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100515 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200516
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300517 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100518
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300519 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200520}
521
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200522static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200523{
524 u8 id;
525
526 /* Get next available identificator.
527 * 1 - 128 are used by kernel.
528 * 129 - 199 are reserved.
529 * 200 - 254 are used by utilities like l2ping, etc.
530 */
531
532 spin_lock_bh(&conn->lock);
533
534 if (++conn->tx_ident > 128)
535 conn->tx_ident = 1;
536
537 id = conn->tx_ident;
538
539 spin_unlock_bh(&conn->lock);
540
541 return id;
542}
543
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300544static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200545{
546 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200547 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200548
549 BT_DBG("code 0x%2.2x", code);
550
551 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300552 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200553
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200554 if (lmp_no_flush_capable(conn->hcon->hdev))
555 flags = ACL_START_NO_FLUSH;
556 else
557 flags = ACL_START;
558
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700559 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
560
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200561 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200562}
563
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300564static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300565{
566 struct sk_buff *skb;
567 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300568 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300569 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200570 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300571
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300572 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300573 return;
574
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300575 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300576 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300577
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300578 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300579
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300580 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300581 control |= L2CAP_CTRL_FRAME_TYPE;
582
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300583 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300584 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300585
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300586 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300587 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300588
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300589 skb = bt_skb_alloc(count, GFP_ATOMIC);
590 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300591 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300592
593 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300594 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300595 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300596 put_unaligned_le16(control, skb_put(skb, 2));
597
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300598 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300599 u16 fcs = crc16(0, (u8 *)lh, count - 2);
600 put_unaligned_le16(fcs, skb_put(skb, 2));
601 }
602
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200603 if (lmp_no_flush_capable(conn->hcon->hdev))
604 flags = ACL_START_NO_FLUSH;
605 else
606 flags = ACL_START;
607
Andrei Emeltchenko15770b12011-10-11 14:04:33 +0300608 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700609
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300610 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300611}
612
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300613static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300614{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300615 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300616 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300617 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300618 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300619 control |= L2CAP_SUPER_RCV_READY;
620
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300621 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300622
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300623 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300624}
625
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300626static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300627{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300628 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300629}
630
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300631static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200632{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300633 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200634
635 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100636 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
637 return;
638
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300639 if (l2cap_check_security(chan) &&
640 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200641 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300642 req.scid = cpu_to_le16(chan->scid);
643 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200644
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300645 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300646 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200647
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300648 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
649 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200650 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200651 } else {
652 struct l2cap_info_req req;
653 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
654
655 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
656 conn->info_ident = l2cap_get_ident(conn);
657
658 mod_timer(&conn->info_timer, jiffies +
659 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
660
661 l2cap_send_cmd(conn, conn->info_ident,
662 L2CAP_INFO_REQ, sizeof(req), &req);
663 }
664}
665
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300666static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
667{
668 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300669 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300670 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
671
672 switch (mode) {
673 case L2CAP_MODE_ERTM:
674 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
675 case L2CAP_MODE_STREAMING:
676 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
677 default:
678 return 0x00;
679 }
680}
681
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300682static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300683{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300684 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300685 struct l2cap_disconn_req req;
686
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300687 if (!conn)
688 return;
689
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300690 sk = chan->sk;
691
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300692 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300693 __clear_retrans_timer(chan);
694 __clear_monitor_timer(chan);
695 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300696 }
697
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300698 req.dcid = cpu_to_le16(chan->dcid);
699 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300700 l2cap_send_cmd(conn, l2cap_get_ident(conn),
701 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300702
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300703 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300704 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300705}
706
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200708static void l2cap_conn_start(struct l2cap_conn *conn)
709{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300710 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200711
712 BT_DBG("conn %p", conn);
713
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300714 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200715
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300716 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300717 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300718
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200719 bh_lock_sock(sk);
720
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300721 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200722 bh_unlock_sock(sk);
723 continue;
724 }
725
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300726 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300727 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300728
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300729 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300730 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300731 bh_unlock_sock(sk);
732 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200733 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300734
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300735 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
736 && test_bit(CONF_STATE2_DEVICE,
737 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300738 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300739 * so release the lock */
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300740 read_unlock(&conn->chan_lock);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300741 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300742 read_lock(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300743 bh_unlock_sock(sk);
744 continue;
745 }
746
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300747 req.scid = cpu_to_le16(chan->scid);
748 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300749
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300750 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300751 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300752
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300753 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
754 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300755
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300756 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200757 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300758 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300759 rsp.scid = cpu_to_le16(chan->dcid);
760 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200761
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300762 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100763 if (bt_sk(sk)->defer_setup) {
764 struct sock *parent = bt_sk(sk)->parent;
765 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
766 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000767 if (parent)
768 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100769
770 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300771 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100772 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
773 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
774 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200775 } else {
776 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
777 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
778 }
779
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300780 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
781 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300782
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300783 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300784 rsp.result != L2CAP_CR_SUCCESS) {
785 bh_unlock_sock(sk);
786 continue;
787 }
788
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300789 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300790 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300791 l2cap_build_conf_req(chan, buf), buf);
792 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200793 }
794
795 bh_unlock_sock(sk);
796 }
797
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300798 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200799}
800
Ville Tervob62f3282011-02-10 22:38:50 -0300801/* Find socket with cid and source bdaddr.
802 * Returns closest match, locked.
803 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300804static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300805{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300806 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300807
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300808 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300809
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300810 list_for_each_entry(c, &chan_list, global_l) {
811 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300812
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300813 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300814 continue;
815
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300816 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300817 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300818 if (!bacmp(&bt_sk(sk)->src, src)) {
819 read_unlock(&chan_list_lock);
820 return c;
821 }
Ville Tervob62f3282011-02-10 22:38:50 -0300822
823 /* Closest match */
824 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300825 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300826 }
827 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300828
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300829 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300830
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300831 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300832}
833
834static void l2cap_le_conn_ready(struct l2cap_conn *conn)
835{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300836 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300837 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300838
839 BT_DBG("");
840
841 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300842 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300843 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300844 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300845 return;
846
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300847 parent = pchan->sk;
848
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300849 bh_lock_sock(parent);
850
Ville Tervob62f3282011-02-10 22:38:50 -0300851 /* Check for backlog size */
852 if (sk_acceptq_is_full(parent)) {
853 BT_DBG("backlog full %d", parent->sk_ack_backlog);
854 goto clean;
855 }
856
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300857 chan = pchan->ops->new_connection(pchan->data);
858 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300859 goto clean;
860
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300861 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300862
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300863 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300864
865 hci_conn_hold(conn->hcon);
866
Ville Tervob62f3282011-02-10 22:38:50 -0300867 bacpy(&bt_sk(sk)->src, conn->src);
868 bacpy(&bt_sk(sk)->dst, conn->dst);
869
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300870 bt_accept_enqueue(parent, sk);
871
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300872 __l2cap_chan_add(conn, chan);
873
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300874 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300875
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300876 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300877 parent->sk_data_ready(parent, 0);
878
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300879 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300880
881clean:
882 bh_unlock_sock(parent);
883}
884
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300885static void l2cap_chan_ready(struct sock *sk)
886{
887 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
888 struct sock *parent = bt_sk(sk)->parent;
889
890 BT_DBG("sk %p, parent %p", sk, parent);
891
892 chan->conf_state = 0;
893 __clear_chan_timer(chan);
894
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300895 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300896 sk->sk_state_change(sk);
897
898 if (parent)
899 parent->sk_data_ready(parent, 0);
900}
901
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200902static void l2cap_conn_ready(struct l2cap_conn *conn)
903{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300904 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200905
906 BT_DBG("conn %p", conn);
907
Ville Tervob62f3282011-02-10 22:38:50 -0300908 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
909 l2cap_le_conn_ready(conn);
910
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300911 if (conn->hcon->out && conn->hcon->type == LE_LINK)
912 smp_conn_security(conn, conn->hcon->pending_sec_level);
913
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300914 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200915
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300916 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300917 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300918
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200919 bh_lock_sock(sk);
920
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300921 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300922 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300923 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300924
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300925 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300926 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300927 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200928 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300929
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300930 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300931 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200932
933 bh_unlock_sock(sk);
934 }
935
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300936 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200937}
938
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200939/* Notify sockets that we cannot guaranty reliability anymore */
940static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
941{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300942 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200943
944 BT_DBG("conn %p", conn);
945
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300946 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200947
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300948 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300949 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300950
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300951 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200952 sk->sk_err = err;
953 }
954
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300955 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200956}
957
958static void l2cap_info_timeout(unsigned long arg)
959{
960 struct l2cap_conn *conn = (void *) arg;
961
Marcel Holtmann984947d2009-02-06 23:35:19 +0100962 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100963 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100964
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200965 l2cap_conn_start(conn);
966}
967
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300968static void l2cap_conn_del(struct hci_conn *hcon, int err)
969{
970 struct l2cap_conn *conn = hcon->l2cap_data;
971 struct l2cap_chan *chan, *l;
972 struct sock *sk;
973
974 if (!conn)
975 return;
976
977 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
978
979 kfree_skb(conn->rx_skb);
980
981 /* Kill channels */
982 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
983 sk = chan->sk;
984 bh_lock_sock(sk);
985 l2cap_chan_del(chan, err);
986 bh_unlock_sock(sk);
987 chan->ops->close(chan->data);
988 }
989
990 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
991 del_timer_sync(&conn->info_timer);
992
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300993 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) {
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300994 del_timer(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300995 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300996 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300997
998 hcon->l2cap_data = NULL;
999 kfree(conn);
1000}
1001
1002static void security_timeout(unsigned long arg)
1003{
1004 struct l2cap_conn *conn = (void *) arg;
1005
1006 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1007}
1008
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1010{
Marcel Holtmann01394182006-07-03 10:02:46 +02001011 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012
Marcel Holtmann01394182006-07-03 10:02:46 +02001013 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 return conn;
1015
Marcel Holtmann01394182006-07-03 10:02:46 +02001016 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1017 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019
1020 hcon->l2cap_data = conn;
1021 conn->hcon = hcon;
1022
Marcel Holtmann01394182006-07-03 10:02:46 +02001023 BT_DBG("hcon %p conn %p", hcon, conn);
1024
Ville Tervoacd7d372011-02-10 22:38:49 -03001025 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1026 conn->mtu = hcon->hdev->le_mtu;
1027 else
1028 conn->mtu = hcon->hdev->acl_mtu;
1029
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 conn->src = &hcon->hdev->bdaddr;
1031 conn->dst = &hcon->dst;
1032
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001033 conn->feat_mask = 0;
1034
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001036 rwlock_init(&conn->chan_lock);
1037
1038 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001040 if (hcon->type == LE_LINK)
1041 setup_timer(&conn->security_timer, security_timeout,
1042 (unsigned long) conn);
1043 else
Ville Tervob62f3282011-02-10 22:38:50 -03001044 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +00001045 (unsigned long) conn);
1046
Marcel Holtmann2950f212009-02-12 14:02:50 +01001047 conn->disc_reason = 0x13;
1048
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 return conn;
1050}
1051
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001052static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001054 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001055 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001056 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057}
1058
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060
1061/* Find socket with psm and source bdaddr.
1062 * Returns closest match.
1063 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001064static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001066 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001068 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001069
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001070 list_for_each_entry(c, &chan_list, global_l) {
1071 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001072
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001073 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 continue;
1075
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001076 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001078 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001079 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001080 return c;
1081 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082
1083 /* Closest match */
1084 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001085 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 }
1087 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001089 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001090
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001091 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092}
1093
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001094int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001096 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 bdaddr_t *src = &bt_sk(sk)->src;
1098 bdaddr_t *dst = &bt_sk(sk)->dst;
1099 struct l2cap_conn *conn;
1100 struct hci_conn *hcon;
1101 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001102 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001103 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001105 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001106 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001108 hdev = hci_get_route(dst, src);
1109 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 return -EHOSTUNREACH;
1111
1112 hci_dev_lock_bh(hdev);
1113
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001114 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001115
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001116 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001117 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001118 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001119 else
1120 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001121 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001122
Ville Tervo30e76272011-02-22 16:10:53 -03001123 if (IS_ERR(hcon)) {
1124 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001126 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127
1128 conn = l2cap_conn_add(hcon, 0);
1129 if (!conn) {
1130 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001131 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 goto done;
1133 }
1134
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 /* Update source addr of the socket */
1136 bacpy(src, conn->src);
1137
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001138 l2cap_chan_add(conn, chan);
1139
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001140 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001141 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
1143 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001144 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001145 __clear_chan_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001146 if (l2cap_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001147 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001148 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001149 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 }
1151
Ville Tervo30e76272011-02-22 16:10:53 -03001152 err = 0;
1153
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154done:
1155 hci_dev_unlock_bh(hdev);
1156 hci_dev_put(hdev);
1157 return err;
1158}
1159
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001160int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001161{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001162 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001163 DECLARE_WAITQUEUE(wait, current);
1164 int err = 0;
1165 int timeo = HZ/5;
1166
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001167 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001168 set_current_state(TASK_INTERRUPTIBLE);
1169 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001170 if (!timeo)
1171 timeo = HZ/5;
1172
1173 if (signal_pending(current)) {
1174 err = sock_intr_errno(timeo);
1175 break;
1176 }
1177
1178 release_sock(sk);
1179 timeo = schedule_timeout(timeo);
1180 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001181 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001182
1183 err = sock_error(sk);
1184 if (err)
1185 break;
1186 }
1187 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001188 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001189 return err;
1190}
1191
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001192static void l2cap_monitor_timeout(unsigned long arg)
1193{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001194 struct l2cap_chan *chan = (void *) arg;
1195 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001196
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001197 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001198
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001199 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001200 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001201 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001202 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001203 return;
1204 }
1205
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001206 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001207 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001208
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001209 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001210 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001211}
1212
1213static void l2cap_retrans_timeout(unsigned long arg)
1214{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001215 struct l2cap_chan *chan = (void *) arg;
1216 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001217
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001218 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001219
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001220 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001221 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001222 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001223
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001224 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001225
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001226 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001227 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001228}
1229
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001230static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001231{
1232 struct sk_buff *skb;
1233
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001234 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001235 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001236 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001237 break;
1238
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001239 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001240 kfree_skb(skb);
1241
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001242 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001243 }
1244
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001245 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001246 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001247}
1248
Szymon Janc67c9e842011-07-28 16:24:33 +02001249static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001250{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001251 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001252 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001253
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001254 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001255
Andrei Emeltchenkod57b0e82011-10-11 14:04:31 +03001256 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
1257 lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001258 flags = ACL_START_NO_FLUSH;
1259 else
1260 flags = ACL_START;
1261
Andrei Emeltchenko15770b12011-10-11 14:04:33 +03001262 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001263 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001264}
1265
Szymon Janc67c9e842011-07-28 16:24:33 +02001266static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001267{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001268 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001269 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001270
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001271 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001272 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001273 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001274 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001275
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001276 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001277 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1278 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001279 }
1280
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001281 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001282
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001283 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001284 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001285}
1286
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001287static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001288{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001289 struct sk_buff *skb, *tx_skb;
1290 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001291
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001292 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001293 if (!skb)
1294 return;
1295
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001296 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001297 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001298 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001299
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001300 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001301 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001302
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001303 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001304
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001305 if (chan->remote_max_tx &&
1306 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001307 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001308 return;
1309 }
1310
1311 tx_skb = skb_clone(skb, GFP_ATOMIC);
1312 bt_cb(skb)->retries++;
1313 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001314 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001315
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001316 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001317 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001318
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001319 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001320 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001321
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001322 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1323
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001324 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001325 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1326 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1327 }
1328
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001329 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001330}
1331
Szymon Janc67c9e842011-07-28 16:24:33 +02001332static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001333{
1334 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001335 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001336 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001337
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001338 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001339 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001340
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001341 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001342
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001343 if (chan->remote_max_tx &&
1344 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001345 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001346 break;
1347 }
1348
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001349 tx_skb = skb_clone(skb, GFP_ATOMIC);
1350
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001351 bt_cb(skb)->retries++;
1352
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001353 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001354 control &= L2CAP_CTRL_SAR;
1355
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001356 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001357 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001358
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001359 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1360 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001361 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1362
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001363
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001364 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001365 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1366 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1367 }
1368
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001369 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001370
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001371 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001372
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001373 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1374 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001375
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301376 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001377 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301378
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001379 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001380
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001381 if (skb_queue_is_last(&chan->tx_q, skb))
1382 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001383 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001384 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001385
1386 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001387 }
1388
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001389 return nsent;
1390}
1391
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001392static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001393{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001394 int ret;
1395
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001396 if (!skb_queue_empty(&chan->tx_q))
1397 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001398
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001399 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001400 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001401 return ret;
1402}
1403
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001404static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001405{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001406 u16 control = 0;
1407
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001408 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001409
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001410 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001411 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001412 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001413 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001414 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001415 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001416
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001417 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001418 return;
1419
1420 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001421 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001422}
1423
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001424static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001425{
1426 struct srej_list *tail;
1427 u16 control;
1428
1429 control = L2CAP_SUPER_SELECT_REJECT;
1430 control |= L2CAP_CTRL_FINAL;
1431
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001432 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001433 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1434
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001435 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001436}
1437
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001438static 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 -07001439{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001440 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001441 struct sk_buff **frag;
1442 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001444 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001445 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446
1447 sent += count;
1448 len -= count;
1449
1450 /* Continuation fragments (no L2CAP header) */
1451 frag = &skb_shinfo(skb)->frag_list;
1452 while (len) {
1453 count = min_t(unsigned int, conn->mtu, len);
1454
1455 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1456 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001457 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001458 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1459 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460
1461 sent += count;
1462 len -= count;
1463
1464 frag = &(*frag)->next;
1465 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
1467 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001468}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469
Szymon Janc67c9e842011-07-28 16:24:33 +02001470static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001471{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001472 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001473 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001474 struct sk_buff *skb;
1475 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1476 struct l2cap_hdr *lh;
1477
1478 BT_DBG("sk %p len %d", sk, (int)len);
1479
1480 count = min_t(unsigned int, (conn->mtu - hlen), len);
1481 skb = bt_skb_send_alloc(sk, count + hlen,
1482 msg->msg_flags & MSG_DONTWAIT, &err);
1483 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001484 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001485
1486 /* Create L2CAP header */
1487 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001488 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001489 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001490 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001491
1492 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1493 if (unlikely(err < 0)) {
1494 kfree_skb(skb);
1495 return ERR_PTR(err);
1496 }
1497 return skb;
1498}
1499
Szymon Janc67c9e842011-07-28 16:24:33 +02001500static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001501{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001502 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001503 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001504 struct sk_buff *skb;
1505 int err, count, hlen = L2CAP_HDR_SIZE;
1506 struct l2cap_hdr *lh;
1507
1508 BT_DBG("sk %p len %d", sk, (int)len);
1509
1510 count = min_t(unsigned int, (conn->mtu - hlen), len);
1511 skb = bt_skb_send_alloc(sk, count + hlen,
1512 msg->msg_flags & MSG_DONTWAIT, &err);
1513 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001514 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001515
1516 /* Create L2CAP header */
1517 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001518 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001519 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1520
1521 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1522 if (unlikely(err < 0)) {
1523 kfree_skb(skb);
1524 return ERR_PTR(err);
1525 }
1526 return skb;
1527}
1528
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001529static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1530 struct msghdr *msg, size_t len,
1531 u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001532{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001533 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001534 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001535 struct sk_buff *skb;
1536 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1537 struct l2cap_hdr *lh;
1538
1539 BT_DBG("sk %p len %d", sk, (int)len);
1540
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001541 if (!conn)
1542 return ERR_PTR(-ENOTCONN);
1543
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001544 if (sdulen)
1545 hlen += 2;
1546
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001547 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001548 hlen += 2;
1549
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001550 count = min_t(unsigned int, (conn->mtu - hlen), len);
1551 skb = bt_skb_send_alloc(sk, count + hlen,
1552 msg->msg_flags & MSG_DONTWAIT, &err);
1553 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001554 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001555
1556 /* Create L2CAP header */
1557 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001558 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001559 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1560 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001561 if (sdulen)
1562 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001563
1564 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1565 if (unlikely(err < 0)) {
1566 kfree_skb(skb);
1567 return ERR_PTR(err);
1568 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001569
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001570 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001571 put_unaligned_le16(0, skb_put(skb, 2));
1572
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001573 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001574 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575}
1576
Szymon Janc67c9e842011-07-28 16:24:33 +02001577static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001578{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001579 struct sk_buff *skb;
1580 struct sk_buff_head sar_queue;
1581 u16 control;
1582 size_t size = 0;
1583
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001584 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001585 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001586 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001587 if (IS_ERR(skb))
1588 return PTR_ERR(skb);
1589
1590 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001591 len -= chan->remote_mps;
1592 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001593
1594 while (len > 0) {
1595 size_t buflen;
1596
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001597 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001598 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001599 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001600 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001601 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001602 buflen = len;
1603 }
1604
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001605 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001606 if (IS_ERR(skb)) {
1607 skb_queue_purge(&sar_queue);
1608 return PTR_ERR(skb);
1609 }
1610
1611 __skb_queue_tail(&sar_queue, skb);
1612 len -= buflen;
1613 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001614 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001615 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1616 if (chan->tx_send_head == NULL)
1617 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001618
1619 return size;
1620}
1621
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001622int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1623{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001624 struct sk_buff *skb;
1625 u16 control;
1626 int err;
1627
1628 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001629 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001630 skb = l2cap_create_connless_pdu(chan, msg, len);
1631 if (IS_ERR(skb))
1632 return PTR_ERR(skb);
1633
1634 l2cap_do_send(chan, skb);
1635 return len;
1636 }
1637
1638 switch (chan->mode) {
1639 case L2CAP_MODE_BASIC:
1640 /* Check outgoing MTU */
1641 if (len > chan->omtu)
1642 return -EMSGSIZE;
1643
1644 /* Create a basic PDU */
1645 skb = l2cap_create_basic_pdu(chan, msg, len);
1646 if (IS_ERR(skb))
1647 return PTR_ERR(skb);
1648
1649 l2cap_do_send(chan, skb);
1650 err = len;
1651 break;
1652
1653 case L2CAP_MODE_ERTM:
1654 case L2CAP_MODE_STREAMING:
1655 /* Entire SDU fits into one PDU */
1656 if (len <= chan->remote_mps) {
1657 control = L2CAP_SDU_UNSEGMENTED;
1658 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1659 0);
1660 if (IS_ERR(skb))
1661 return PTR_ERR(skb);
1662
1663 __skb_queue_tail(&chan->tx_q, skb);
1664
1665 if (chan->tx_send_head == NULL)
1666 chan->tx_send_head = skb;
1667
1668 } else {
1669 /* Segment SDU into multiples PDUs */
1670 err = l2cap_sar_segment_sdu(chan, msg, len);
1671 if (err < 0)
1672 return err;
1673 }
1674
1675 if (chan->mode == L2CAP_MODE_STREAMING) {
1676 l2cap_streaming_send(chan);
1677 err = len;
1678 break;
1679 }
1680
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001681 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1682 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001683 err = len;
1684 break;
1685 }
1686
1687 err = l2cap_ertm_send(chan);
1688 if (err >= 0)
1689 err = len;
1690
1691 break;
1692
1693 default:
1694 BT_DBG("bad state %1.1x", chan->mode);
1695 err = -EBADFD;
1696 }
1697
1698 return err;
1699}
1700
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701/* Copy frame to all raw sockets on that connection */
1702static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1703{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001705 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706
1707 BT_DBG("conn %p", conn);
1708
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001709 read_lock(&conn->chan_lock);
1710 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001711 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001712 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 continue;
1714
1715 /* Don't send frame to the socket it came from */
1716 if (skb->sk == sk)
1717 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001718 nskb = skb_clone(skb, GFP_ATOMIC);
1719 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 continue;
1721
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001722 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723 kfree_skb(nskb);
1724 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001725 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726}
1727
1728/* ---- L2CAP signalling commands ---- */
1729static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1730 u8 code, u8 ident, u16 dlen, void *data)
1731{
1732 struct sk_buff *skb, **frag;
1733 struct l2cap_cmd_hdr *cmd;
1734 struct l2cap_hdr *lh;
1735 int len, count;
1736
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001737 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1738 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739
1740 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1741 count = min_t(unsigned int, conn->mtu, len);
1742
1743 skb = bt_skb_alloc(count, GFP_ATOMIC);
1744 if (!skb)
1745 return NULL;
1746
1747 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001748 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001749
1750 if (conn->hcon->type == LE_LINK)
1751 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1752 else
1753 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754
1755 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1756 cmd->code = code;
1757 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001758 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759
1760 if (dlen) {
1761 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1762 memcpy(skb_put(skb, count), data, count);
1763 data += count;
1764 }
1765
1766 len -= skb->len;
1767
1768 /* Continuation fragments (no L2CAP header) */
1769 frag = &skb_shinfo(skb)->frag_list;
1770 while (len) {
1771 count = min_t(unsigned int, conn->mtu, len);
1772
1773 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1774 if (!*frag)
1775 goto fail;
1776
1777 memcpy(skb_put(*frag, count), data, count);
1778
1779 len -= count;
1780 data += count;
1781
1782 frag = &(*frag)->next;
1783 }
1784
1785 return skb;
1786
1787fail:
1788 kfree_skb(skb);
1789 return NULL;
1790}
1791
1792static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1793{
1794 struct l2cap_conf_opt *opt = *ptr;
1795 int len;
1796
1797 len = L2CAP_CONF_OPT_SIZE + opt->len;
1798 *ptr += len;
1799
1800 *type = opt->type;
1801 *olen = opt->len;
1802
1803 switch (opt->len) {
1804 case 1:
1805 *val = *((u8 *) opt->val);
1806 break;
1807
1808 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001809 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 break;
1811
1812 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001813 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814 break;
1815
1816 default:
1817 *val = (unsigned long) opt->val;
1818 break;
1819 }
1820
1821 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1822 return len;
1823}
1824
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1826{
1827 struct l2cap_conf_opt *opt = *ptr;
1828
1829 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1830
1831 opt->type = type;
1832 opt->len = len;
1833
1834 switch (len) {
1835 case 1:
1836 *((u8 *) opt->val) = val;
1837 break;
1838
1839 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001840 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 break;
1842
1843 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001844 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 break;
1846
1847 default:
1848 memcpy(opt->val, (void *) val, len);
1849 break;
1850 }
1851
1852 *ptr += L2CAP_CONF_OPT_SIZE + len;
1853}
1854
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001855static void l2cap_ack_timeout(unsigned long arg)
1856{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001857 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001858
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001859 bh_lock_sock(chan->sk);
1860 l2cap_send_ack(chan);
1861 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001862}
1863
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001864static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001865{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001866 struct sock *sk = chan->sk;
1867
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001868 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001869 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001870 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001871 chan->num_acked = 0;
1872 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001873
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001874 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1875 (unsigned long) chan);
1876 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1877 (unsigned long) chan);
1878 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001879
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001880 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001881
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001882 INIT_LIST_HEAD(&chan->srej_l);
1883
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001884
1885 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001886}
1887
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001888static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1889{
1890 switch (mode) {
1891 case L2CAP_MODE_STREAMING:
1892 case L2CAP_MODE_ERTM:
1893 if (l2cap_mode_supported(mode, remote_feat_mask))
1894 return mode;
1895 /* fall through */
1896 default:
1897 return L2CAP_MODE_BASIC;
1898 }
1899}
1900
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03001901static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001904 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905 void *ptr = req->data;
1906
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001907 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001909 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001910 goto done;
1911
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001912 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001913 case L2CAP_MODE_STREAMING:
1914 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001915 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001916 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001917
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001918 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001919 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001920 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001921 break;
1922 }
1923
1924done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001925 if (chan->imtu != L2CAP_DEFAULT_MTU)
1926 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001927
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001928 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001929 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001930 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1931 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001932 break;
1933
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001934 rfc.mode = L2CAP_MODE_BASIC;
1935 rfc.txwin_size = 0;
1936 rfc.max_transmit = 0;
1937 rfc.retrans_timeout = 0;
1938 rfc.monitor_timeout = 0;
1939 rfc.max_pdu_size = 0;
1940
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001941 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1942 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001943 break;
1944
1945 case L2CAP_MODE_ERTM:
1946 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001947 rfc.txwin_size = chan->tx_win;
1948 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001949 rfc.retrans_timeout = 0;
1950 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001951 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001952 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1953 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001954
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001955 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1956 (unsigned long) &rfc);
1957
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001958 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001959 break;
1960
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001961 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001962 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001963 chan->fcs = L2CAP_FCS_NONE;
1964 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001965 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001966 break;
1967
1968 case L2CAP_MODE_STREAMING:
1969 rfc.mode = L2CAP_MODE_STREAMING;
1970 rfc.txwin_size = 0;
1971 rfc.max_transmit = 0;
1972 rfc.retrans_timeout = 0;
1973 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001974 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001975 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1976 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001977
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001978 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1979 (unsigned long) &rfc);
1980
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001981 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001982 break;
1983
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001984 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001985 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001986 chan->fcs = L2CAP_FCS_NONE;
1987 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001988 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001989 break;
1990 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001992 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001993 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994
1995 return ptr - data;
1996}
1997
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001998static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002000 struct l2cap_conf_rsp *rsp = data;
2001 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002002 void *req = chan->conf_req;
2003 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002004 int type, hint, olen;
2005 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002006 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002007 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002008 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002010 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002011
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002012 while (len >= L2CAP_CONF_OPT_SIZE) {
2013 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002015 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002016 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002017
2018 switch (type) {
2019 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002020 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002021 break;
2022
2023 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002024 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002025 break;
2026
2027 case L2CAP_CONF_QOS:
2028 break;
2029
Marcel Holtmann6464f352007-10-20 13:39:51 +02002030 case L2CAP_CONF_RFC:
2031 if (olen == sizeof(rfc))
2032 memcpy(&rfc, (void *) val, olen);
2033 break;
2034
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002035 case L2CAP_CONF_FCS:
2036 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002037 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002038
2039 break;
2040
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002041 default:
2042 if (hint)
2043 break;
2044
2045 result = L2CAP_CONF_UNKNOWN;
2046 *((u8 *) ptr++) = type;
2047 break;
2048 }
2049 }
2050
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002051 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002052 goto done;
2053
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002054 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002055 case L2CAP_MODE_STREAMING:
2056 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002057 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002058 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002059 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002060 break;
2061 }
2062
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002063 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002064 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002065
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002066 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002067 }
2068
2069done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002070 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002071 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002072 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002073
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002074 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002075 return -ECONNREFUSED;
2076
2077 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2078 sizeof(rfc), (unsigned long) &rfc);
2079 }
2080
2081
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002082 if (result == L2CAP_CONF_SUCCESS) {
2083 /* Configure output options and let the other side know
2084 * which ones we don't like. */
2085
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002086 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2087 result = L2CAP_CONF_UNACCEPT;
2088 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002089 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002090 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002091 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002092 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002093
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002094 switch (rfc.mode) {
2095 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002096 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002097 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002098 break;
2099
2100 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002101 chan->remote_tx_win = rfc.txwin_size;
2102 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002103
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002104 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2105 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002106
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002107 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002108
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002109 rfc.retrans_timeout =
2110 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2111 rfc.monitor_timeout =
2112 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002113
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002114 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002115
2116 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2117 sizeof(rfc), (unsigned long) &rfc);
2118
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002119 break;
2120
2121 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002122 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2123 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002124
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002125 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002126
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002127 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002128
2129 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2130 sizeof(rfc), (unsigned long) &rfc);
2131
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002132 break;
2133
2134 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002135 result = L2CAP_CONF_UNACCEPT;
2136
2137 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002138 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002139 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002140
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002141 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002142 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002143 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002144 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002145 rsp->result = cpu_to_le16(result);
2146 rsp->flags = cpu_to_le16(0x0000);
2147
2148 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149}
2150
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002151static 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 -03002152{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002153 struct l2cap_conf_req *req = data;
2154 void *ptr = req->data;
2155 int type, olen;
2156 unsigned long val;
2157 struct l2cap_conf_rfc rfc;
2158
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002159 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002160
2161 while (len >= L2CAP_CONF_OPT_SIZE) {
2162 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2163
2164 switch (type) {
2165 case L2CAP_CONF_MTU:
2166 if (val < L2CAP_DEFAULT_MIN_MTU) {
2167 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002168 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002169 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002170 chan->imtu = val;
2171 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002172 break;
2173
2174 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002175 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002176 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002177 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002178 break;
2179
2180 case L2CAP_CONF_RFC:
2181 if (olen == sizeof(rfc))
2182 memcpy(&rfc, (void *)val, olen);
2183
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002184 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002185 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002186 return -ECONNREFUSED;
2187
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002188 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002189
2190 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2191 sizeof(rfc), (unsigned long) &rfc);
2192 break;
2193 }
2194 }
2195
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002196 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002197 return -ECONNREFUSED;
2198
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002199 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002200
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002201 if (*result == L2CAP_CONF_SUCCESS) {
2202 switch (rfc.mode) {
2203 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002204 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2205 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2206 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002207 break;
2208 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002209 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002210 }
2211 }
2212
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002213 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002214 req->flags = cpu_to_le16(0x0000);
2215
2216 return ptr - data;
2217}
2218
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002219static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220{
2221 struct l2cap_conf_rsp *rsp = data;
2222 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002224 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002226 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002227 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002228 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229
2230 return ptr - data;
2231}
2232
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002233void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002234{
2235 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002236 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002237 u8 buf[128];
2238
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002239 rsp.scid = cpu_to_le16(chan->dcid);
2240 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002241 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2242 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2243 l2cap_send_cmd(conn, chan->ident,
2244 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2245
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002246 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002247 return;
2248
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002249 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2250 l2cap_build_conf_req(chan, buf), buf);
2251 chan->num_conf_req++;
2252}
2253
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002254static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002255{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002256 int type, olen;
2257 unsigned long val;
2258 struct l2cap_conf_rfc rfc;
2259
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002260 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002261
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002262 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002263 return;
2264
2265 while (len >= L2CAP_CONF_OPT_SIZE) {
2266 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2267
2268 switch (type) {
2269 case L2CAP_CONF_RFC:
2270 if (olen == sizeof(rfc))
2271 memcpy(&rfc, (void *)val, olen);
2272 goto done;
2273 }
2274 }
2275
2276done:
2277 switch (rfc.mode) {
2278 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002279 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2280 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2281 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002282 break;
2283 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002284 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002285 }
2286}
2287
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002288static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2289{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002290 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002291
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002292 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002293 return 0;
2294
2295 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2296 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002297 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002298
2299 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002300 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002301
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002302 l2cap_conn_start(conn);
2303 }
2304
2305 return 0;
2306}
2307
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2309{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2311 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002312 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002313 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002314 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315
2316 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002317 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318
2319 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2320
2321 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002322 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2323 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 result = L2CAP_CR_BAD_PSM;
2325 goto sendresp;
2326 }
2327
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002328 parent = pchan->sk;
2329
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002330 bh_lock_sock(parent);
2331
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002332 /* Check if the ACL is secure enough (if not SDP) */
2333 if (psm != cpu_to_le16(0x0001) &&
2334 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002335 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002336 result = L2CAP_CR_SEC_BLOCK;
2337 goto response;
2338 }
2339
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 result = L2CAP_CR_NO_MEM;
2341
2342 /* Check for backlog size */
2343 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002344 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345 goto response;
2346 }
2347
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002348 chan = pchan->ops->new_connection(pchan->data);
2349 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 goto response;
2351
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002352 sk = chan->sk;
2353
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002354 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355
2356 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002357 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2358 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002360 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 goto response;
2362 }
2363
2364 hci_conn_hold(conn->hcon);
2365
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 bacpy(&bt_sk(sk)->src, conn->src);
2367 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002368 chan->psm = psm;
2369 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002371 bt_accept_enqueue(parent, sk);
2372
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002373 __l2cap_chan_add(conn, chan);
2374
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002375 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002377 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002379 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380
Marcel Holtmann984947d2009-02-06 23:35:19 +01002381 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002382 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002383 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002384 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002385 result = L2CAP_CR_PEND;
2386 status = L2CAP_CS_AUTHOR_PEND;
2387 parent->sk_data_ready(parent, 0);
2388 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002389 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002390 result = L2CAP_CR_SUCCESS;
2391 status = L2CAP_CS_NO_INFO;
2392 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002393 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002394 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002395 result = L2CAP_CR_PEND;
2396 status = L2CAP_CS_AUTHEN_PEND;
2397 }
2398 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002399 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002400 result = L2CAP_CR_PEND;
2401 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 }
2403
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002404 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405
2406response:
2407 bh_unlock_sock(parent);
2408
2409sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002410 rsp.scid = cpu_to_le16(scid);
2411 rsp.dcid = cpu_to_le16(dcid);
2412 rsp.result = cpu_to_le16(result);
2413 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002415
2416 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2417 struct l2cap_info_req info;
2418 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2419
2420 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2421 conn->info_ident = l2cap_get_ident(conn);
2422
2423 mod_timer(&conn->info_timer, jiffies +
2424 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2425
2426 l2cap_send_cmd(conn, conn->info_ident,
2427 L2CAP_INFO_REQ, sizeof(info), &info);
2428 }
2429
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002430 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002431 result == L2CAP_CR_SUCCESS) {
2432 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002433 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002434 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002435 l2cap_build_conf_req(chan, buf), buf);
2436 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002437 }
2438
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439 return 0;
2440}
2441
2442static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2443{
2444 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2445 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002446 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 struct sock *sk;
2448 u8 req[128];
2449
2450 scid = __le16_to_cpu(rsp->scid);
2451 dcid = __le16_to_cpu(rsp->dcid);
2452 result = __le16_to_cpu(rsp->result);
2453 status = __le16_to_cpu(rsp->status);
2454
2455 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2456
2457 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002458 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002459 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002460 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002462 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002463 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002464 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465 }
2466
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002467 sk = chan->sk;
2468
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 switch (result) {
2470 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002471 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002472 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002473 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002474 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002475
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002476 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002477 break;
2478
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002480 l2cap_build_conf_req(chan, req), req);
2481 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482 break;
2483
2484 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002485 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486 break;
2487
2488 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002489 /* don't delete l2cap channel if sk is owned by user */
2490 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002491 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002492 __clear_chan_timer(chan);
2493 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002494 break;
2495 }
2496
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002497 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 break;
2499 }
2500
2501 bh_unlock_sock(sk);
2502 return 0;
2503}
2504
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002505static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002506{
2507 /* FCS is enabled only in ERTM or streaming mode, if one or both
2508 * sides request it.
2509 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002510 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002511 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002512 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002513 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002514}
2515
Al Viro88219a02007-07-29 00:17:25 -07002516static 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 -07002517{
2518 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2519 u16 dcid, flags;
2520 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002521 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002523 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524
2525 dcid = __le16_to_cpu(req->dcid);
2526 flags = __le16_to_cpu(req->flags);
2527
2528 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2529
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002530 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002531 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532 return -ENOENT;
2533
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002534 sk = chan->sk;
2535
David S. Miller033b1142011-07-21 13:38:42 -07002536 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002537 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002538
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002539 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2540 rej.scid = cpu_to_le16(chan->scid);
2541 rej.dcid = cpu_to_le16(chan->dcid);
2542
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002543 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2544 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002545 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002546 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002547
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002548 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002549 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002550 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002551 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002552 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002553 L2CAP_CONF_REJECT, flags), rsp);
2554 goto unlock;
2555 }
2556
2557 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002558 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2559 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560
2561 if (flags & 0x0001) {
2562 /* Incomplete config. Send empty response. */
2563 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002564 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002565 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566 goto unlock;
2567 }
2568
2569 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002570 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002571 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002572 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002574 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002576 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002577 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002578
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002579 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002580 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002581
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002582 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002583 goto unlock;
2584
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002585 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002586 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002587
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002588 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002589
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002590 chan->next_tx_seq = 0;
2591 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002592 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002593 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002594 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002595
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002597 goto unlock;
2598 }
2599
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002600 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002601 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002603 l2cap_build_conf_req(chan, buf), buf);
2604 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605 }
2606
2607unlock:
2608 bh_unlock_sock(sk);
2609 return 0;
2610}
2611
2612static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2613{
2614 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2615 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002616 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002618 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619
2620 scid = __le16_to_cpu(rsp->scid);
2621 flags = __le16_to_cpu(rsp->flags);
2622 result = __le16_to_cpu(rsp->result);
2623
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002624 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2625 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002627 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002628 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629 return 0;
2630
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002631 sk = chan->sk;
2632
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633 switch (result) {
2634 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002635 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 break;
2637
2638 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002639 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002640 char req[64];
2641
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002642 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002643 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002644 goto done;
2645 }
2646
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002647 /* throw out any old stored conf requests */
2648 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002649 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2650 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002651 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002652 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002653 goto done;
2654 }
2655
2656 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2657 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002658 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002659 if (result != L2CAP_CONF_SUCCESS)
2660 goto done;
2661 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 }
2663
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002664 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002665 sk->sk_err = ECONNRESET;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002666 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002667 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668 goto done;
2669 }
2670
2671 if (flags & 0x01)
2672 goto done;
2673
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002674 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002676 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002677 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002678
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002679 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002680 chan->next_tx_seq = 0;
2681 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002682 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002683 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002684 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002685
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686 l2cap_chan_ready(sk);
2687 }
2688
2689done:
2690 bh_unlock_sock(sk);
2691 return 0;
2692}
2693
2694static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2695{
2696 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2697 struct l2cap_disconn_rsp rsp;
2698 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002699 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 struct sock *sk;
2701
2702 scid = __le16_to_cpu(req->scid);
2703 dcid = __le16_to_cpu(req->dcid);
2704
2705 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2706
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002707 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002708 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 return 0;
2710
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002711 sk = chan->sk;
2712
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002713 rsp.dcid = cpu_to_le16(chan->scid);
2714 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2716
2717 sk->sk_shutdown = SHUTDOWN_MASK;
2718
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002719 /* don't delete l2cap channel if sk is owned by user */
2720 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002721 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002722 __clear_chan_timer(chan);
2723 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002724 bh_unlock_sock(sk);
2725 return 0;
2726 }
2727
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002728 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729 bh_unlock_sock(sk);
2730
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002731 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732 return 0;
2733}
2734
2735static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2736{
2737 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2738 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002739 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 struct sock *sk;
2741
2742 scid = __le16_to_cpu(rsp->scid);
2743 dcid = __le16_to_cpu(rsp->dcid);
2744
2745 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2746
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002747 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002748 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749 return 0;
2750
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002751 sk = chan->sk;
2752
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002753 /* don't delete l2cap channel if sk is owned by user */
2754 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002755 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002756 __clear_chan_timer(chan);
2757 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002758 bh_unlock_sock(sk);
2759 return 0;
2760 }
2761
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002762 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 bh_unlock_sock(sk);
2764
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002765 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 return 0;
2767}
2768
2769static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2770{
2771 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772 u16 type;
2773
2774 type = __le16_to_cpu(req->type);
2775
2776 BT_DBG("type 0x%4.4x", type);
2777
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002778 if (type == L2CAP_IT_FEAT_MASK) {
2779 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002780 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002781 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2782 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2783 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002784 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002785 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2786 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03002787 if (enable_hs)
2788 feat_mask |= L2CAP_FEAT_EXT_FLOW;
2789
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002790 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002791 l2cap_send_cmd(conn, cmd->ident,
2792 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002793 } else if (type == L2CAP_IT_FIXED_CHAN) {
2794 u8 buf[12];
2795 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2796 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2797 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2798 memcpy(buf + 4, l2cap_fixed_chan, 8);
2799 l2cap_send_cmd(conn, cmd->ident,
2800 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002801 } else {
2802 struct l2cap_info_rsp rsp;
2803 rsp.type = cpu_to_le16(type);
2804 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2805 l2cap_send_cmd(conn, cmd->ident,
2806 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2807 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808
2809 return 0;
2810}
2811
2812static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2813{
2814 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2815 u16 type, result;
2816
2817 type = __le16_to_cpu(rsp->type);
2818 result = __le16_to_cpu(rsp->result);
2819
2820 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2821
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002822 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2823 if (cmd->ident != conn->info_ident ||
2824 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2825 return 0;
2826
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002827 del_timer(&conn->info_timer);
2828
Ville Tervoadb08ed2010-08-04 09:43:33 +03002829 if (result != L2CAP_IR_SUCCESS) {
2830 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2831 conn->info_ident = 0;
2832
2833 l2cap_conn_start(conn);
2834
2835 return 0;
2836 }
2837
Marcel Holtmann984947d2009-02-06 23:35:19 +01002838 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002839 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002840
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002841 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002842 struct l2cap_info_req req;
2843 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2844
2845 conn->info_ident = l2cap_get_ident(conn);
2846
2847 l2cap_send_cmd(conn, conn->info_ident,
2848 L2CAP_INFO_REQ, sizeof(req), &req);
2849 } else {
2850 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2851 conn->info_ident = 0;
2852
2853 l2cap_conn_start(conn);
2854 }
2855 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002856 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002857 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002858
2859 l2cap_conn_start(conn);
2860 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002861
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 return 0;
2863}
2864
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002865static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002866 u16 to_multiplier)
2867{
2868 u16 max_latency;
2869
2870 if (min > max || min < 6 || max > 3200)
2871 return -EINVAL;
2872
2873 if (to_multiplier < 10 || to_multiplier > 3200)
2874 return -EINVAL;
2875
2876 if (max >= to_multiplier * 8)
2877 return -EINVAL;
2878
2879 max_latency = (to_multiplier * 8 / max) - 1;
2880 if (latency > 499 || latency > max_latency)
2881 return -EINVAL;
2882
2883 return 0;
2884}
2885
2886static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2887 struct l2cap_cmd_hdr *cmd, u8 *data)
2888{
2889 struct hci_conn *hcon = conn->hcon;
2890 struct l2cap_conn_param_update_req *req;
2891 struct l2cap_conn_param_update_rsp rsp;
2892 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002893 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002894
2895 if (!(hcon->link_mode & HCI_LM_MASTER))
2896 return -EINVAL;
2897
2898 cmd_len = __le16_to_cpu(cmd->len);
2899 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2900 return -EPROTO;
2901
2902 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002903 min = __le16_to_cpu(req->min);
2904 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002905 latency = __le16_to_cpu(req->latency);
2906 to_multiplier = __le16_to_cpu(req->to_multiplier);
2907
2908 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2909 min, max, latency, to_multiplier);
2910
2911 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002912
2913 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2914 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002915 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2916 else
2917 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2918
2919 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2920 sizeof(rsp), &rsp);
2921
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002922 if (!err)
2923 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2924
Claudio Takahaside731152011-02-11 19:28:55 -02002925 return 0;
2926}
2927
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002928static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2929 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2930{
2931 int err = 0;
2932
2933 switch (cmd->code) {
2934 case L2CAP_COMMAND_REJ:
2935 l2cap_command_rej(conn, cmd, data);
2936 break;
2937
2938 case L2CAP_CONN_REQ:
2939 err = l2cap_connect_req(conn, cmd, data);
2940 break;
2941
2942 case L2CAP_CONN_RSP:
2943 err = l2cap_connect_rsp(conn, cmd, data);
2944 break;
2945
2946 case L2CAP_CONF_REQ:
2947 err = l2cap_config_req(conn, cmd, cmd_len, data);
2948 break;
2949
2950 case L2CAP_CONF_RSP:
2951 err = l2cap_config_rsp(conn, cmd, data);
2952 break;
2953
2954 case L2CAP_DISCONN_REQ:
2955 err = l2cap_disconnect_req(conn, cmd, data);
2956 break;
2957
2958 case L2CAP_DISCONN_RSP:
2959 err = l2cap_disconnect_rsp(conn, cmd, data);
2960 break;
2961
2962 case L2CAP_ECHO_REQ:
2963 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2964 break;
2965
2966 case L2CAP_ECHO_RSP:
2967 break;
2968
2969 case L2CAP_INFO_REQ:
2970 err = l2cap_information_req(conn, cmd, data);
2971 break;
2972
2973 case L2CAP_INFO_RSP:
2974 err = l2cap_information_rsp(conn, cmd, data);
2975 break;
2976
2977 default:
2978 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2979 err = -EINVAL;
2980 break;
2981 }
2982
2983 return err;
2984}
2985
2986static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2987 struct l2cap_cmd_hdr *cmd, u8 *data)
2988{
2989 switch (cmd->code) {
2990 case L2CAP_COMMAND_REJ:
2991 return 0;
2992
2993 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002994 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002995
2996 case L2CAP_CONN_PARAM_UPDATE_RSP:
2997 return 0;
2998
2999 default:
3000 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3001 return -EINVAL;
3002 }
3003}
3004
3005static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3006 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007{
3008 u8 *data = skb->data;
3009 int len = skb->len;
3010 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003011 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012
3013 l2cap_raw_recv(conn, skb);
3014
3015 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003016 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3018 data += L2CAP_CMD_HDR_SIZE;
3019 len -= L2CAP_CMD_HDR_SIZE;
3020
Al Viro88219a02007-07-29 00:17:25 -07003021 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022
Al Viro88219a02007-07-29 00:17:25 -07003023 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 -07003024
Al Viro88219a02007-07-29 00:17:25 -07003025 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026 BT_DBG("corrupted command");
3027 break;
3028 }
3029
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003030 if (conn->hcon->type == LE_LINK)
3031 err = l2cap_le_sig_cmd(conn, &cmd, data);
3032 else
3033 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034
3035 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003036 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003037
3038 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039
3040 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003041 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003042 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3043 }
3044
Al Viro88219a02007-07-29 00:17:25 -07003045 data += cmd_len;
3046 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047 }
3048
3049 kfree_skb(skb);
3050}
3051
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003052static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003053{
3054 u16 our_fcs, rcv_fcs;
3055 int hdr_size = L2CAP_HDR_SIZE + 2;
3056
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003057 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003058 skb_trim(skb, skb->len - 2);
3059 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3060 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3061
3062 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003063 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003064 }
3065 return 0;
3066}
3067
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003068static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003069{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003070 u16 control = 0;
3071
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003072 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003073
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003074 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003075
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003076 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003077 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003078 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003079 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003080 }
3081
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003082 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003083 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003084
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003085 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003086
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003087 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003088 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003089 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003090 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003091 }
3092}
3093
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003094static 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 -03003095{
3096 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003097 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003098
3099 bt_cb(skb)->tx_seq = tx_seq;
3100 bt_cb(skb)->sar = sar;
3101
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003102 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003103 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003104 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003105 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003106 }
3107
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003108 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003109 if (tx_seq_offset < 0)
3110 tx_seq_offset += 64;
3111
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003112 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003113 if (bt_cb(next_skb)->tx_seq == tx_seq)
3114 return -EINVAL;
3115
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003116 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003117 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003118 if (next_tx_seq_offset < 0)
3119 next_tx_seq_offset += 64;
3120
3121 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003122 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003123 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003124 }
3125
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003126 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003127 break;
3128
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003129 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003130
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003131 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003132
3133 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003134}
3135
Mat Martineau84084a32011-07-22 14:54:00 -07003136static void append_skb_frag(struct sk_buff *skb,
3137 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003138{
Mat Martineau84084a32011-07-22 14:54:00 -07003139 /* skb->len reflects data in skb as well as all fragments
3140 * skb->data_len reflects only data in fragments
3141 */
3142 if (!skb_has_frag_list(skb))
3143 skb_shinfo(skb)->frag_list = new_frag;
3144
3145 new_frag->next = NULL;
3146
3147 (*last_frag)->next = new_frag;
3148 *last_frag = new_frag;
3149
3150 skb->len += new_frag->len;
3151 skb->data_len += new_frag->len;
3152 skb->truesize += new_frag->truesize;
3153}
3154
3155static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
3156{
3157 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003158
3159 switch (control & L2CAP_CTRL_SAR) {
3160 case L2CAP_SDU_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003161 if (chan->sdu)
3162 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003163
Mat Martineau84084a32011-07-22 14:54:00 -07003164 err = chan->ops->recv(chan->data, skb);
3165 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003166
3167 case L2CAP_SDU_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003168 if (chan->sdu)
3169 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003170
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003171 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003172 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003173
Mat Martineau84084a32011-07-22 14:54:00 -07003174 if (chan->sdu_len > chan->imtu) {
3175 err = -EMSGSIZE;
3176 break;
3177 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003178
Mat Martineau84084a32011-07-22 14:54:00 -07003179 if (skb->len >= chan->sdu_len)
3180 break;
3181
3182 chan->sdu = skb;
3183 chan->sdu_last_frag = skb;
3184
3185 skb = NULL;
3186 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003187 break;
3188
3189 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003190 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003191 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003192
Mat Martineau84084a32011-07-22 14:54:00 -07003193 append_skb_frag(chan->sdu, skb,
3194 &chan->sdu_last_frag);
3195 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003196
Mat Martineau84084a32011-07-22 14:54:00 -07003197 if (chan->sdu->len >= chan->sdu_len)
3198 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003199
Mat Martineau84084a32011-07-22 14:54:00 -07003200 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003201 break;
3202
3203 case L2CAP_SDU_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003204 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003205 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003206
Mat Martineau84084a32011-07-22 14:54:00 -07003207 append_skb_frag(chan->sdu, skb,
3208 &chan->sdu_last_frag);
3209 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003210
Mat Martineau84084a32011-07-22 14:54:00 -07003211 if (chan->sdu->len != chan->sdu_len)
3212 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003213
Mat Martineau84084a32011-07-22 14:54:00 -07003214 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003215
Mat Martineau84084a32011-07-22 14:54:00 -07003216 if (!err) {
3217 /* Reassembly complete */
3218 chan->sdu = NULL;
3219 chan->sdu_last_frag = NULL;
3220 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003221 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003222 break;
3223 }
3224
Mat Martineau84084a32011-07-22 14:54:00 -07003225 if (err) {
3226 kfree_skb(skb);
3227 kfree_skb(chan->sdu);
3228 chan->sdu = NULL;
3229 chan->sdu_last_frag = NULL;
3230 chan->sdu_len = 0;
3231 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003232
Mat Martineau84084a32011-07-22 14:54:00 -07003233 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003234}
3235
Mat Martineau26f880d2011-07-07 09:39:01 -07003236static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003237{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003238 u16 control;
3239
Mat Martineau26f880d2011-07-07 09:39:01 -07003240 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003241
Mat Martineau26f880d2011-07-07 09:39:01 -07003242 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3243
3244 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3245 control |= L2CAP_SUPER_RCV_NOT_READY;
3246 l2cap_send_sframe(chan, control);
3247
3248 set_bit(CONN_RNR_SENT, &chan->conn_state);
3249
3250 __clear_ack_timer(chan);
3251}
3252
3253static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3254{
3255 u16 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003256
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003257 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003258 goto done;
3259
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003260 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003261 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003262 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003263 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003264
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003265 __clear_retrans_timer(chan);
3266 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003267
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003268 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003269
3270done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003271 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3272 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003273
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003274 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003275}
3276
Mat Martineaue3281402011-07-07 09:39:02 -07003277void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003278{
Mat Martineaue3281402011-07-07 09:39:02 -07003279 if (chan->mode == L2CAP_MODE_ERTM) {
3280 if (busy)
3281 l2cap_ertm_enter_local_busy(chan);
3282 else
3283 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003284 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003285}
3286
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003287static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003288{
3289 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003290 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003291
Mat Martineaue3281402011-07-07 09:39:02 -07003292 while ((skb = skb_peek(&chan->srej_q)) &&
3293 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3294 int err;
3295
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003296 if (bt_cb(skb)->tx_seq != tx_seq)
3297 break;
3298
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003299 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003300 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Mat Martineau84084a32011-07-22 14:54:00 -07003301 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003302
3303 if (err < 0) {
3304 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3305 break;
3306 }
3307
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003308 chan->buffer_seq_srej =
3309 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003310 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003311 }
3312}
3313
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003314static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003315{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003316 struct srej_list *l, *tmp;
3317 u16 control;
3318
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003319 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003320 if (l->tx_seq == tx_seq) {
3321 list_del(&l->list);
3322 kfree(l);
3323 return;
3324 }
3325 control = L2CAP_SUPER_SELECT_REJECT;
3326 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003327 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003328 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003329 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003330 }
3331}
3332
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003333static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003334{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003335 struct srej_list *new;
3336 u16 control;
3337
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003338 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003339 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003340 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003341 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003342
3343 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003344 new->tx_seq = chan->expected_tx_seq;
3345 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003346 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003347 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003348 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003349}
3350
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003351static 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 -03003352{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003353 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003354 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003355 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003356 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003357 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003358 int err = 0;
3359
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003360 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3361 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003362
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003363 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003364 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003365 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003366 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003367 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003368 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003369 }
3370
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003371 chan->expected_ack_seq = req_seq;
3372 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003373
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003374 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003375 if (tx_seq_offset < 0)
3376 tx_seq_offset += 64;
3377
3378 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003379 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003380 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003381 goto drop;
3382 }
3383
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003384 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003385 goto drop;
3386
Mat Martineau02f1b642011-06-29 14:35:19 -07003387 if (tx_seq == chan->expected_tx_seq)
3388 goto expected;
3389
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003390 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003391 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003392
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003393 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003394 struct srej_list, list);
3395 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003396 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003397 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003398
3399 list_del(&first->list);
3400 kfree(first);
3401
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003402 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003403 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003404 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003405 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003406 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003407 }
3408 } else {
3409 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003410
3411 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003412 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003413 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003414
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003415 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003416 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003417 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003418 return 0;
3419 }
3420 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003421 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003422 }
3423 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003424 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003425 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003426 if (expected_tx_seq_offset < 0)
3427 expected_tx_seq_offset += 64;
3428
3429 /* duplicated tx_seq */
3430 if (tx_seq_offset < expected_tx_seq_offset)
3431 goto drop;
3432
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003433 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003434
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003435 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003436
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003437 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003438 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003439
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003440 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003441 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003442
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003443 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003444
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003445 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003446
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003447 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003448 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003449 return 0;
3450
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003451expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003452 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003453
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003454 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003455 bt_cb(skb)->tx_seq = tx_seq;
3456 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003457 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003458 return 0;
3459 }
3460
Mat Martineau84084a32011-07-22 14:54:00 -07003461 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Mat Martineaufadd1922011-07-07 09:39:03 -07003462 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Mat Martineaue3281402011-07-07 09:39:02 -07003463 if (err < 0) {
3464 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3465 return err;
3466 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003467
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003468 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003469 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003470 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003471 }
3472
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003473 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003474
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003475 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3476 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003477 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003478
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003479 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003480
3481drop:
3482 kfree_skb(skb);
3483 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003484}
3485
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003486static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003487{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003488 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003489 rx_control);
3490
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003491 chan->expected_ack_seq = __get_reqseq(rx_control);
3492 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003493
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003494 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003495 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3496 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3497 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003498 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003499 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003500
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003501 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003502 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003503 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003504 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003505 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003506
3507 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003508 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003509
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003510 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003511 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003512
3513 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003514 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003515 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003516 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003517
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003518 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3519 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003520 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003521 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003522 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003523 }
3524}
3525
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003526static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003527{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003528 u8 tx_seq = __get_reqseq(rx_control);
3529
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003530 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003531
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003532 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003533
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003534 chan->expected_ack_seq = tx_seq;
3535 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003536
3537 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003538 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003539 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003540 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003541 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003542
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003543 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3544 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003545 }
3546}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003547static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003548{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003549 u8 tx_seq = __get_reqseq(rx_control);
3550
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003551 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003552
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003553 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003554
3555 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003556 chan->expected_ack_seq = tx_seq;
3557 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003558
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003559 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003560 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003561
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003562 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003563
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003564 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003565 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003566 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003567 }
3568 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003569 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003570 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003571 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003572 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003573 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003574 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003575 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003576 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003577 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003578 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003579 }
3580 }
3581}
3582
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003583static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003584{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003585 u8 tx_seq = __get_reqseq(rx_control);
3586
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003587 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003588
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003589 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003590 chan->expected_ack_seq = tx_seq;
3591 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003592
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003593 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003594 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003595
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003596 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003597 __clear_retrans_timer(chan);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003598 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003599 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003600 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003601 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003602
3603 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003604 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003605 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003606 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003607}
3608
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003609static 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 -03003610{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003611 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003612
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003613 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003614 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003615 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003616 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003617 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003618 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003619 }
3620
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003621 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3622 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003623 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003624 break;
3625
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003626 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003627 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003628 break;
3629
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003630 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003631 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003632 break;
3633
3634 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003635 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003636 break;
3637 }
3638
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003639 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003640 return 0;
3641}
3642
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003643static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3644{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003645 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003646 u16 control;
3647 u8 req_seq;
3648 int len, next_tx_seq_offset, req_seq_offset;
3649
3650 control = get_unaligned_le16(skb->data);
3651 skb_pull(skb, 2);
3652 len = skb->len;
3653
3654 /*
3655 * We can just drop the corrupted I-frame here.
3656 * Receiver will miss it and start proper recovery
3657 * procedures and ask retransmission.
3658 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003659 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003660 goto drop;
3661
3662 if (__is_sar_start(control) && __is_iframe(control))
3663 len -= 2;
3664
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003665 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003666 len -= 2;
3667
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003668 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003669 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003670 goto drop;
3671 }
3672
3673 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003674 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003675 if (req_seq_offset < 0)
3676 req_seq_offset += 64;
3677
3678 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003679 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003680 if (next_tx_seq_offset < 0)
3681 next_tx_seq_offset += 64;
3682
3683 /* check for invalid req-seq */
3684 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003685 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003686 goto drop;
3687 }
3688
3689 if (__is_iframe(control)) {
3690 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003691 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003692 goto drop;
3693 }
3694
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003695 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003696 } else {
3697 if (len != 0) {
3698 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003699 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003700 goto drop;
3701 }
3702
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003703 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003704 }
3705
3706 return 0;
3707
3708drop:
3709 kfree_skb(skb);
3710 return 0;
3711}
3712
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3714{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003715 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003716 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003717 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003718 u8 tx_seq;
3719 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003721 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003722 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723 BT_DBG("unknown cid 0x%4.4x", cid);
3724 goto drop;
3725 }
3726
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003727 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003728
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003729 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003731 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003732 goto drop;
3733
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003734 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003735 case L2CAP_MODE_BASIC:
3736 /* If socket recv buffers overflows we drop data here
3737 * which is *bad* because L2CAP has to be reliable.
3738 * But we don't have any other choice. L2CAP doesn't
3739 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003741 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003742 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003744 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003745 goto done;
3746 break;
3747
3748 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003749 if (!sock_owned_by_user(sk)) {
3750 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003751 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003752 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003753 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003754 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003755
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003756 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003757
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003758 case L2CAP_MODE_STREAMING:
3759 control = get_unaligned_le16(skb->data);
3760 skb_pull(skb, 2);
3761 len = skb->len;
3762
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003763 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003764 goto drop;
3765
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003766 if (__is_sar_start(control))
3767 len -= 2;
3768
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003769 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003770 len -= 2;
3771
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003772 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003773 goto drop;
3774
3775 tx_seq = __get_txseq(control);
3776
Mat Martineau84084a32011-07-22 14:54:00 -07003777 if (chan->expected_tx_seq != tx_seq) {
3778 /* Frame(s) missing - must discard partial SDU */
3779 kfree_skb(chan->sdu);
3780 chan->sdu = NULL;
3781 chan->sdu_last_frag = NULL;
3782 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003783
Mat Martineau84084a32011-07-22 14:54:00 -07003784 /* TODO: Notify userland of missing data */
3785 }
3786
3787 chan->expected_tx_seq = (tx_seq + 1) % 64;
3788
3789 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
3790 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003791
3792 goto done;
3793
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003794 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003795 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003796 break;
3797 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798
3799drop:
3800 kfree_skb(skb);
3801
3802done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003803 if (sk)
3804 bh_unlock_sock(sk);
3805
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806 return 0;
3807}
3808
Al Viro8e036fc2007-07-29 00:16:36 -07003809static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003811 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003812 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003814 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3815 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816 goto drop;
3817
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003818 sk = chan->sk;
3819
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003820 bh_lock_sock(sk);
3821
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822 BT_DBG("sk %p, len %d", sk, skb->len);
3823
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003824 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003825 goto drop;
3826
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003827 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828 goto drop;
3829
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003830 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831 goto done;
3832
3833drop:
3834 kfree_skb(skb);
3835
3836done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003837 if (sk)
3838 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839 return 0;
3840}
3841
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003842static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3843{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003844 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003845 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003846
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003847 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3848 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003849 goto drop;
3850
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003851 sk = chan->sk;
3852
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003853 bh_lock_sock(sk);
3854
3855 BT_DBG("sk %p, len %d", sk, skb->len);
3856
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003857 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003858 goto drop;
3859
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003860 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003861 goto drop;
3862
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003863 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003864 goto done;
3865
3866drop:
3867 kfree_skb(skb);
3868
3869done:
3870 if (sk)
3871 bh_unlock_sock(sk);
3872 return 0;
3873}
3874
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3876{
3877 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003878 u16 cid, len;
3879 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880
3881 skb_pull(skb, L2CAP_HDR_SIZE);
3882 cid = __le16_to_cpu(lh->cid);
3883 len = __le16_to_cpu(lh->len);
3884
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003885 if (len != skb->len) {
3886 kfree_skb(skb);
3887 return;
3888 }
3889
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3891
3892 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003893 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003894 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895 l2cap_sig_channel(conn, skb);
3896 break;
3897
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003898 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003899 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003900 skb_pull(skb, 2);
3901 l2cap_conless_channel(conn, psm, skb);
3902 break;
3903
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003904 case L2CAP_CID_LE_DATA:
3905 l2cap_att_channel(conn, cid, skb);
3906 break;
3907
Anderson Brigliab501d6a2011-06-07 18:46:31 -03003908 case L2CAP_CID_SMP:
3909 if (smp_sig_channel(conn, skb))
3910 l2cap_conn_del(conn->hcon, EACCES);
3911 break;
3912
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913 default:
3914 l2cap_data_channel(conn, cid, skb);
3915 break;
3916 }
3917}
3918
3919/* ---- L2CAP interface with lower layer (HCI) ---- */
3920
3921static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3922{
3923 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003924 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003925
3926 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003927 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928
3929 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3930
3931 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003932 read_lock(&chan_list_lock);
3933 list_for_each_entry(c, &chan_list, global_l) {
3934 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003935
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003936 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937 continue;
3938
3939 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003940 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03003941 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003942 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003944 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3945 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03003946 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003947 lm2 |= HCI_LM_MASTER;
3948 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003950 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951
3952 return exact ? lm1 : lm2;
3953}
3954
3955static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3956{
Marcel Holtmann01394182006-07-03 10:02:46 +02003957 struct l2cap_conn *conn;
3958
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3960
Ville Tervoacd7d372011-02-10 22:38:49 -03003961 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003962 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963
3964 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965 conn = l2cap_conn_add(hcon, status);
3966 if (conn)
3967 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003968 } else
Joe Perchese1750722011-06-29 18:18:29 -07003969 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970
3971 return 0;
3972}
3973
Marcel Holtmann2950f212009-02-12 14:02:50 +01003974static int l2cap_disconn_ind(struct hci_conn *hcon)
3975{
3976 struct l2cap_conn *conn = hcon->l2cap_data;
3977
3978 BT_DBG("hcon %p", hcon);
3979
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03003980 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01003981 return 0x13;
3982
3983 return conn->disc_reason;
3984}
3985
3986static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987{
3988 BT_DBG("hcon %p reason %d", hcon, reason);
3989
Ville Tervoacd7d372011-02-10 22:38:49 -03003990 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003991 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992
Joe Perchese1750722011-06-29 18:18:29 -07003993 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003994
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995 return 0;
3996}
3997
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003998static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003999{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004000 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004001 return;
4002
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004003 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004004 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004005 __clear_chan_timer(chan);
4006 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004007 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004008 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004009 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004010 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004011 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004012 }
4013}
4014
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004015static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004017 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004018 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019
Marcel Holtmann01394182006-07-03 10:02:46 +02004020 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004022
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023 BT_DBG("conn %p", conn);
4024
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004025 if (hcon->type == LE_LINK) {
4026 smp_distribute_keys(conn, 0);
4027 del_timer(&conn->security_timer);
4028 }
4029
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004030 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004032 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004033 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004034
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035 bh_lock_sock(sk);
4036
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004037 BT_DBG("chan->scid %d", chan->scid);
4038
4039 if (chan->scid == L2CAP_CID_LE_DATA) {
4040 if (!status && encrypt) {
4041 chan->sec_level = hcon->sec_level;
4042 l2cap_chan_ready(sk);
4043 }
4044
4045 bh_unlock_sock(sk);
4046 continue;
4047 }
4048
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004049 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004050 bh_unlock_sock(sk);
4051 continue;
4052 }
4053
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004054 if (!status && (chan->state == BT_CONNECTED ||
4055 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004056 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004057 bh_unlock_sock(sk);
4058 continue;
4059 }
4060
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004061 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004062 if (!status) {
4063 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004064 req.scid = cpu_to_le16(chan->scid);
4065 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004066
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004067 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004068 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004069
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004070 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004071 L2CAP_CONN_REQ, sizeof(req), &req);
4072 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004073 __clear_chan_timer(chan);
4074 __set_chan_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004075 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004076 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004077 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004078 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004079
4080 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004081 if (bt_sk(sk)->defer_setup) {
4082 struct sock *parent = bt_sk(sk)->parent;
4083 res = L2CAP_CR_PEND;
4084 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004085 if (parent)
4086 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004087 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004088 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004089 res = L2CAP_CR_SUCCESS;
4090 stat = L2CAP_CS_NO_INFO;
4091 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004092 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004093 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004094 __set_chan_timer(chan, HZ / 10);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004095 res = L2CAP_CR_SEC_BLOCK;
4096 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004097 }
4098
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004099 rsp.scid = cpu_to_le16(chan->dcid);
4100 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004101 rsp.result = cpu_to_le16(res);
4102 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004103 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4104 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105 }
4106
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107 bh_unlock_sock(sk);
4108 }
4109
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004110 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004111
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112 return 0;
4113}
4114
4115static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4116{
4117 struct l2cap_conn *conn = hcon->l2cap_data;
4118
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004119 if (!conn)
4120 conn = l2cap_conn_add(hcon, 0);
4121
4122 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123 goto drop;
4124
4125 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4126
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004127 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004129 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004130 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131 int len;
4132
4133 if (conn->rx_len) {
4134 BT_ERR("Unexpected start frame (len %d)", skb->len);
4135 kfree_skb(conn->rx_skb);
4136 conn->rx_skb = NULL;
4137 conn->rx_len = 0;
4138 l2cap_conn_unreliable(conn, ECOMM);
4139 }
4140
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004141 /* Start fragment always begin with Basic L2CAP header */
4142 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143 BT_ERR("Frame is too short (len %d)", skb->len);
4144 l2cap_conn_unreliable(conn, ECOMM);
4145 goto drop;
4146 }
4147
4148 hdr = (struct l2cap_hdr *) skb->data;
4149 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004150 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151
4152 if (len == skb->len) {
4153 /* Complete frame received */
4154 l2cap_recv_frame(conn, skb);
4155 return 0;
4156 }
4157
4158 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4159
4160 if (skb->len > len) {
4161 BT_ERR("Frame is too long (len %d, expected len %d)",
4162 skb->len, len);
4163 l2cap_conn_unreliable(conn, ECOMM);
4164 goto drop;
4165 }
4166
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004167 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004168
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004169 if (chan && chan->sk) {
4170 struct sock *sk = chan->sk;
4171
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004172 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004173 BT_ERR("Frame exceeding recv MTU (len %d, "
4174 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004175 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004176 bh_unlock_sock(sk);
4177 l2cap_conn_unreliable(conn, ECOMM);
4178 goto drop;
4179 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004180 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004181 }
4182
Linus Torvalds1da177e2005-04-16 15:20:36 -07004183 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004184 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4185 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004186 goto drop;
4187
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004188 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004189 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004190 conn->rx_len = len - skb->len;
4191 } else {
4192 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4193
4194 if (!conn->rx_len) {
4195 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4196 l2cap_conn_unreliable(conn, ECOMM);
4197 goto drop;
4198 }
4199
4200 if (skb->len > conn->rx_len) {
4201 BT_ERR("Fragment is too long (len %d, expected %d)",
4202 skb->len, conn->rx_len);
4203 kfree_skb(conn->rx_skb);
4204 conn->rx_skb = NULL;
4205 conn->rx_len = 0;
4206 l2cap_conn_unreliable(conn, ECOMM);
4207 goto drop;
4208 }
4209
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004210 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004211 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004212 conn->rx_len -= skb->len;
4213
4214 if (!conn->rx_len) {
4215 /* Complete frame received */
4216 l2cap_recv_frame(conn, conn->rx_skb);
4217 conn->rx_skb = NULL;
4218 }
4219 }
4220
4221drop:
4222 kfree_skb(skb);
4223 return 0;
4224}
4225
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004226static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004228 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004230 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004232 list_for_each_entry(c, &chan_list, global_l) {
4233 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004234
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004235 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 +01004236 batostr(&bt_sk(sk)->src),
4237 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004238 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004239 c->scid, c->dcid, c->imtu, c->omtu,
4240 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004241}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004243 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004244
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004245 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246}
4247
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004248static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4249{
4250 return single_open(file, l2cap_debugfs_show, inode->i_private);
4251}
4252
4253static const struct file_operations l2cap_debugfs_fops = {
4254 .open = l2cap_debugfs_open,
4255 .read = seq_read,
4256 .llseek = seq_lseek,
4257 .release = single_release,
4258};
4259
4260static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004261
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262static struct hci_proto l2cap_hci_proto = {
4263 .name = "L2CAP",
4264 .id = HCI_PROTO_L2CAP,
4265 .connect_ind = l2cap_connect_ind,
4266 .connect_cfm = l2cap_connect_cfm,
4267 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004268 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004269 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004270 .recv_acldata = l2cap_recv_acldata
4271};
4272
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004273int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274{
4275 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004276
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004277 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278 if (err < 0)
4279 return err;
4280
Linus Torvalds1da177e2005-04-16 15:20:36 -07004281 err = hci_register_proto(&l2cap_hci_proto);
4282 if (err < 0) {
4283 BT_ERR("L2CAP protocol registration failed");
4284 bt_sock_unregister(BTPROTO_L2CAP);
4285 goto error;
4286 }
4287
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004288 if (bt_debugfs) {
4289 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4290 bt_debugfs, NULL, &l2cap_debugfs_fops);
4291 if (!l2cap_debugfs)
4292 BT_ERR("Failed to create L2CAP debug file");
4293 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004294
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295 return 0;
4296
4297error:
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004298 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299 return err;
4300}
4301
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004302void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004304 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4307 BT_ERR("L2CAP protocol unregistration failed");
4308
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004309 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310}
4311
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004312module_param(disable_ertm, bool, 0644);
4313MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03004314
4315module_param(enable_hs, bool, 0644);
4316MODULE_PARM_DESC(enable_hs, "Enable High Speed");