blob: f35eb73b25fd17a0c821a0c0ed42aca17f212ec6 [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)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300616 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
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
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300619 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300620
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300621 control |= __set_reqseq(chan, chan->buffer_seq);
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);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001314 control &= __get_sar_mask(chan);
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
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001319 control |= __set_reqseq(chan, chan->buffer_seq);
1320 control |= 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);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001354 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001355
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
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001359 control |= __set_reqseq(chan, chan->buffer_seq);
1360 control |= 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
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001408 control |= __set_reqseq(chan, chan->buffer_seq);
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)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001411 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
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
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001420 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
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
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001429 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001430 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);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001433 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001434
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);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001585 control = __set_ctrl_sar(chan, L2CAP_SAR_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) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001598 control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001599 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001600 } else {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001601 control = __set_ctrl_sar(chan, L2CAP_SAR_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) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001657 control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001658 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
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001901static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
1902{
1903 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
1904}
1905
1906static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
1907{
1908 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
1909 __l2cap_ews_supported(chan))
1910 /* use extended control field */
1911 set_bit(FLAG_EXT_CTRL, &chan->flags);
1912 else
1913 chan->tx_win = min_t(u16, chan->tx_win,
1914 L2CAP_DEFAULT_TX_WINDOW);
1915}
1916
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03001917static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001920 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 void *ptr = req->data;
1922
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001923 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001925 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001926 goto done;
1927
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001928 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001929 case L2CAP_MODE_STREAMING:
1930 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001931 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001932 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001933
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001934 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001935 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001936 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001937 break;
1938 }
1939
1940done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001941 if (chan->imtu != L2CAP_DEFAULT_MTU)
1942 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001943
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001944 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001945 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001946 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1947 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001948 break;
1949
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001950 rfc.mode = L2CAP_MODE_BASIC;
1951 rfc.txwin_size = 0;
1952 rfc.max_transmit = 0;
1953 rfc.retrans_timeout = 0;
1954 rfc.monitor_timeout = 0;
1955 rfc.max_pdu_size = 0;
1956
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001957 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1958 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001959 break;
1960
1961 case L2CAP_MODE_ERTM:
1962 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001963 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001964 rfc.retrans_timeout = 0;
1965 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001966 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001967 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1968 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001969
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001970 l2cap_txwin_setup(chan);
1971
1972 rfc.txwin_size = min_t(u16, chan->tx_win,
1973 L2CAP_DEFAULT_TX_WINDOW);
1974
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001975 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1976 (unsigned long) &rfc);
1977
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001978 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001979 break;
1980
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001981 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001982 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001983 chan->fcs = L2CAP_FCS_NONE;
1984 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001985 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001986
1987 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1988 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
1989 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001990 break;
1991
1992 case L2CAP_MODE_STREAMING:
1993 rfc.mode = L2CAP_MODE_STREAMING;
1994 rfc.txwin_size = 0;
1995 rfc.max_transmit = 0;
1996 rfc.retrans_timeout = 0;
1997 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001998 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001999 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
2000 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002001
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002002 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2003 (unsigned long) &rfc);
2004
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002005 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002006 break;
2007
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002008 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002009 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002010 chan->fcs = L2CAP_FCS_NONE;
2011 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002012 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002013 break;
2014 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002016 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002017 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018
2019 return ptr - data;
2020}
2021
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002022static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002024 struct l2cap_conf_rsp *rsp = data;
2025 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002026 void *req = chan->conf_req;
2027 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002028 int type, hint, olen;
2029 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002030 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002031 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002032 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002034 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002035
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002036 while (len >= L2CAP_CONF_OPT_SIZE) {
2037 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002039 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002040 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002041
2042 switch (type) {
2043 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002044 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002045 break;
2046
2047 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002048 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002049 break;
2050
2051 case L2CAP_CONF_QOS:
2052 break;
2053
Marcel Holtmann6464f352007-10-20 13:39:51 +02002054 case L2CAP_CONF_RFC:
2055 if (olen == sizeof(rfc))
2056 memcpy(&rfc, (void *) val, olen);
2057 break;
2058
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002059 case L2CAP_CONF_FCS:
2060 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002061 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002062
2063 break;
2064
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002065 case L2CAP_CONF_EWS:
2066 if (!enable_hs)
2067 return -ECONNREFUSED;
2068
2069 set_bit(FLAG_EXT_CTRL, &chan->flags);
2070 set_bit(CONF_EWS_RECV, &chan->conf_state);
2071 chan->remote_tx_win = val;
2072 break;
2073
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002074 default:
2075 if (hint)
2076 break;
2077
2078 result = L2CAP_CONF_UNKNOWN;
2079 *((u8 *) ptr++) = type;
2080 break;
2081 }
2082 }
2083
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002084 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002085 goto done;
2086
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002087 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002088 case L2CAP_MODE_STREAMING:
2089 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002090 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002091 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002092 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002093 break;
2094 }
2095
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002096 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002097 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002098
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002099 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002100 }
2101
2102done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002103 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002104 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002105 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002106
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002107 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002108 return -ECONNREFUSED;
2109
2110 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2111 sizeof(rfc), (unsigned long) &rfc);
2112 }
2113
2114
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002115 if (result == L2CAP_CONF_SUCCESS) {
2116 /* Configure output options and let the other side know
2117 * which ones we don't like. */
2118
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002119 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2120 result = L2CAP_CONF_UNACCEPT;
2121 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002122 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002123 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002124 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002125 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002126
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002127 switch (rfc.mode) {
2128 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002129 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002130 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002131 break;
2132
2133 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002134 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2135 chan->remote_tx_win = rfc.txwin_size;
2136 else
2137 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2138
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002139 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002140
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002141 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2142 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002143
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002144 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002145
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002146 rfc.retrans_timeout =
2147 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2148 rfc.monitor_timeout =
2149 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002150
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002151 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002152
2153 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2154 sizeof(rfc), (unsigned long) &rfc);
2155
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002156 break;
2157
2158 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002159 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2160 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002161
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002162 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002163
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002164 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002165
2166 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2167 sizeof(rfc), (unsigned long) &rfc);
2168
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002169 break;
2170
2171 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002172 result = L2CAP_CONF_UNACCEPT;
2173
2174 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002175 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002176 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002177
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002178 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002179 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002180 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002181 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002182 rsp->result = cpu_to_le16(result);
2183 rsp->flags = cpu_to_le16(0x0000);
2184
2185 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186}
2187
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002188static 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 -03002189{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002190 struct l2cap_conf_req *req = data;
2191 void *ptr = req->data;
2192 int type, olen;
2193 unsigned long val;
2194 struct l2cap_conf_rfc rfc;
2195
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002196 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002197
2198 while (len >= L2CAP_CONF_OPT_SIZE) {
2199 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2200
2201 switch (type) {
2202 case L2CAP_CONF_MTU:
2203 if (val < L2CAP_DEFAULT_MIN_MTU) {
2204 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002205 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002206 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002207 chan->imtu = val;
2208 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002209 break;
2210
2211 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002212 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002213 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002214 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002215 break;
2216
2217 case L2CAP_CONF_RFC:
2218 if (olen == sizeof(rfc))
2219 memcpy(&rfc, (void *)val, olen);
2220
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002221 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002222 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002223 return -ECONNREFUSED;
2224
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002225 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002226
2227 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2228 sizeof(rfc), (unsigned long) &rfc);
2229 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002230
2231 case L2CAP_CONF_EWS:
2232 chan->tx_win = min_t(u16, val,
2233 L2CAP_DEFAULT_EXT_WINDOW);
2234 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS,
2235 2, chan->tx_win);
2236 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002237 }
2238 }
2239
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002240 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002241 return -ECONNREFUSED;
2242
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002243 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002244
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002245 if (*result == L2CAP_CONF_SUCCESS) {
2246 switch (rfc.mode) {
2247 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002248 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2249 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2250 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002251 break;
2252 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002253 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002254 }
2255 }
2256
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002257 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002258 req->flags = cpu_to_le16(0x0000);
2259
2260 return ptr - data;
2261}
2262
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002263static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264{
2265 struct l2cap_conf_rsp *rsp = data;
2266 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002268 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002270 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002271 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002272 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273
2274 return ptr - data;
2275}
2276
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002277void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002278{
2279 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002280 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002281 u8 buf[128];
2282
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002283 rsp.scid = cpu_to_le16(chan->dcid);
2284 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002285 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2286 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2287 l2cap_send_cmd(conn, chan->ident,
2288 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2289
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002290 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002291 return;
2292
Gustavo F. Padovan710f9b0a2011-03-25 14:30:37 -03002293 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2294 l2cap_build_conf_req(chan, buf), buf);
2295 chan->num_conf_req++;
2296}
2297
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002298static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002299{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002300 int type, olen;
2301 unsigned long val;
2302 struct l2cap_conf_rfc rfc;
2303
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002304 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002305
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002306 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002307 return;
2308
2309 while (len >= L2CAP_CONF_OPT_SIZE) {
2310 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2311
2312 switch (type) {
2313 case L2CAP_CONF_RFC:
2314 if (olen == sizeof(rfc))
2315 memcpy(&rfc, (void *)val, olen);
2316 goto done;
2317 }
2318 }
2319
2320done:
2321 switch (rfc.mode) {
2322 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002323 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2324 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2325 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002326 break;
2327 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002328 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002329 }
2330}
2331
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002332static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2333{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002334 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002335
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002336 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002337 return 0;
2338
2339 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2340 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002341 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002342
2343 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002344 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002345
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002346 l2cap_conn_start(conn);
2347 }
2348
2349 return 0;
2350}
2351
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2353{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2355 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002356 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002357 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002358 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359
2360 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002361 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362
2363 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2364
2365 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002366 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2367 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368 result = L2CAP_CR_BAD_PSM;
2369 goto sendresp;
2370 }
2371
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002372 parent = pchan->sk;
2373
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002374 bh_lock_sock(parent);
2375
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002376 /* Check if the ACL is secure enough (if not SDP) */
2377 if (psm != cpu_to_le16(0x0001) &&
2378 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002379 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002380 result = L2CAP_CR_SEC_BLOCK;
2381 goto response;
2382 }
2383
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384 result = L2CAP_CR_NO_MEM;
2385
2386 /* Check for backlog size */
2387 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002388 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389 goto response;
2390 }
2391
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002392 chan = pchan->ops->new_connection(pchan->data);
2393 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394 goto response;
2395
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002396 sk = chan->sk;
2397
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002398 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399
2400 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002401 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2402 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002404 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 goto response;
2406 }
2407
2408 hci_conn_hold(conn->hcon);
2409
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 bacpy(&bt_sk(sk)->src, conn->src);
2411 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002412 chan->psm = psm;
2413 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002415 bt_accept_enqueue(parent, sk);
2416
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002417 __l2cap_chan_add(conn, chan);
2418
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002419 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002421 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002423 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424
Marcel Holtmann984947d2009-02-06 23:35:19 +01002425 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002426 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002427 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002428 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002429 result = L2CAP_CR_PEND;
2430 status = L2CAP_CS_AUTHOR_PEND;
2431 parent->sk_data_ready(parent, 0);
2432 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002433 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002434 result = L2CAP_CR_SUCCESS;
2435 status = L2CAP_CS_NO_INFO;
2436 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002437 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002438 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002439 result = L2CAP_CR_PEND;
2440 status = L2CAP_CS_AUTHEN_PEND;
2441 }
2442 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002443 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002444 result = L2CAP_CR_PEND;
2445 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446 }
2447
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002448 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449
2450response:
2451 bh_unlock_sock(parent);
2452
2453sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002454 rsp.scid = cpu_to_le16(scid);
2455 rsp.dcid = cpu_to_le16(dcid);
2456 rsp.result = cpu_to_le16(result);
2457 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002459
2460 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2461 struct l2cap_info_req info;
2462 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2463
2464 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2465 conn->info_ident = l2cap_get_ident(conn);
2466
2467 mod_timer(&conn->info_timer, jiffies +
2468 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2469
2470 l2cap_send_cmd(conn, conn->info_ident,
2471 L2CAP_INFO_REQ, sizeof(info), &info);
2472 }
2473
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002474 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002475 result == L2CAP_CR_SUCCESS) {
2476 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002477 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002478 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002479 l2cap_build_conf_req(chan, buf), buf);
2480 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002481 }
2482
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483 return 0;
2484}
2485
2486static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2487{
2488 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2489 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002490 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491 struct sock *sk;
2492 u8 req[128];
2493
2494 scid = __le16_to_cpu(rsp->scid);
2495 dcid = __le16_to_cpu(rsp->dcid);
2496 result = __le16_to_cpu(rsp->result);
2497 status = __le16_to_cpu(rsp->status);
2498
2499 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2500
2501 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002502 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002503 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002504 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002506 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002507 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002508 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509 }
2510
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002511 sk = chan->sk;
2512
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513 switch (result) {
2514 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002515 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002516 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002517 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002518 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002519
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002520 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002521 break;
2522
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002524 l2cap_build_conf_req(chan, req), req);
2525 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526 break;
2527
2528 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002529 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530 break;
2531
2532 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002533 /* don't delete l2cap channel if sk is owned by user */
2534 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002535 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002536 __clear_chan_timer(chan);
2537 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002538 break;
2539 }
2540
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002541 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542 break;
2543 }
2544
2545 bh_unlock_sock(sk);
2546 return 0;
2547}
2548
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002549static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002550{
2551 /* FCS is enabled only in ERTM or streaming mode, if one or both
2552 * sides request it.
2553 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002554 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002555 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002556 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002557 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002558}
2559
Al Viro88219a02007-07-29 00:17:25 -07002560static 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 -07002561{
2562 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2563 u16 dcid, flags;
2564 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002565 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002567 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568
2569 dcid = __le16_to_cpu(req->dcid);
2570 flags = __le16_to_cpu(req->flags);
2571
2572 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2573
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002574 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002575 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576 return -ENOENT;
2577
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002578 sk = chan->sk;
2579
David S. Miller033b1142011-07-21 13:38:42 -07002580 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002581 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002582
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002583 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2584 rej.scid = cpu_to_le16(chan->scid);
2585 rej.dcid = cpu_to_le16(chan->dcid);
2586
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002587 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2588 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002589 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002590 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002591
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002592 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002593 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002594 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002595 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002596 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002597 L2CAP_CONF_REJECT, flags), rsp);
2598 goto unlock;
2599 }
2600
2601 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002602 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2603 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604
2605 if (flags & 0x0001) {
2606 /* Incomplete config. Send empty response. */
2607 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002608 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002609 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610 goto unlock;
2611 }
2612
2613 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002614 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002615 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002616 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002618 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002620 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002621 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002622
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002623 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002624 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002625
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002626 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002627 goto unlock;
2628
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002629 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002630 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002631
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002632 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002633
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002634 chan->next_tx_seq = 0;
2635 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002636 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002637 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002638 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002639
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002641 goto unlock;
2642 }
2643
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002644 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002645 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002647 l2cap_build_conf_req(chan, buf), buf);
2648 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 }
2650
2651unlock:
2652 bh_unlock_sock(sk);
2653 return 0;
2654}
2655
2656static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2657{
2658 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2659 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002660 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002662 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663
2664 scid = __le16_to_cpu(rsp->scid);
2665 flags = __le16_to_cpu(rsp->flags);
2666 result = __le16_to_cpu(rsp->result);
2667
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002668 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2669 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002671 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002672 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673 return 0;
2674
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002675 sk = chan->sk;
2676
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677 switch (result) {
2678 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002679 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 break;
2681
2682 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002683 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002684 char req[64];
2685
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002686 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002687 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002688 goto done;
2689 }
2690
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002691 /* throw out any old stored conf requests */
2692 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002693 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2694 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002695 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002696 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002697 goto done;
2698 }
2699
2700 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2701 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002702 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002703 if (result != L2CAP_CONF_SUCCESS)
2704 goto done;
2705 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706 }
2707
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002708 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002709 sk->sk_err = ECONNRESET;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002710 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002711 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712 goto done;
2713 }
2714
2715 if (flags & 0x01)
2716 goto done;
2717
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002718 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002720 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002721 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002722
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002723 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002724 chan->next_tx_seq = 0;
2725 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002726 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002727 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002728 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002729
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 l2cap_chan_ready(sk);
2731 }
2732
2733done:
2734 bh_unlock_sock(sk);
2735 return 0;
2736}
2737
2738static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2739{
2740 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2741 struct l2cap_disconn_rsp rsp;
2742 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002743 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744 struct sock *sk;
2745
2746 scid = __le16_to_cpu(req->scid);
2747 dcid = __le16_to_cpu(req->dcid);
2748
2749 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2750
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002751 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002752 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753 return 0;
2754
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002755 sk = chan->sk;
2756
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002757 rsp.dcid = cpu_to_le16(chan->scid);
2758 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2760
2761 sk->sk_shutdown = SHUTDOWN_MASK;
2762
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002763 /* don't delete l2cap channel if sk is owned by user */
2764 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002765 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002766 __clear_chan_timer(chan);
2767 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002768 bh_unlock_sock(sk);
2769 return 0;
2770 }
2771
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002772 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773 bh_unlock_sock(sk);
2774
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002775 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776 return 0;
2777}
2778
2779static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2780{
2781 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2782 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002783 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784 struct sock *sk;
2785
2786 scid = __le16_to_cpu(rsp->scid);
2787 dcid = __le16_to_cpu(rsp->dcid);
2788
2789 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2790
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002791 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002792 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793 return 0;
2794
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002795 sk = chan->sk;
2796
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002797 /* don't delete l2cap channel if sk is owned by user */
2798 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002799 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002800 __clear_chan_timer(chan);
2801 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002802 bh_unlock_sock(sk);
2803 return 0;
2804 }
2805
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002806 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807 bh_unlock_sock(sk);
2808
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002809 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810 return 0;
2811}
2812
2813static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2814{
2815 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816 u16 type;
2817
2818 type = __le16_to_cpu(req->type);
2819
2820 BT_DBG("type 0x%4.4x", type);
2821
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002822 if (type == L2CAP_IT_FEAT_MASK) {
2823 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002824 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002825 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2826 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2827 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002828 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002829 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2830 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03002831 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002832 feat_mask |= L2CAP_FEAT_EXT_FLOW
2833 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03002834
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002835 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002836 l2cap_send_cmd(conn, cmd->ident,
2837 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002838 } else if (type == L2CAP_IT_FIXED_CHAN) {
2839 u8 buf[12];
2840 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2841 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2842 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2843 memcpy(buf + 4, l2cap_fixed_chan, 8);
2844 l2cap_send_cmd(conn, cmd->ident,
2845 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002846 } else {
2847 struct l2cap_info_rsp rsp;
2848 rsp.type = cpu_to_le16(type);
2849 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2850 l2cap_send_cmd(conn, cmd->ident,
2851 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2852 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853
2854 return 0;
2855}
2856
2857static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2858{
2859 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2860 u16 type, result;
2861
2862 type = __le16_to_cpu(rsp->type);
2863 result = __le16_to_cpu(rsp->result);
2864
2865 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2866
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002867 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2868 if (cmd->ident != conn->info_ident ||
2869 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2870 return 0;
2871
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002872 del_timer(&conn->info_timer);
2873
Ville Tervoadb08ed2010-08-04 09:43:33 +03002874 if (result != L2CAP_IR_SUCCESS) {
2875 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2876 conn->info_ident = 0;
2877
2878 l2cap_conn_start(conn);
2879
2880 return 0;
2881 }
2882
Marcel Holtmann984947d2009-02-06 23:35:19 +01002883 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002884 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002885
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002886 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002887 struct l2cap_info_req req;
2888 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2889
2890 conn->info_ident = l2cap_get_ident(conn);
2891
2892 l2cap_send_cmd(conn, conn->info_ident,
2893 L2CAP_INFO_REQ, sizeof(req), &req);
2894 } else {
2895 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2896 conn->info_ident = 0;
2897
2898 l2cap_conn_start(conn);
2899 }
2900 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002901 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002902 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002903
2904 l2cap_conn_start(conn);
2905 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002906
Linus Torvalds1da177e2005-04-16 15:20:36 -07002907 return 0;
2908}
2909
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002910static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002911 u16 to_multiplier)
2912{
2913 u16 max_latency;
2914
2915 if (min > max || min < 6 || max > 3200)
2916 return -EINVAL;
2917
2918 if (to_multiplier < 10 || to_multiplier > 3200)
2919 return -EINVAL;
2920
2921 if (max >= to_multiplier * 8)
2922 return -EINVAL;
2923
2924 max_latency = (to_multiplier * 8 / max) - 1;
2925 if (latency > 499 || latency > max_latency)
2926 return -EINVAL;
2927
2928 return 0;
2929}
2930
2931static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2932 struct l2cap_cmd_hdr *cmd, u8 *data)
2933{
2934 struct hci_conn *hcon = conn->hcon;
2935 struct l2cap_conn_param_update_req *req;
2936 struct l2cap_conn_param_update_rsp rsp;
2937 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002938 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002939
2940 if (!(hcon->link_mode & HCI_LM_MASTER))
2941 return -EINVAL;
2942
2943 cmd_len = __le16_to_cpu(cmd->len);
2944 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2945 return -EPROTO;
2946
2947 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002948 min = __le16_to_cpu(req->min);
2949 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002950 latency = __le16_to_cpu(req->latency);
2951 to_multiplier = __le16_to_cpu(req->to_multiplier);
2952
2953 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2954 min, max, latency, to_multiplier);
2955
2956 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002957
2958 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2959 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002960 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2961 else
2962 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2963
2964 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2965 sizeof(rsp), &rsp);
2966
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002967 if (!err)
2968 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2969
Claudio Takahaside731152011-02-11 19:28:55 -02002970 return 0;
2971}
2972
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002973static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2974 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2975{
2976 int err = 0;
2977
2978 switch (cmd->code) {
2979 case L2CAP_COMMAND_REJ:
2980 l2cap_command_rej(conn, cmd, data);
2981 break;
2982
2983 case L2CAP_CONN_REQ:
2984 err = l2cap_connect_req(conn, cmd, data);
2985 break;
2986
2987 case L2CAP_CONN_RSP:
2988 err = l2cap_connect_rsp(conn, cmd, data);
2989 break;
2990
2991 case L2CAP_CONF_REQ:
2992 err = l2cap_config_req(conn, cmd, cmd_len, data);
2993 break;
2994
2995 case L2CAP_CONF_RSP:
2996 err = l2cap_config_rsp(conn, cmd, data);
2997 break;
2998
2999 case L2CAP_DISCONN_REQ:
3000 err = l2cap_disconnect_req(conn, cmd, data);
3001 break;
3002
3003 case L2CAP_DISCONN_RSP:
3004 err = l2cap_disconnect_rsp(conn, cmd, data);
3005 break;
3006
3007 case L2CAP_ECHO_REQ:
3008 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3009 break;
3010
3011 case L2CAP_ECHO_RSP:
3012 break;
3013
3014 case L2CAP_INFO_REQ:
3015 err = l2cap_information_req(conn, cmd, data);
3016 break;
3017
3018 case L2CAP_INFO_RSP:
3019 err = l2cap_information_rsp(conn, cmd, data);
3020 break;
3021
3022 default:
3023 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3024 err = -EINVAL;
3025 break;
3026 }
3027
3028 return err;
3029}
3030
3031static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3032 struct l2cap_cmd_hdr *cmd, u8 *data)
3033{
3034 switch (cmd->code) {
3035 case L2CAP_COMMAND_REJ:
3036 return 0;
3037
3038 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003039 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003040
3041 case L2CAP_CONN_PARAM_UPDATE_RSP:
3042 return 0;
3043
3044 default:
3045 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3046 return -EINVAL;
3047 }
3048}
3049
3050static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3051 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052{
3053 u8 *data = skb->data;
3054 int len = skb->len;
3055 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003056 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057
3058 l2cap_raw_recv(conn, skb);
3059
3060 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003061 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3063 data += L2CAP_CMD_HDR_SIZE;
3064 len -= L2CAP_CMD_HDR_SIZE;
3065
Al Viro88219a02007-07-29 00:17:25 -07003066 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067
Al Viro88219a02007-07-29 00:17:25 -07003068 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 -07003069
Al Viro88219a02007-07-29 00:17:25 -07003070 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071 BT_DBG("corrupted command");
3072 break;
3073 }
3074
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003075 if (conn->hcon->type == LE_LINK)
3076 err = l2cap_le_sig_cmd(conn, &cmd, data);
3077 else
3078 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079
3080 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003081 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003082
3083 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084
3085 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003086 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3088 }
3089
Al Viro88219a02007-07-29 00:17:25 -07003090 data += cmd_len;
3091 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003092 }
3093
3094 kfree_skb(skb);
3095}
3096
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003097static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003098{
3099 u16 our_fcs, rcv_fcs;
3100 int hdr_size = L2CAP_HDR_SIZE + 2;
3101
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003102 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003103 skb_trim(skb, skb->len - 2);
3104 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3105 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3106
3107 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003108 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003109 }
3110 return 0;
3111}
3112
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003113static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003114{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003115 u16 control = 0;
3116
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003117 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003118
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003119 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003120
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003121 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003122 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003123 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003124 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003125 }
3126
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003127 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003128 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003129
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003130 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003131
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003132 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003133 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003134 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003135 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003136 }
3137}
3138
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003139static 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 -03003140{
3141 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003142 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003143
3144 bt_cb(skb)->tx_seq = tx_seq;
3145 bt_cb(skb)->sar = sar;
3146
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003147 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003148 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003149 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003150 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003151 }
3152
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003153 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003154 if (tx_seq_offset < 0)
3155 tx_seq_offset += 64;
3156
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003157 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003158 if (bt_cb(next_skb)->tx_seq == tx_seq)
3159 return -EINVAL;
3160
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003161 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003162 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003163 if (next_tx_seq_offset < 0)
3164 next_tx_seq_offset += 64;
3165
3166 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003167 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003168 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003169 }
3170
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003171 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003172 break;
3173
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003174 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003175
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003176 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003177
3178 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003179}
3180
Mat Martineau84084a32011-07-22 14:54:00 -07003181static void append_skb_frag(struct sk_buff *skb,
3182 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003183{
Mat Martineau84084a32011-07-22 14:54:00 -07003184 /* skb->len reflects data in skb as well as all fragments
3185 * skb->data_len reflects only data in fragments
3186 */
3187 if (!skb_has_frag_list(skb))
3188 skb_shinfo(skb)->frag_list = new_frag;
3189
3190 new_frag->next = NULL;
3191
3192 (*last_frag)->next = new_frag;
3193 *last_frag = new_frag;
3194
3195 skb->len += new_frag->len;
3196 skb->data_len += new_frag->len;
3197 skb->truesize += new_frag->truesize;
3198}
3199
3200static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
3201{
3202 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003203
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003204 switch (__get_ctrl_sar(chan, control)) {
3205 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003206 if (chan->sdu)
3207 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003208
Mat Martineau84084a32011-07-22 14:54:00 -07003209 err = chan->ops->recv(chan->data, skb);
3210 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003211
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003212 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003213 if (chan->sdu)
3214 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003215
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003216 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003217 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003218
Mat Martineau84084a32011-07-22 14:54:00 -07003219 if (chan->sdu_len > chan->imtu) {
3220 err = -EMSGSIZE;
3221 break;
3222 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003223
Mat Martineau84084a32011-07-22 14:54:00 -07003224 if (skb->len >= chan->sdu_len)
3225 break;
3226
3227 chan->sdu = skb;
3228 chan->sdu_last_frag = skb;
3229
3230 skb = NULL;
3231 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003232 break;
3233
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003234 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003235 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003236 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003237
Mat Martineau84084a32011-07-22 14:54:00 -07003238 append_skb_frag(chan->sdu, skb,
3239 &chan->sdu_last_frag);
3240 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003241
Mat Martineau84084a32011-07-22 14:54:00 -07003242 if (chan->sdu->len >= chan->sdu_len)
3243 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003244
Mat Martineau84084a32011-07-22 14:54:00 -07003245 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003246 break;
3247
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003248 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003249 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003250 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003251
Mat Martineau84084a32011-07-22 14:54:00 -07003252 append_skb_frag(chan->sdu, skb,
3253 &chan->sdu_last_frag);
3254 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003255
Mat Martineau84084a32011-07-22 14:54:00 -07003256 if (chan->sdu->len != chan->sdu_len)
3257 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003258
Mat Martineau84084a32011-07-22 14:54:00 -07003259 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003260
Mat Martineau84084a32011-07-22 14:54:00 -07003261 if (!err) {
3262 /* Reassembly complete */
3263 chan->sdu = NULL;
3264 chan->sdu_last_frag = NULL;
3265 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003266 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003267 break;
3268 }
3269
Mat Martineau84084a32011-07-22 14:54:00 -07003270 if (err) {
3271 kfree_skb(skb);
3272 kfree_skb(chan->sdu);
3273 chan->sdu = NULL;
3274 chan->sdu_last_frag = NULL;
3275 chan->sdu_len = 0;
3276 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003277
Mat Martineau84084a32011-07-22 14:54:00 -07003278 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003279}
3280
Mat Martineau26f880d2011-07-07 09:39:01 -07003281static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003282{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003283 u16 control;
3284
Mat Martineau26f880d2011-07-07 09:39:01 -07003285 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003286
Mat Martineau26f880d2011-07-07 09:39:01 -07003287 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3288
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003289 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003290 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Mat Martineau26f880d2011-07-07 09:39:01 -07003291 l2cap_send_sframe(chan, control);
3292
3293 set_bit(CONN_RNR_SENT, &chan->conn_state);
3294
3295 __clear_ack_timer(chan);
3296}
3297
3298static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3299{
3300 u16 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003301
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003302 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003303 goto done;
3304
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003305 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003306 control |= L2CAP_CTRL_POLL;
3307 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003308 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003309 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003310
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003311 __clear_retrans_timer(chan);
3312 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003313
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003314 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003315
3316done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003317 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3318 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003319
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003320 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003321}
3322
Mat Martineaue3281402011-07-07 09:39:02 -07003323void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003324{
Mat Martineaue3281402011-07-07 09:39:02 -07003325 if (chan->mode == L2CAP_MODE_ERTM) {
3326 if (busy)
3327 l2cap_ertm_enter_local_busy(chan);
3328 else
3329 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003330 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003331}
3332
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003333static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003334{
3335 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003336 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003337
Mat Martineaue3281402011-07-07 09:39:02 -07003338 while ((skb = skb_peek(&chan->srej_q)) &&
3339 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3340 int err;
3341
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003342 if (bt_cb(skb)->tx_seq != tx_seq)
3343 break;
3344
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003345 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003346 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003347 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003348
3349 if (err < 0) {
3350 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3351 break;
3352 }
3353
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003354 chan->buffer_seq_srej =
3355 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003356 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003357 }
3358}
3359
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003360static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003361{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003362 struct srej_list *l, *tmp;
3363 u16 control;
3364
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003365 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003366 if (l->tx_seq == tx_seq) {
3367 list_del(&l->list);
3368 kfree(l);
3369 return;
3370 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003371 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003372 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003373 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003374 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003375 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003376 }
3377}
3378
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003379static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003380{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003381 struct srej_list *new;
3382 u16 control;
3383
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003384 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003385 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003386 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003387 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003388
3389 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003390 new->tx_seq = chan->expected_tx_seq;
3391 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003392 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003393 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003394 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003395}
3396
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003397static 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 -03003398{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003399 u8 tx_seq = __get_txseq(rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003400 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003401 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003402 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003403 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003404 int err = 0;
3405
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003406 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3407 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003408
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003409 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003410 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003411 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003412 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003413 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003414 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003415 }
3416
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003417 chan->expected_ack_seq = req_seq;
3418 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003419
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003420 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003421 if (tx_seq_offset < 0)
3422 tx_seq_offset += 64;
3423
3424 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003425 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003426 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003427 goto drop;
3428 }
3429
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003430 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003431 goto drop;
3432
Mat Martineau02f1b642011-06-29 14:35:19 -07003433 if (tx_seq == chan->expected_tx_seq)
3434 goto expected;
3435
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003436 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003437 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003438
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003439 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003440 struct srej_list, list);
3441 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003442 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003443 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003444
3445 list_del(&first->list);
3446 kfree(first);
3447
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003448 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003449 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003450 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003451 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003452 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003453 }
3454 } else {
3455 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003456
3457 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003458 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003459 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003460
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003461 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003462 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003463 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003464 return 0;
3465 }
3466 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003467 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003468 }
3469 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003470 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003471 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003472 if (expected_tx_seq_offset < 0)
3473 expected_tx_seq_offset += 64;
3474
3475 /* duplicated tx_seq */
3476 if (tx_seq_offset < expected_tx_seq_offset)
3477 goto drop;
3478
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003479 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003480
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003481 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003482
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003483 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003484 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003485
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003486 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003487 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003488
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003489 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003490
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003491 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003492
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003493 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003494 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003495 return 0;
3496
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003497expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003498 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003499
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003500 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003501 bt_cb(skb)->tx_seq = tx_seq;
3502 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003503 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003504 return 0;
3505 }
3506
Mat Martineau84084a32011-07-22 14:54:00 -07003507 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Mat Martineaufadd1922011-07-07 09:39:03 -07003508 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Mat Martineaue3281402011-07-07 09:39:02 -07003509 if (err < 0) {
3510 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3511 return err;
3512 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003513
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003514 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003515 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003516 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003517 }
3518
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003519 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003520
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003521 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3522 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003523 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003524
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003525 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003526
3527drop:
3528 kfree_skb(skb);
3529 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003530}
3531
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003532static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003533{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003534 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan,
3535 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003536
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003537 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003538 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003539
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003540 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003541 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3542 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3543 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003544 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003545 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003546
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003547 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003548 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003549 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003550 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003551 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003552
3553 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003554 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003555
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003556 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003557 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003558
3559 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003560 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003561 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003562 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003563
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003564 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3565 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003566 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003567 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003568 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003569 }
3570}
3571
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003572static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003573{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003574 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003575
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003576 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003577
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003578 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003579
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003580 chan->expected_ack_seq = tx_seq;
3581 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003582
3583 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003584 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003585 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003586 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003587 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003588
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003589 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3590 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003591 }
3592}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003593static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003594{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003595 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003596
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003597 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003598
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003599 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003600
3601 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003602 chan->expected_ack_seq = tx_seq;
3603 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003604
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003605 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003606 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003607
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003608 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003609
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003610 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003611 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003612 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003613 }
3614 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003615 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003616 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003617 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003618 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003619 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003620 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003621 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003622 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003623 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003624 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003625 }
3626 }
3627}
3628
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003629static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003630{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003631 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003632
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003633 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003634
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003635 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003636 chan->expected_ack_seq = tx_seq;
3637 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003638
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003639 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003640 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003641
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003642 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003643 __clear_retrans_timer(chan);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003644 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003645 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003646 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003647 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003648
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003649 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003650 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003651 } else {
3652 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
3653 l2cap_send_sframe(chan, rx_control);
3654 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003655}
3656
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003657static 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 -03003658{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003659 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003660
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003661 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003662 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003663 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003664 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003665 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003666 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003667 }
3668
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003669 switch (__get_ctrl_super(chan, rx_control)) {
3670 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003671 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003672 break;
3673
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003674 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003675 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003676 break;
3677
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003678 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003679 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003680 break;
3681
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003682 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003683 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003684 break;
3685 }
3686
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003687 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003688 return 0;
3689}
3690
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003691static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3692{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003693 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003694 u16 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003695 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003696 int len, next_tx_seq_offset, req_seq_offset;
3697
3698 control = get_unaligned_le16(skb->data);
3699 skb_pull(skb, 2);
3700 len = skb->len;
3701
3702 /*
3703 * We can just drop the corrupted I-frame here.
3704 * Receiver will miss it and start proper recovery
3705 * procedures and ask retransmission.
3706 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003707 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003708 goto drop;
3709
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003710 if (__is_sar_start(chan, control) && __is_iframe(control))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003711 len -= 2;
3712
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003713 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003714 len -= 2;
3715
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003716 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003717 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003718 goto drop;
3719 }
3720
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003721 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003722 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003723 if (req_seq_offset < 0)
3724 req_seq_offset += 64;
3725
3726 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003727 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003728 if (next_tx_seq_offset < 0)
3729 next_tx_seq_offset += 64;
3730
3731 /* check for invalid req-seq */
3732 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003733 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003734 goto drop;
3735 }
3736
3737 if (__is_iframe(control)) {
3738 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003739 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003740 goto drop;
3741 }
3742
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003743 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003744 } else {
3745 if (len != 0) {
3746 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003747 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003748 goto drop;
3749 }
3750
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003751 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003752 }
3753
3754 return 0;
3755
3756drop:
3757 kfree_skb(skb);
3758 return 0;
3759}
3760
Linus Torvalds1da177e2005-04-16 15:20:36 -07003761static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3762{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003763 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003764 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003765 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003766 u8 tx_seq;
3767 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003769 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003770 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771 BT_DBG("unknown cid 0x%4.4x", cid);
3772 goto drop;
3773 }
3774
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003775 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003776
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003777 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003779 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003780 goto drop;
3781
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003782 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003783 case L2CAP_MODE_BASIC:
3784 /* If socket recv buffers overflows we drop data here
3785 * which is *bad* because L2CAP has to be reliable.
3786 * But we don't have any other choice. L2CAP doesn't
3787 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003788
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003789 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003790 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003792 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003793 goto done;
3794 break;
3795
3796 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003797 if (!sock_owned_by_user(sk)) {
3798 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003799 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003800 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003801 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003802 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003803
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003804 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003805
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003806 case L2CAP_MODE_STREAMING:
3807 control = get_unaligned_le16(skb->data);
3808 skb_pull(skb, 2);
3809 len = skb->len;
3810
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003811 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003812 goto drop;
3813
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003814 if (__is_sar_start(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003815 len -= 2;
3816
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003817 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003818 len -= 2;
3819
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003820 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003821 goto drop;
3822
3823 tx_seq = __get_txseq(control);
3824
Mat Martineau84084a32011-07-22 14:54:00 -07003825 if (chan->expected_tx_seq != tx_seq) {
3826 /* Frame(s) missing - must discard partial SDU */
3827 kfree_skb(chan->sdu);
3828 chan->sdu = NULL;
3829 chan->sdu_last_frag = NULL;
3830 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003831
Mat Martineau84084a32011-07-22 14:54:00 -07003832 /* TODO: Notify userland of missing data */
3833 }
3834
3835 chan->expected_tx_seq = (tx_seq + 1) % 64;
3836
3837 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
3838 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003839
3840 goto done;
3841
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003842 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003843 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003844 break;
3845 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846
3847drop:
3848 kfree_skb(skb);
3849
3850done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003851 if (sk)
3852 bh_unlock_sock(sk);
3853
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854 return 0;
3855}
3856
Al Viro8e036fc2007-07-29 00:16:36 -07003857static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003859 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003860 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003862 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3863 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864 goto drop;
3865
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003866 sk = chan->sk;
3867
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003868 bh_lock_sock(sk);
3869
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870 BT_DBG("sk %p, len %d", sk, skb->len);
3871
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003872 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873 goto drop;
3874
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003875 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876 goto drop;
3877
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003878 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879 goto done;
3880
3881drop:
3882 kfree_skb(skb);
3883
3884done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003885 if (sk)
3886 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887 return 0;
3888}
3889
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003890static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3891{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003892 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003893 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003894
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003895 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3896 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003897 goto drop;
3898
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003899 sk = chan->sk;
3900
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003901 bh_lock_sock(sk);
3902
3903 BT_DBG("sk %p, len %d", sk, skb->len);
3904
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003905 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003906 goto drop;
3907
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003908 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003909 goto drop;
3910
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003911 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003912 goto done;
3913
3914drop:
3915 kfree_skb(skb);
3916
3917done:
3918 if (sk)
3919 bh_unlock_sock(sk);
3920 return 0;
3921}
3922
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3924{
3925 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003926 u16 cid, len;
3927 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928
3929 skb_pull(skb, L2CAP_HDR_SIZE);
3930 cid = __le16_to_cpu(lh->cid);
3931 len = __le16_to_cpu(lh->len);
3932
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003933 if (len != skb->len) {
3934 kfree_skb(skb);
3935 return;
3936 }
3937
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3939
3940 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003941 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003942 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943 l2cap_sig_channel(conn, skb);
3944 break;
3945
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003946 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003947 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948 skb_pull(skb, 2);
3949 l2cap_conless_channel(conn, psm, skb);
3950 break;
3951
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003952 case L2CAP_CID_LE_DATA:
3953 l2cap_att_channel(conn, cid, skb);
3954 break;
3955
Anderson Brigliab501d6a2011-06-07 18:46:31 -03003956 case L2CAP_CID_SMP:
3957 if (smp_sig_channel(conn, skb))
3958 l2cap_conn_del(conn->hcon, EACCES);
3959 break;
3960
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961 default:
3962 l2cap_data_channel(conn, cid, skb);
3963 break;
3964 }
3965}
3966
3967/* ---- L2CAP interface with lower layer (HCI) ---- */
3968
3969static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3970{
3971 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003972 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973
3974 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003975 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003976
3977 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3978
3979 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003980 read_lock(&chan_list_lock);
3981 list_for_each_entry(c, &chan_list, global_l) {
3982 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003983
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003984 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985 continue;
3986
3987 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003988 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03003989 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003990 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003992 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3993 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03003994 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003995 lm2 |= HCI_LM_MASTER;
3996 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003997 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003998 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999
4000 return exact ? lm1 : lm2;
4001}
4002
4003static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4004{
Marcel Holtmann01394182006-07-03 10:02:46 +02004005 struct l2cap_conn *conn;
4006
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4008
Ville Tervoacd7d372011-02-10 22:38:49 -03004009 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004010 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011
4012 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013 conn = l2cap_conn_add(hcon, status);
4014 if (conn)
4015 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004016 } else
Joe Perchese1750722011-06-29 18:18:29 -07004017 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018
4019 return 0;
4020}
4021
Marcel Holtmann2950f212009-02-12 14:02:50 +01004022static int l2cap_disconn_ind(struct hci_conn *hcon)
4023{
4024 struct l2cap_conn *conn = hcon->l2cap_data;
4025
4026 BT_DBG("hcon %p", hcon);
4027
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03004028 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004029 return 0x13;
4030
4031 return conn->disc_reason;
4032}
4033
4034static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035{
4036 BT_DBG("hcon %p reason %d", hcon, reason);
4037
Ville Tervoacd7d372011-02-10 22:38:49 -03004038 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004039 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004040
Joe Perchese1750722011-06-29 18:18:29 -07004041 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004042
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043 return 0;
4044}
4045
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004046static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004047{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004048 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004049 return;
4050
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004051 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004052 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004053 __clear_chan_timer(chan);
4054 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004055 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004056 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004057 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004058 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004059 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004060 }
4061}
4062
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004063static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004065 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004066 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067
Marcel Holtmann01394182006-07-03 10:02:46 +02004068 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004070
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071 BT_DBG("conn %p", conn);
4072
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004073 if (hcon->type == LE_LINK) {
4074 smp_distribute_keys(conn, 0);
4075 del_timer(&conn->security_timer);
4076 }
4077
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004078 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004080 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004081 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004082
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083 bh_lock_sock(sk);
4084
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004085 BT_DBG("chan->scid %d", chan->scid);
4086
4087 if (chan->scid == L2CAP_CID_LE_DATA) {
4088 if (!status && encrypt) {
4089 chan->sec_level = hcon->sec_level;
4090 l2cap_chan_ready(sk);
4091 }
4092
4093 bh_unlock_sock(sk);
4094 continue;
4095 }
4096
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004097 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004098 bh_unlock_sock(sk);
4099 continue;
4100 }
4101
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004102 if (!status && (chan->state == BT_CONNECTED ||
4103 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004104 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004105 bh_unlock_sock(sk);
4106 continue;
4107 }
4108
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004109 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004110 if (!status) {
4111 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004112 req.scid = cpu_to_le16(chan->scid);
4113 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004114
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004115 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004116 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004117
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004118 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004119 L2CAP_CONN_REQ, sizeof(req), &req);
4120 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004121 __clear_chan_timer(chan);
4122 __set_chan_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004123 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004124 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004125 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004126 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004127
4128 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004129 if (bt_sk(sk)->defer_setup) {
4130 struct sock *parent = bt_sk(sk)->parent;
4131 res = L2CAP_CR_PEND;
4132 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004133 if (parent)
4134 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004135 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004136 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004137 res = L2CAP_CR_SUCCESS;
4138 stat = L2CAP_CS_NO_INFO;
4139 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004140 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004141 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004142 __set_chan_timer(chan, HZ / 10);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004143 res = L2CAP_CR_SEC_BLOCK;
4144 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004145 }
4146
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004147 rsp.scid = cpu_to_le16(chan->dcid);
4148 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004149 rsp.result = cpu_to_le16(res);
4150 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004151 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4152 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153 }
4154
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155 bh_unlock_sock(sk);
4156 }
4157
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004158 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004159
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160 return 0;
4161}
4162
4163static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4164{
4165 struct l2cap_conn *conn = hcon->l2cap_data;
4166
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004167 if (!conn)
4168 conn = l2cap_conn_add(hcon, 0);
4169
4170 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171 goto drop;
4172
4173 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4174
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004175 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004177 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004178 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179 int len;
4180
4181 if (conn->rx_len) {
4182 BT_ERR("Unexpected start frame (len %d)", skb->len);
4183 kfree_skb(conn->rx_skb);
4184 conn->rx_skb = NULL;
4185 conn->rx_len = 0;
4186 l2cap_conn_unreliable(conn, ECOMM);
4187 }
4188
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004189 /* Start fragment always begin with Basic L2CAP header */
4190 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191 BT_ERR("Frame is too short (len %d)", skb->len);
4192 l2cap_conn_unreliable(conn, ECOMM);
4193 goto drop;
4194 }
4195
4196 hdr = (struct l2cap_hdr *) skb->data;
4197 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004198 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199
4200 if (len == skb->len) {
4201 /* Complete frame received */
4202 l2cap_recv_frame(conn, skb);
4203 return 0;
4204 }
4205
4206 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4207
4208 if (skb->len > len) {
4209 BT_ERR("Frame is too long (len %d, expected len %d)",
4210 skb->len, len);
4211 l2cap_conn_unreliable(conn, ECOMM);
4212 goto drop;
4213 }
4214
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004215 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004216
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004217 if (chan && chan->sk) {
4218 struct sock *sk = chan->sk;
4219
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004220 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004221 BT_ERR("Frame exceeding recv MTU (len %d, "
4222 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004223 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004224 bh_unlock_sock(sk);
4225 l2cap_conn_unreliable(conn, ECOMM);
4226 goto drop;
4227 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004228 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004229 }
4230
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004232 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4233 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004234 goto drop;
4235
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004236 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004237 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004238 conn->rx_len = len - skb->len;
4239 } else {
4240 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4241
4242 if (!conn->rx_len) {
4243 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4244 l2cap_conn_unreliable(conn, ECOMM);
4245 goto drop;
4246 }
4247
4248 if (skb->len > conn->rx_len) {
4249 BT_ERR("Fragment is too long (len %d, expected %d)",
4250 skb->len, conn->rx_len);
4251 kfree_skb(conn->rx_skb);
4252 conn->rx_skb = NULL;
4253 conn->rx_len = 0;
4254 l2cap_conn_unreliable(conn, ECOMM);
4255 goto drop;
4256 }
4257
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004258 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004259 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260 conn->rx_len -= skb->len;
4261
4262 if (!conn->rx_len) {
4263 /* Complete frame received */
4264 l2cap_recv_frame(conn, conn->rx_skb);
4265 conn->rx_skb = NULL;
4266 }
4267 }
4268
4269drop:
4270 kfree_skb(skb);
4271 return 0;
4272}
4273
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004274static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004275{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004276 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004277
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004278 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004280 list_for_each_entry(c, &chan_list, global_l) {
4281 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004283 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 +01004284 batostr(&bt_sk(sk)->src),
4285 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004286 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004287 c->scid, c->dcid, c->imtu, c->omtu,
4288 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004289}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004290
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004291 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004292
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004293 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004294}
4295
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004296static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4297{
4298 return single_open(file, l2cap_debugfs_show, inode->i_private);
4299}
4300
4301static const struct file_operations l2cap_debugfs_fops = {
4302 .open = l2cap_debugfs_open,
4303 .read = seq_read,
4304 .llseek = seq_lseek,
4305 .release = single_release,
4306};
4307
4308static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310static struct hci_proto l2cap_hci_proto = {
4311 .name = "L2CAP",
4312 .id = HCI_PROTO_L2CAP,
4313 .connect_ind = l2cap_connect_ind,
4314 .connect_cfm = l2cap_connect_cfm,
4315 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004316 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004317 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318 .recv_acldata = l2cap_recv_acldata
4319};
4320
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004321int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322{
4323 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004324
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004325 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326 if (err < 0)
4327 return err;
4328
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329 err = hci_register_proto(&l2cap_hci_proto);
4330 if (err < 0) {
4331 BT_ERR("L2CAP protocol registration failed");
4332 bt_sock_unregister(BTPROTO_L2CAP);
4333 goto error;
4334 }
4335
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004336 if (bt_debugfs) {
4337 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4338 bt_debugfs, NULL, &l2cap_debugfs_fops);
4339 if (!l2cap_debugfs)
4340 BT_ERR("Failed to create L2CAP debug file");
4341 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343 return 0;
4344
4345error:
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004346 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347 return err;
4348}
4349
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004350void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004351{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004352 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004353
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4355 BT_ERR("L2CAP protocol unregistration failed");
4356
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004357 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004358}
4359
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004360module_param(disable_ertm, bool, 0644);
4361MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03004362
4363module_param(enable_hs, bool, 0644);
4364MODULE_PARM_DESC(enable_hs, "Enable High Speed");