blob: 439e7150f1506163639744b470df3bcc114a4ab4 [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. Padovan710f9b02011-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;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300569 int count, hlen;
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
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300575 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
576 hlen = L2CAP_EXT_HDR_SIZE;
577 else
578 hlen = L2CAP_ENH_HDR_SIZE;
579
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300580 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300581 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300582
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300583 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300584
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300585 count = min_t(unsigned int, conn->mtu, hlen);
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +0300586
587 control |= __set_sframe(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300588
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300589 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +0300590 control |= __set_ctrl_final(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300591
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300592 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +0300593 control |= __set_ctrl_poll(chan);
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300594
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300595 skb = bt_skb_alloc(count, GFP_ATOMIC);
596 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300597 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300598
599 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300600 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300601 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300602 put_unaligned_le16(control, skb_put(skb, 2));
603
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300604 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300605 u16 fcs = crc16(0, (u8 *)lh, count - 2);
606 put_unaligned_le16(fcs, skb_put(skb, 2));
607 }
608
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200609 if (lmp_no_flush_capable(conn->hcon->hdev))
610 flags = ACL_START_NO_FLUSH;
611 else
612 flags = ACL_START;
613
Andrei Emeltchenko15770b12011-10-11 14:04:33 +0300614 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700615
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300616 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300617}
618
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300619static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300620{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300621 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300622 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300623 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300624 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300625 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300626
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300627 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300628
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300629 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300630}
631
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300632static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300633{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300634 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300635}
636
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300637static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200638{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300639 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200640
641 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100642 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
643 return;
644
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300645 if (l2cap_check_security(chan) &&
646 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200647 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300648 req.scid = cpu_to_le16(chan->scid);
649 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200650
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300651 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300652 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200653
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300654 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
655 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200656 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200657 } else {
658 struct l2cap_info_req req;
659 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
660
661 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
662 conn->info_ident = l2cap_get_ident(conn);
663
664 mod_timer(&conn->info_timer, jiffies +
665 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
666
667 l2cap_send_cmd(conn, conn->info_ident,
668 L2CAP_INFO_REQ, sizeof(req), &req);
669 }
670}
671
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300672static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
673{
674 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300675 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300676 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
677
678 switch (mode) {
679 case L2CAP_MODE_ERTM:
680 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
681 case L2CAP_MODE_STREAMING:
682 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
683 default:
684 return 0x00;
685 }
686}
687
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300688static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300689{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300690 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300691 struct l2cap_disconn_req req;
692
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300693 if (!conn)
694 return;
695
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300696 sk = chan->sk;
697
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300698 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300699 __clear_retrans_timer(chan);
700 __clear_monitor_timer(chan);
701 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300702 }
703
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300704 req.dcid = cpu_to_le16(chan->dcid);
705 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300706 l2cap_send_cmd(conn, l2cap_get_ident(conn),
707 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300708
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300709 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300710 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300711}
712
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200714static void l2cap_conn_start(struct l2cap_conn *conn)
715{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300716 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200717
718 BT_DBG("conn %p", conn);
719
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300720 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200721
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300722 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300723 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300724
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200725 bh_lock_sock(sk);
726
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300727 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200728 bh_unlock_sock(sk);
729 continue;
730 }
731
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300732 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300733 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300734
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300735 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300736 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300737 bh_unlock_sock(sk);
738 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200739 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300740
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300741 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
742 && test_bit(CONF_STATE2_DEVICE,
743 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300744 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300745 * so release the lock */
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300746 read_unlock(&conn->chan_lock);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300747 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300748 read_lock(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300749 bh_unlock_sock(sk);
750 continue;
751 }
752
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300753 req.scid = cpu_to_le16(chan->scid);
754 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300755
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300756 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300757 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300758
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300759 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
760 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300761
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300762 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200763 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300764 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300765 rsp.scid = cpu_to_le16(chan->dcid);
766 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200767
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300768 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100769 if (bt_sk(sk)->defer_setup) {
770 struct sock *parent = bt_sk(sk)->parent;
771 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
772 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000773 if (parent)
774 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100775
776 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300777 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100778 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
779 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
780 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200781 } else {
782 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
783 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
784 }
785
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300786 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
787 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300788
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300789 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300790 rsp.result != L2CAP_CR_SUCCESS) {
791 bh_unlock_sock(sk);
792 continue;
793 }
794
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300795 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300796 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300797 l2cap_build_conf_req(chan, buf), buf);
798 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200799 }
800
801 bh_unlock_sock(sk);
802 }
803
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300804 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200805}
806
Ville Tervob62f3282011-02-10 22:38:50 -0300807/* Find socket with cid and source bdaddr.
808 * Returns closest match, locked.
809 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300810static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300811{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300812 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300813
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300814 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300815
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300816 list_for_each_entry(c, &chan_list, global_l) {
817 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300818
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300819 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300820 continue;
821
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300822 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300823 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300824 if (!bacmp(&bt_sk(sk)->src, src)) {
825 read_unlock(&chan_list_lock);
826 return c;
827 }
Ville Tervob62f3282011-02-10 22:38:50 -0300828
829 /* Closest match */
830 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300831 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300832 }
833 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300834
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300835 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300836
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300837 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300838}
839
840static void l2cap_le_conn_ready(struct l2cap_conn *conn)
841{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300842 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300843 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300844
845 BT_DBG("");
846
847 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300848 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300849 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300850 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300851 return;
852
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300853 parent = pchan->sk;
854
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300855 bh_lock_sock(parent);
856
Ville Tervob62f3282011-02-10 22:38:50 -0300857 /* Check for backlog size */
858 if (sk_acceptq_is_full(parent)) {
859 BT_DBG("backlog full %d", parent->sk_ack_backlog);
860 goto clean;
861 }
862
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300863 chan = pchan->ops->new_connection(pchan->data);
864 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300865 goto clean;
866
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300867 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300868
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300869 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300870
871 hci_conn_hold(conn->hcon);
872
Ville Tervob62f3282011-02-10 22:38:50 -0300873 bacpy(&bt_sk(sk)->src, conn->src);
874 bacpy(&bt_sk(sk)->dst, conn->dst);
875
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300876 bt_accept_enqueue(parent, sk);
877
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300878 __l2cap_chan_add(conn, chan);
879
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300880 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300881
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300882 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300883 parent->sk_data_ready(parent, 0);
884
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300885 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300886
887clean:
888 bh_unlock_sock(parent);
889}
890
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300891static void l2cap_chan_ready(struct sock *sk)
892{
893 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
894 struct sock *parent = bt_sk(sk)->parent;
895
896 BT_DBG("sk %p, parent %p", sk, parent);
897
898 chan->conf_state = 0;
899 __clear_chan_timer(chan);
900
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300901 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300902 sk->sk_state_change(sk);
903
904 if (parent)
905 parent->sk_data_ready(parent, 0);
906}
907
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200908static void l2cap_conn_ready(struct l2cap_conn *conn)
909{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300910 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200911
912 BT_DBG("conn %p", conn);
913
Ville Tervob62f3282011-02-10 22:38:50 -0300914 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
915 l2cap_le_conn_ready(conn);
916
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300917 if (conn->hcon->out && conn->hcon->type == LE_LINK)
918 smp_conn_security(conn, conn->hcon->pending_sec_level);
919
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300920 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200921
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300922 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300923 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300924
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200925 bh_lock_sock(sk);
926
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300927 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300928 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300929 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300930
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300931 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300932 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300933 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200934 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300935
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300936 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300937 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200938
939 bh_unlock_sock(sk);
940 }
941
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300942 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200943}
944
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200945/* Notify sockets that we cannot guaranty reliability anymore */
946static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
947{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300948 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200949
950 BT_DBG("conn %p", conn);
951
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300952 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200953
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300954 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300955 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300956
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300957 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200958 sk->sk_err = err;
959 }
960
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300961 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200962}
963
964static void l2cap_info_timeout(unsigned long arg)
965{
966 struct l2cap_conn *conn = (void *) arg;
967
Marcel Holtmann984947d2009-02-06 23:35:19 +0100968 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100969 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100970
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200971 l2cap_conn_start(conn);
972}
973
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300974static void l2cap_conn_del(struct hci_conn *hcon, int err)
975{
976 struct l2cap_conn *conn = hcon->l2cap_data;
977 struct l2cap_chan *chan, *l;
978 struct sock *sk;
979
980 if (!conn)
981 return;
982
983 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
984
985 kfree_skb(conn->rx_skb);
986
987 /* Kill channels */
988 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
989 sk = chan->sk;
990 bh_lock_sock(sk);
991 l2cap_chan_del(chan, err);
992 bh_unlock_sock(sk);
993 chan->ops->close(chan->data);
994 }
995
996 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
997 del_timer_sync(&conn->info_timer);
998
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300999 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) {
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001000 del_timer(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001001 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001002 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001003
1004 hcon->l2cap_data = NULL;
1005 kfree(conn);
1006}
1007
1008static void security_timeout(unsigned long arg)
1009{
1010 struct l2cap_conn *conn = (void *) arg;
1011
1012 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1013}
1014
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1016{
Marcel Holtmann01394182006-07-03 10:02:46 +02001017 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018
Marcel Holtmann01394182006-07-03 10:02:46 +02001019 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 return conn;
1021
Marcel Holtmann01394182006-07-03 10:02:46 +02001022 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1023 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025
1026 hcon->l2cap_data = conn;
1027 conn->hcon = hcon;
1028
Marcel Holtmann01394182006-07-03 10:02:46 +02001029 BT_DBG("hcon %p conn %p", hcon, conn);
1030
Ville Tervoacd7d372011-02-10 22:38:49 -03001031 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1032 conn->mtu = hcon->hdev->le_mtu;
1033 else
1034 conn->mtu = hcon->hdev->acl_mtu;
1035
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 conn->src = &hcon->hdev->bdaddr;
1037 conn->dst = &hcon->dst;
1038
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001039 conn->feat_mask = 0;
1040
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001042 rwlock_init(&conn->chan_lock);
1043
1044 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001046 if (hcon->type == LE_LINK)
1047 setup_timer(&conn->security_timer, security_timeout,
1048 (unsigned long) conn);
1049 else
Ville Tervob62f3282011-02-10 22:38:50 -03001050 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +00001051 (unsigned long) conn);
1052
Marcel Holtmann2950f212009-02-12 14:02:50 +01001053 conn->disc_reason = 0x13;
1054
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 return conn;
1056}
1057
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001058static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001060 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001061 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001062 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063}
1064
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066
1067/* Find socket with psm and source bdaddr.
1068 * Returns closest match.
1069 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001070static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001072 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001074 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001075
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001076 list_for_each_entry(c, &chan_list, global_l) {
1077 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001078
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001079 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 continue;
1081
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001082 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001084 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001085 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001086 return c;
1087 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088
1089 /* Closest match */
1090 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001091 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 }
1093 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001095 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001096
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001097 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098}
1099
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001100int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001102 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 bdaddr_t *src = &bt_sk(sk)->src;
1104 bdaddr_t *dst = &bt_sk(sk)->dst;
1105 struct l2cap_conn *conn;
1106 struct hci_conn *hcon;
1107 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001108 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001109 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001111 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001112 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001114 hdev = hci_get_route(dst, src);
1115 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 return -EHOSTUNREACH;
1117
1118 hci_dev_lock_bh(hdev);
1119
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001120 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001121
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001122 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001123 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001124 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001125 else
1126 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001127 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001128
Ville Tervo30e76272011-02-22 16:10:53 -03001129 if (IS_ERR(hcon)) {
1130 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001132 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133
1134 conn = l2cap_conn_add(hcon, 0);
1135 if (!conn) {
1136 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001137 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 goto done;
1139 }
1140
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 /* Update source addr of the socket */
1142 bacpy(src, conn->src);
1143
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001144 l2cap_chan_add(conn, chan);
1145
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001146 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001147 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148
1149 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001150 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001151 __clear_chan_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001152 if (l2cap_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001153 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001154 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001155 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 }
1157
Ville Tervo30e76272011-02-22 16:10:53 -03001158 err = 0;
1159
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160done:
1161 hci_dev_unlock_bh(hdev);
1162 hci_dev_put(hdev);
1163 return err;
1164}
1165
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001166int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001167{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001168 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001169 DECLARE_WAITQUEUE(wait, current);
1170 int err = 0;
1171 int timeo = HZ/5;
1172
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001173 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001174 set_current_state(TASK_INTERRUPTIBLE);
1175 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001176 if (!timeo)
1177 timeo = HZ/5;
1178
1179 if (signal_pending(current)) {
1180 err = sock_intr_errno(timeo);
1181 break;
1182 }
1183
1184 release_sock(sk);
1185 timeo = schedule_timeout(timeo);
1186 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001187 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001188
1189 err = sock_error(sk);
1190 if (err)
1191 break;
1192 }
1193 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001194 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001195 return err;
1196}
1197
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001198static void l2cap_monitor_timeout(unsigned long arg)
1199{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001200 struct l2cap_chan *chan = (void *) arg;
1201 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001202
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001203 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001204
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001205 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001206 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001207 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001208 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001209 return;
1210 }
1211
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001212 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001213 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001214
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001215 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001216 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001217}
1218
1219static void l2cap_retrans_timeout(unsigned long arg)
1220{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001221 struct l2cap_chan *chan = (void *) arg;
1222 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001223
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001224 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001225
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001226 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001227 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001228 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001229
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001230 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001231
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001232 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001233 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001234}
1235
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001236static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001237{
1238 struct sk_buff *skb;
1239
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001240 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001241 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001242 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001243 break;
1244
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001245 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001246 kfree_skb(skb);
1247
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001248 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001249 }
1250
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001251 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001252 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001253}
1254
Szymon Janc67c9e842011-07-28 16:24:33 +02001255static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001256{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001257 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001258 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001259
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001260 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001261
Andrei Emeltchenkod57b0e82011-10-11 14:04:31 +03001262 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
1263 lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001264 flags = ACL_START_NO_FLUSH;
1265 else
1266 flags = ACL_START;
1267
Andrei Emeltchenko15770b12011-10-11 14:04:33 +03001268 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001269 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001270}
1271
Szymon Janc67c9e842011-07-28 16:24:33 +02001272static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001273{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001274 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001275 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001276
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001277 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001278 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001279 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001280 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001281
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001282 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001283 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1284 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001285 }
1286
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001287 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001288
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001289 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001290 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001291}
1292
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001293static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001294{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001295 struct sk_buff *skb, *tx_skb;
1296 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001297
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001298 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001299 if (!skb)
1300 return;
1301
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001302 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001303 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001304 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001305
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001306 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001307 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001308
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001309 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001310
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001311 if (chan->remote_max_tx &&
1312 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001313 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001314 return;
1315 }
1316
1317 tx_skb = skb_clone(skb, GFP_ATOMIC);
1318 bt_cb(skb)->retries++;
1319 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001320 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001321
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001322 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001323 control |= __set_ctrl_final(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001324
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001325 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001326 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001327
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001328 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1329
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001330 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001331 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1332 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1333 }
1334
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001335 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001336}
1337
Szymon Janc67c9e842011-07-28 16:24:33 +02001338static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001339{
1340 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001341 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001342 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001343
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001344 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001345 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001346
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001347 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001348
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001349 if (chan->remote_max_tx &&
1350 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001351 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001352 break;
1353 }
1354
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001355 tx_skb = skb_clone(skb, GFP_ATOMIC);
1356
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001357 bt_cb(skb)->retries++;
1358
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001359 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001360 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001361
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001362 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001363 control |= __set_ctrl_final(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001364
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001365 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001366 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001367 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1368
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001369
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001370 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001371 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1372 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1373 }
1374
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001375 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001376
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001377 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001378
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001379 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1380 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001381
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301382 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001383 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301384
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001385 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001386
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001387 if (skb_queue_is_last(&chan->tx_q, skb))
1388 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001389 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001390 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001391
1392 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001393 }
1394
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001395 return nsent;
1396}
1397
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001398static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001399{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001400 int ret;
1401
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001402 if (!skb_queue_empty(&chan->tx_q))
1403 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001404
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001405 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001406 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001407 return ret;
1408}
1409
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001410static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001411{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001412 u16 control = 0;
1413
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001414 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001415
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001416 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001417 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001418 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001419 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001420 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001421 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001422
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001423 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001424 return;
1425
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001426 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001427 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001428}
1429
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001430static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001431{
1432 struct srej_list *tail;
1433 u16 control;
1434
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001435 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001436 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001437
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001438 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001439 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001440
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001441 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001442}
1443
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001444static 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 -07001445{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001446 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001447 struct sk_buff **frag;
1448 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001450 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001451 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452
1453 sent += count;
1454 len -= count;
1455
1456 /* Continuation fragments (no L2CAP header) */
1457 frag = &skb_shinfo(skb)->frag_list;
1458 while (len) {
1459 count = min_t(unsigned int, conn->mtu, len);
1460
1461 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1462 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001463 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001464 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1465 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
1467 sent += count;
1468 len -= count;
1469
1470 frag = &(*frag)->next;
1471 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472
1473 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001474}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475
Szymon Janc67c9e842011-07-28 16:24:33 +02001476static 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 -03001477{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001478 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001479 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001480 struct sk_buff *skb;
1481 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1482 struct l2cap_hdr *lh;
1483
1484 BT_DBG("sk %p len %d", sk, (int)len);
1485
1486 count = min_t(unsigned int, (conn->mtu - hlen), len);
1487 skb = bt_skb_send_alloc(sk, count + hlen,
1488 msg->msg_flags & MSG_DONTWAIT, &err);
1489 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001490 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001491
1492 /* Create L2CAP header */
1493 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001494 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001495 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001496 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001497
1498 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1499 if (unlikely(err < 0)) {
1500 kfree_skb(skb);
1501 return ERR_PTR(err);
1502 }
1503 return skb;
1504}
1505
Szymon Janc67c9e842011-07-28 16:24:33 +02001506static 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 -03001507{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001508 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001509 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001510 struct sk_buff *skb;
1511 int err, count, hlen = L2CAP_HDR_SIZE;
1512 struct l2cap_hdr *lh;
1513
1514 BT_DBG("sk %p len %d", sk, (int)len);
1515
1516 count = min_t(unsigned int, (conn->mtu - hlen), len);
1517 skb = bt_skb_send_alloc(sk, count + hlen,
1518 msg->msg_flags & MSG_DONTWAIT, &err);
1519 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001520 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001521
1522 /* Create L2CAP header */
1523 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001524 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001525 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1526
1527 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1528 if (unlikely(err < 0)) {
1529 kfree_skb(skb);
1530 return ERR_PTR(err);
1531 }
1532 return skb;
1533}
1534
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001535static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1536 struct msghdr *msg, size_t len,
1537 u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001538{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001539 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001540 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001541 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001542 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001543 struct l2cap_hdr *lh;
1544
1545 BT_DBG("sk %p len %d", sk, (int)len);
1546
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001547 if (!conn)
1548 return ERR_PTR(-ENOTCONN);
1549
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001550 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1551 hlen = L2CAP_EXT_HDR_SIZE;
1552 else
1553 hlen = L2CAP_ENH_HDR_SIZE;
1554
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001555 if (sdulen)
1556 hlen += 2;
1557
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001558 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001559 hlen += 2;
1560
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001561 count = min_t(unsigned int, (conn->mtu - hlen), len);
1562 skb = bt_skb_send_alloc(sk, count + hlen,
1563 msg->msg_flags & MSG_DONTWAIT, &err);
1564 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001565 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001566
1567 /* Create L2CAP header */
1568 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001569 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001570 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1571 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001572 if (sdulen)
1573 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001574
1575 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1576 if (unlikely(err < 0)) {
1577 kfree_skb(skb);
1578 return ERR_PTR(err);
1579 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001580
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001581 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001582 put_unaligned_le16(0, skb_put(skb, 2));
1583
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001584 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001585 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586}
1587
Szymon Janc67c9e842011-07-28 16:24:33 +02001588static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001589{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001590 struct sk_buff *skb;
1591 struct sk_buff_head sar_queue;
1592 u16 control;
1593 size_t size = 0;
1594
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001595 skb_queue_head_init(&sar_queue);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001596 control = __set_ctrl_sar(chan, L2CAP_SAR_START);
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001597 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001598 if (IS_ERR(skb))
1599 return PTR_ERR(skb);
1600
1601 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001602 len -= chan->remote_mps;
1603 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001604
1605 while (len > 0) {
1606 size_t buflen;
1607
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001608 if (len > chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001609 control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001610 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001611 } else {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001612 control = __set_ctrl_sar(chan, L2CAP_SAR_END);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001613 buflen = len;
1614 }
1615
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001616 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001617 if (IS_ERR(skb)) {
1618 skb_queue_purge(&sar_queue);
1619 return PTR_ERR(skb);
1620 }
1621
1622 __skb_queue_tail(&sar_queue, skb);
1623 len -= buflen;
1624 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001625 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001626 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1627 if (chan->tx_send_head == NULL)
1628 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001629
1630 return size;
1631}
1632
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001633int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1634{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001635 struct sk_buff *skb;
1636 u16 control;
1637 int err;
1638
1639 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001640 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001641 skb = l2cap_create_connless_pdu(chan, msg, len);
1642 if (IS_ERR(skb))
1643 return PTR_ERR(skb);
1644
1645 l2cap_do_send(chan, skb);
1646 return len;
1647 }
1648
1649 switch (chan->mode) {
1650 case L2CAP_MODE_BASIC:
1651 /* Check outgoing MTU */
1652 if (len > chan->omtu)
1653 return -EMSGSIZE;
1654
1655 /* Create a basic PDU */
1656 skb = l2cap_create_basic_pdu(chan, msg, len);
1657 if (IS_ERR(skb))
1658 return PTR_ERR(skb);
1659
1660 l2cap_do_send(chan, skb);
1661 err = len;
1662 break;
1663
1664 case L2CAP_MODE_ERTM:
1665 case L2CAP_MODE_STREAMING:
1666 /* Entire SDU fits into one PDU */
1667 if (len <= chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001668 control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001669 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1670 0);
1671 if (IS_ERR(skb))
1672 return PTR_ERR(skb);
1673
1674 __skb_queue_tail(&chan->tx_q, skb);
1675
1676 if (chan->tx_send_head == NULL)
1677 chan->tx_send_head = skb;
1678
1679 } else {
1680 /* Segment SDU into multiples PDUs */
1681 err = l2cap_sar_segment_sdu(chan, msg, len);
1682 if (err < 0)
1683 return err;
1684 }
1685
1686 if (chan->mode == L2CAP_MODE_STREAMING) {
1687 l2cap_streaming_send(chan);
1688 err = len;
1689 break;
1690 }
1691
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001692 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1693 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001694 err = len;
1695 break;
1696 }
1697
1698 err = l2cap_ertm_send(chan);
1699 if (err >= 0)
1700 err = len;
1701
1702 break;
1703
1704 default:
1705 BT_DBG("bad state %1.1x", chan->mode);
1706 err = -EBADFD;
1707 }
1708
1709 return err;
1710}
1711
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712/* Copy frame to all raw sockets on that connection */
1713static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1714{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001716 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717
1718 BT_DBG("conn %p", conn);
1719
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001720 read_lock(&conn->chan_lock);
1721 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001722 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001723 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724 continue;
1725
1726 /* Don't send frame to the socket it came from */
1727 if (skb->sk == sk)
1728 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001729 nskb = skb_clone(skb, GFP_ATOMIC);
1730 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 continue;
1732
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001733 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 kfree_skb(nskb);
1735 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001736 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737}
1738
1739/* ---- L2CAP signalling commands ---- */
1740static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1741 u8 code, u8 ident, u16 dlen, void *data)
1742{
1743 struct sk_buff *skb, **frag;
1744 struct l2cap_cmd_hdr *cmd;
1745 struct l2cap_hdr *lh;
1746 int len, count;
1747
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001748 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1749 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750
1751 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1752 count = min_t(unsigned int, conn->mtu, len);
1753
1754 skb = bt_skb_alloc(count, GFP_ATOMIC);
1755 if (!skb)
1756 return NULL;
1757
1758 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001759 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001760
1761 if (conn->hcon->type == LE_LINK)
1762 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1763 else
1764 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765
1766 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1767 cmd->code = code;
1768 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001769 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770
1771 if (dlen) {
1772 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1773 memcpy(skb_put(skb, count), data, count);
1774 data += count;
1775 }
1776
1777 len -= skb->len;
1778
1779 /* Continuation fragments (no L2CAP header) */
1780 frag = &skb_shinfo(skb)->frag_list;
1781 while (len) {
1782 count = min_t(unsigned int, conn->mtu, len);
1783
1784 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1785 if (!*frag)
1786 goto fail;
1787
1788 memcpy(skb_put(*frag, count), data, count);
1789
1790 len -= count;
1791 data += count;
1792
1793 frag = &(*frag)->next;
1794 }
1795
1796 return skb;
1797
1798fail:
1799 kfree_skb(skb);
1800 return NULL;
1801}
1802
1803static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1804{
1805 struct l2cap_conf_opt *opt = *ptr;
1806 int len;
1807
1808 len = L2CAP_CONF_OPT_SIZE + opt->len;
1809 *ptr += len;
1810
1811 *type = opt->type;
1812 *olen = opt->len;
1813
1814 switch (opt->len) {
1815 case 1:
1816 *val = *((u8 *) opt->val);
1817 break;
1818
1819 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001820 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821 break;
1822
1823 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001824 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825 break;
1826
1827 default:
1828 *val = (unsigned long) opt->val;
1829 break;
1830 }
1831
1832 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1833 return len;
1834}
1835
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1837{
1838 struct l2cap_conf_opt *opt = *ptr;
1839
1840 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1841
1842 opt->type = type;
1843 opt->len = len;
1844
1845 switch (len) {
1846 case 1:
1847 *((u8 *) opt->val) = val;
1848 break;
1849
1850 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001851 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 break;
1853
1854 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001855 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856 break;
1857
1858 default:
1859 memcpy(opt->val, (void *) val, len);
1860 break;
1861 }
1862
1863 *ptr += L2CAP_CONF_OPT_SIZE + len;
1864}
1865
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001866static void l2cap_ack_timeout(unsigned long arg)
1867{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001868 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001869
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001870 bh_lock_sock(chan->sk);
1871 l2cap_send_ack(chan);
1872 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001873}
1874
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001875static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001876{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001877 struct sock *sk = chan->sk;
1878
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001879 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001880 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001881 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001882 chan->num_acked = 0;
1883 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001884
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001885 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1886 (unsigned long) chan);
1887 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1888 (unsigned long) chan);
1889 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001890
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001891 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001892
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001893 INIT_LIST_HEAD(&chan->srej_l);
1894
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001895
1896 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001897}
1898
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001899static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1900{
1901 switch (mode) {
1902 case L2CAP_MODE_STREAMING:
1903 case L2CAP_MODE_ERTM:
1904 if (l2cap_mode_supported(mode, remote_feat_mask))
1905 return mode;
1906 /* fall through */
1907 default:
1908 return L2CAP_MODE_BASIC;
1909 }
1910}
1911
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001912static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
1913{
1914 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
1915}
1916
1917static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
1918{
1919 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
1920 __l2cap_ews_supported(chan))
1921 /* use extended control field */
1922 set_bit(FLAG_EXT_CTRL, &chan->flags);
1923 else
1924 chan->tx_win = min_t(u16, chan->tx_win,
1925 L2CAP_DEFAULT_TX_WINDOW);
1926}
1927
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001928static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001931 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 void *ptr = req->data;
1933
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001934 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001936 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001937 goto done;
1938
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001939 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001940 case L2CAP_MODE_STREAMING:
1941 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001942 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001943 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001944
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001945 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001946 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001947 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001948 break;
1949 }
1950
1951done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001952 if (chan->imtu != L2CAP_DEFAULT_MTU)
1953 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001954
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001955 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001956 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001957 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1958 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001959 break;
1960
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001961 rfc.mode = L2CAP_MODE_BASIC;
1962 rfc.txwin_size = 0;
1963 rfc.max_transmit = 0;
1964 rfc.retrans_timeout = 0;
1965 rfc.monitor_timeout = 0;
1966 rfc.max_pdu_size = 0;
1967
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001968 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1969 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001970 break;
1971
1972 case L2CAP_MODE_ERTM:
1973 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001974 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001975 rfc.retrans_timeout = 0;
1976 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001977 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001978 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1979 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001980
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001981 l2cap_txwin_setup(chan);
1982
1983 rfc.txwin_size = min_t(u16, chan->tx_win,
1984 L2CAP_DEFAULT_TX_WINDOW);
1985
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001986 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1987 (unsigned long) &rfc);
1988
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001989 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001990 break;
1991
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001992 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001993 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001994 chan->fcs = L2CAP_FCS_NONE;
1995 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001996 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001997
1998 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1999 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2000 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002001 break;
2002
2003 case L2CAP_MODE_STREAMING:
2004 rfc.mode = L2CAP_MODE_STREAMING;
2005 rfc.txwin_size = 0;
2006 rfc.max_transmit = 0;
2007 rfc.retrans_timeout = 0;
2008 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002009 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002010 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
2011 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002012
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002013 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2014 (unsigned long) &rfc);
2015
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002016 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002017 break;
2018
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002019 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002020 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002021 chan->fcs = L2CAP_FCS_NONE;
2022 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002023 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002024 break;
2025 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002027 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002028 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029
2030 return ptr - data;
2031}
2032
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002033static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002035 struct l2cap_conf_rsp *rsp = data;
2036 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002037 void *req = chan->conf_req;
2038 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002039 int type, hint, olen;
2040 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002041 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002042 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002043 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002045 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002046
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002047 while (len >= L2CAP_CONF_OPT_SIZE) {
2048 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002050 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002051 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002052
2053 switch (type) {
2054 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002055 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002056 break;
2057
2058 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002059 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002060 break;
2061
2062 case L2CAP_CONF_QOS:
2063 break;
2064
Marcel Holtmann6464f352007-10-20 13:39:51 +02002065 case L2CAP_CONF_RFC:
2066 if (olen == sizeof(rfc))
2067 memcpy(&rfc, (void *) val, olen);
2068 break;
2069
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002070 case L2CAP_CONF_FCS:
2071 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002072 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002073
2074 break;
2075
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002076 case L2CAP_CONF_EWS:
2077 if (!enable_hs)
2078 return -ECONNREFUSED;
2079
2080 set_bit(FLAG_EXT_CTRL, &chan->flags);
2081 set_bit(CONF_EWS_RECV, &chan->conf_state);
2082 chan->remote_tx_win = val;
2083 break;
2084
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002085 default:
2086 if (hint)
2087 break;
2088
2089 result = L2CAP_CONF_UNKNOWN;
2090 *((u8 *) ptr++) = type;
2091 break;
2092 }
2093 }
2094
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002095 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002096 goto done;
2097
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002098 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002099 case L2CAP_MODE_STREAMING:
2100 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002101 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002102 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002103 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002104 break;
2105 }
2106
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002107 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002108 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002109
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002110 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002111 }
2112
2113done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002114 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002115 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002116 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002117
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002118 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002119 return -ECONNREFUSED;
2120
2121 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2122 sizeof(rfc), (unsigned long) &rfc);
2123 }
2124
2125
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002126 if (result == L2CAP_CONF_SUCCESS) {
2127 /* Configure output options and let the other side know
2128 * which ones we don't like. */
2129
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002130 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2131 result = L2CAP_CONF_UNACCEPT;
2132 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002133 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002134 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002135 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002136 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002137
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002138 switch (rfc.mode) {
2139 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002140 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002141 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002142 break;
2143
2144 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002145 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2146 chan->remote_tx_win = rfc.txwin_size;
2147 else
2148 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2149
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002150 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002151
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002152 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2153 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002154
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002155 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002156
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002157 rfc.retrans_timeout =
2158 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2159 rfc.monitor_timeout =
2160 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002161
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002162 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002163
2164 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2165 sizeof(rfc), (unsigned long) &rfc);
2166
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002167 break;
2168
2169 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002170 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2171 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002172
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002173 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002174
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002175 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002176
2177 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2178 sizeof(rfc), (unsigned long) &rfc);
2179
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002180 break;
2181
2182 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002183 result = L2CAP_CONF_UNACCEPT;
2184
2185 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002186 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002187 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002188
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002189 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002190 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002191 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002192 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002193 rsp->result = cpu_to_le16(result);
2194 rsp->flags = cpu_to_le16(0x0000);
2195
2196 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197}
2198
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002199static 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 -03002200{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002201 struct l2cap_conf_req *req = data;
2202 void *ptr = req->data;
2203 int type, olen;
2204 unsigned long val;
2205 struct l2cap_conf_rfc rfc;
2206
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002207 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002208
2209 while (len >= L2CAP_CONF_OPT_SIZE) {
2210 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2211
2212 switch (type) {
2213 case L2CAP_CONF_MTU:
2214 if (val < L2CAP_DEFAULT_MIN_MTU) {
2215 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002216 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002217 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002218 chan->imtu = val;
2219 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002220 break;
2221
2222 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002223 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002224 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002225 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002226 break;
2227
2228 case L2CAP_CONF_RFC:
2229 if (olen == sizeof(rfc))
2230 memcpy(&rfc, (void *)val, olen);
2231
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002232 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002233 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002234 return -ECONNREFUSED;
2235
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002236 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002237
2238 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2239 sizeof(rfc), (unsigned long) &rfc);
2240 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002241
2242 case L2CAP_CONF_EWS:
2243 chan->tx_win = min_t(u16, val,
2244 L2CAP_DEFAULT_EXT_WINDOW);
2245 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS,
2246 2, chan->tx_win);
2247 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002248 }
2249 }
2250
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002251 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002252 return -ECONNREFUSED;
2253
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002254 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002255
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002256 if (*result == L2CAP_CONF_SUCCESS) {
2257 switch (rfc.mode) {
2258 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002259 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2260 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2261 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002262 break;
2263 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002264 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002265 }
2266 }
2267
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002268 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002269 req->flags = cpu_to_le16(0x0000);
2270
2271 return ptr - data;
2272}
2273
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002274static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275{
2276 struct l2cap_conf_rsp *rsp = data;
2277 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002279 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002281 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002282 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002283 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284
2285 return ptr - data;
2286}
2287
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002288void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002289{
2290 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002291 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002292 u8 buf[128];
2293
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002294 rsp.scid = cpu_to_le16(chan->dcid);
2295 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002296 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2297 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2298 l2cap_send_cmd(conn, chan->ident,
2299 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2300
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002301 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002302 return;
2303
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002304 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2305 l2cap_build_conf_req(chan, buf), buf);
2306 chan->num_conf_req++;
2307}
2308
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002309static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002310{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002311 int type, olen;
2312 unsigned long val;
2313 struct l2cap_conf_rfc rfc;
2314
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002315 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002316
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002317 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002318 return;
2319
2320 while (len >= L2CAP_CONF_OPT_SIZE) {
2321 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2322
2323 switch (type) {
2324 case L2CAP_CONF_RFC:
2325 if (olen == sizeof(rfc))
2326 memcpy(&rfc, (void *)val, olen);
2327 goto done;
2328 }
2329 }
2330
2331done:
2332 switch (rfc.mode) {
2333 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002334 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2335 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2336 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002337 break;
2338 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002339 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002340 }
2341}
2342
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002343static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2344{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002345 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002346
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002347 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002348 return 0;
2349
2350 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2351 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002352 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002353
2354 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002355 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002356
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002357 l2cap_conn_start(conn);
2358 }
2359
2360 return 0;
2361}
2362
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2364{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2366 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002367 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002368 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002369 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370
2371 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002372 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373
2374 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2375
2376 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002377 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2378 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379 result = L2CAP_CR_BAD_PSM;
2380 goto sendresp;
2381 }
2382
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002383 parent = pchan->sk;
2384
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002385 bh_lock_sock(parent);
2386
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002387 /* Check if the ACL is secure enough (if not SDP) */
2388 if (psm != cpu_to_le16(0x0001) &&
2389 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002390 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002391 result = L2CAP_CR_SEC_BLOCK;
2392 goto response;
2393 }
2394
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 result = L2CAP_CR_NO_MEM;
2396
2397 /* Check for backlog size */
2398 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002399 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 goto response;
2401 }
2402
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002403 chan = pchan->ops->new_connection(pchan->data);
2404 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 goto response;
2406
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002407 sk = chan->sk;
2408
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002409 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410
2411 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002412 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2413 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002415 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416 goto response;
2417 }
2418
2419 hci_conn_hold(conn->hcon);
2420
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 bacpy(&bt_sk(sk)->src, conn->src);
2422 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002423 chan->psm = psm;
2424 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002426 bt_accept_enqueue(parent, sk);
2427
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002428 __l2cap_chan_add(conn, chan);
2429
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002430 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002432 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002434 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435
Marcel Holtmann984947d2009-02-06 23:35:19 +01002436 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002437 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002438 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002439 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002440 result = L2CAP_CR_PEND;
2441 status = L2CAP_CS_AUTHOR_PEND;
2442 parent->sk_data_ready(parent, 0);
2443 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002444 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002445 result = L2CAP_CR_SUCCESS;
2446 status = L2CAP_CS_NO_INFO;
2447 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002448 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002449 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002450 result = L2CAP_CR_PEND;
2451 status = L2CAP_CS_AUTHEN_PEND;
2452 }
2453 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002454 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002455 result = L2CAP_CR_PEND;
2456 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 }
2458
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002459 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460
2461response:
2462 bh_unlock_sock(parent);
2463
2464sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002465 rsp.scid = cpu_to_le16(scid);
2466 rsp.dcid = cpu_to_le16(dcid);
2467 rsp.result = cpu_to_le16(result);
2468 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002470
2471 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2472 struct l2cap_info_req info;
2473 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2474
2475 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2476 conn->info_ident = l2cap_get_ident(conn);
2477
2478 mod_timer(&conn->info_timer, jiffies +
2479 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2480
2481 l2cap_send_cmd(conn, conn->info_ident,
2482 L2CAP_INFO_REQ, sizeof(info), &info);
2483 }
2484
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002485 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002486 result == L2CAP_CR_SUCCESS) {
2487 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002488 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002489 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002490 l2cap_build_conf_req(chan, buf), buf);
2491 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002492 }
2493
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494 return 0;
2495}
2496
2497static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2498{
2499 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2500 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002501 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502 struct sock *sk;
2503 u8 req[128];
2504
2505 scid = __le16_to_cpu(rsp->scid);
2506 dcid = __le16_to_cpu(rsp->dcid);
2507 result = __le16_to_cpu(rsp->result);
2508 status = __le16_to_cpu(rsp->status);
2509
2510 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2511
2512 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002513 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002514 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002515 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002517 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002518 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002519 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520 }
2521
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002522 sk = chan->sk;
2523
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524 switch (result) {
2525 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002526 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002527 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002528 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002529 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002530
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002531 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002532 break;
2533
Linus Torvalds1da177e2005-04-16 15:20:36 -07002534 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002535 l2cap_build_conf_req(chan, req), req);
2536 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537 break;
2538
2539 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002540 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541 break;
2542
2543 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002544 /* don't delete l2cap channel if sk is owned by user */
2545 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002546 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002547 __clear_chan_timer(chan);
2548 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002549 break;
2550 }
2551
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002552 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553 break;
2554 }
2555
2556 bh_unlock_sock(sk);
2557 return 0;
2558}
2559
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002560static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002561{
2562 /* FCS is enabled only in ERTM or streaming mode, if one or both
2563 * sides request it.
2564 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002565 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002566 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002567 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002568 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002569}
2570
Al Viro88219a02007-07-29 00:17:25 -07002571static 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 -07002572{
2573 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2574 u16 dcid, flags;
2575 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002576 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002578 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579
2580 dcid = __le16_to_cpu(req->dcid);
2581 flags = __le16_to_cpu(req->flags);
2582
2583 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2584
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002585 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002586 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 return -ENOENT;
2588
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002589 sk = chan->sk;
2590
David S. Miller033b1142011-07-21 13:38:42 -07002591 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002592 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002593
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002594 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2595 rej.scid = cpu_to_le16(chan->scid);
2596 rej.dcid = cpu_to_le16(chan->dcid);
2597
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002598 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2599 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002600 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002601 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002602
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002603 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002604 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002605 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002606 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002607 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002608 L2CAP_CONF_REJECT, flags), rsp);
2609 goto unlock;
2610 }
2611
2612 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002613 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2614 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615
2616 if (flags & 0x0001) {
2617 /* Incomplete config. Send empty response. */
2618 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002619 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002620 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621 goto unlock;
2622 }
2623
2624 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002625 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002626 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002627 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002629 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002631 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002632 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002633
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002634 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002635 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002636
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002637 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002638 goto unlock;
2639
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002640 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002641 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002642
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002643 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002644
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002645 chan->next_tx_seq = 0;
2646 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002647 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002648 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002649 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002650
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002652 goto unlock;
2653 }
2654
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002655 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002656 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002658 l2cap_build_conf_req(chan, buf), buf);
2659 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660 }
2661
2662unlock:
2663 bh_unlock_sock(sk);
2664 return 0;
2665}
2666
2667static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2668{
2669 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2670 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002671 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002673 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674
2675 scid = __le16_to_cpu(rsp->scid);
2676 flags = __le16_to_cpu(rsp->flags);
2677 result = __le16_to_cpu(rsp->result);
2678
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002679 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2680 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002682 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002683 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 return 0;
2685
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002686 sk = chan->sk;
2687
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688 switch (result) {
2689 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002690 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691 break;
2692
2693 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002694 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002695 char req[64];
2696
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002697 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002698 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002699 goto done;
2700 }
2701
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002702 /* throw out any old stored conf requests */
2703 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002704 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2705 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002706 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002707 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002708 goto done;
2709 }
2710
2711 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2712 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002713 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002714 if (result != L2CAP_CONF_SUCCESS)
2715 goto done;
2716 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717 }
2718
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002719 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002720 sk->sk_err = ECONNRESET;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002721 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002722 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723 goto done;
2724 }
2725
2726 if (flags & 0x01)
2727 goto done;
2728
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002729 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002731 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002732 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002733
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002734 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002735 chan->next_tx_seq = 0;
2736 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002737 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002738 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002739 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002740
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741 l2cap_chan_ready(sk);
2742 }
2743
2744done:
2745 bh_unlock_sock(sk);
2746 return 0;
2747}
2748
2749static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2750{
2751 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2752 struct l2cap_disconn_rsp rsp;
2753 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002754 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755 struct sock *sk;
2756
2757 scid = __le16_to_cpu(req->scid);
2758 dcid = __le16_to_cpu(req->dcid);
2759
2760 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2761
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002762 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002763 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 return 0;
2765
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002766 sk = chan->sk;
2767
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002768 rsp.dcid = cpu_to_le16(chan->scid);
2769 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2771
2772 sk->sk_shutdown = SHUTDOWN_MASK;
2773
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002774 /* don't delete l2cap channel if sk is owned by user */
2775 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002776 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002777 __clear_chan_timer(chan);
2778 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002779 bh_unlock_sock(sk);
2780 return 0;
2781 }
2782
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002783 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784 bh_unlock_sock(sk);
2785
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002786 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787 return 0;
2788}
2789
2790static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2791{
2792 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2793 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002794 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795 struct sock *sk;
2796
2797 scid = __le16_to_cpu(rsp->scid);
2798 dcid = __le16_to_cpu(rsp->dcid);
2799
2800 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2801
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002802 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002803 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804 return 0;
2805
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002806 sk = chan->sk;
2807
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002808 /* don't delete l2cap channel if sk is owned by user */
2809 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002810 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002811 __clear_chan_timer(chan);
2812 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002813 bh_unlock_sock(sk);
2814 return 0;
2815 }
2816
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002817 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818 bh_unlock_sock(sk);
2819
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002820 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821 return 0;
2822}
2823
2824static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2825{
2826 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002827 u16 type;
2828
2829 type = __le16_to_cpu(req->type);
2830
2831 BT_DBG("type 0x%4.4x", type);
2832
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002833 if (type == L2CAP_IT_FEAT_MASK) {
2834 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002835 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002836 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2837 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2838 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002839 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002840 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2841 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03002842 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002843 feat_mask |= L2CAP_FEAT_EXT_FLOW
2844 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03002845
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002846 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002847 l2cap_send_cmd(conn, cmd->ident,
2848 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002849 } else if (type == L2CAP_IT_FIXED_CHAN) {
2850 u8 buf[12];
2851 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2852 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2853 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2854 memcpy(buf + 4, l2cap_fixed_chan, 8);
2855 l2cap_send_cmd(conn, cmd->ident,
2856 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002857 } else {
2858 struct l2cap_info_rsp rsp;
2859 rsp.type = cpu_to_le16(type);
2860 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2861 l2cap_send_cmd(conn, cmd->ident,
2862 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2863 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864
2865 return 0;
2866}
2867
2868static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2869{
2870 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2871 u16 type, result;
2872
2873 type = __le16_to_cpu(rsp->type);
2874 result = __le16_to_cpu(rsp->result);
2875
2876 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2877
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002878 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2879 if (cmd->ident != conn->info_ident ||
2880 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2881 return 0;
2882
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002883 del_timer(&conn->info_timer);
2884
Ville Tervoadb08ed2010-08-04 09:43:33 +03002885 if (result != L2CAP_IR_SUCCESS) {
2886 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2887 conn->info_ident = 0;
2888
2889 l2cap_conn_start(conn);
2890
2891 return 0;
2892 }
2893
Marcel Holtmann984947d2009-02-06 23:35:19 +01002894 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002895 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002896
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002897 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002898 struct l2cap_info_req req;
2899 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2900
2901 conn->info_ident = l2cap_get_ident(conn);
2902
2903 l2cap_send_cmd(conn, conn->info_ident,
2904 L2CAP_INFO_REQ, sizeof(req), &req);
2905 } else {
2906 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2907 conn->info_ident = 0;
2908
2909 l2cap_conn_start(conn);
2910 }
2911 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002912 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002913 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002914
2915 l2cap_conn_start(conn);
2916 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002917
Linus Torvalds1da177e2005-04-16 15:20:36 -07002918 return 0;
2919}
2920
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002921static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002922 u16 to_multiplier)
2923{
2924 u16 max_latency;
2925
2926 if (min > max || min < 6 || max > 3200)
2927 return -EINVAL;
2928
2929 if (to_multiplier < 10 || to_multiplier > 3200)
2930 return -EINVAL;
2931
2932 if (max >= to_multiplier * 8)
2933 return -EINVAL;
2934
2935 max_latency = (to_multiplier * 8 / max) - 1;
2936 if (latency > 499 || latency > max_latency)
2937 return -EINVAL;
2938
2939 return 0;
2940}
2941
2942static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2943 struct l2cap_cmd_hdr *cmd, u8 *data)
2944{
2945 struct hci_conn *hcon = conn->hcon;
2946 struct l2cap_conn_param_update_req *req;
2947 struct l2cap_conn_param_update_rsp rsp;
2948 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002949 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002950
2951 if (!(hcon->link_mode & HCI_LM_MASTER))
2952 return -EINVAL;
2953
2954 cmd_len = __le16_to_cpu(cmd->len);
2955 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2956 return -EPROTO;
2957
2958 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002959 min = __le16_to_cpu(req->min);
2960 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002961 latency = __le16_to_cpu(req->latency);
2962 to_multiplier = __le16_to_cpu(req->to_multiplier);
2963
2964 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2965 min, max, latency, to_multiplier);
2966
2967 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002968
2969 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2970 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002971 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2972 else
2973 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2974
2975 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2976 sizeof(rsp), &rsp);
2977
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002978 if (!err)
2979 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2980
Claudio Takahaside731152011-02-11 19:28:55 -02002981 return 0;
2982}
2983
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002984static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2985 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2986{
2987 int err = 0;
2988
2989 switch (cmd->code) {
2990 case L2CAP_COMMAND_REJ:
2991 l2cap_command_rej(conn, cmd, data);
2992 break;
2993
2994 case L2CAP_CONN_REQ:
2995 err = l2cap_connect_req(conn, cmd, data);
2996 break;
2997
2998 case L2CAP_CONN_RSP:
2999 err = l2cap_connect_rsp(conn, cmd, data);
3000 break;
3001
3002 case L2CAP_CONF_REQ:
3003 err = l2cap_config_req(conn, cmd, cmd_len, data);
3004 break;
3005
3006 case L2CAP_CONF_RSP:
3007 err = l2cap_config_rsp(conn, cmd, data);
3008 break;
3009
3010 case L2CAP_DISCONN_REQ:
3011 err = l2cap_disconnect_req(conn, cmd, data);
3012 break;
3013
3014 case L2CAP_DISCONN_RSP:
3015 err = l2cap_disconnect_rsp(conn, cmd, data);
3016 break;
3017
3018 case L2CAP_ECHO_REQ:
3019 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3020 break;
3021
3022 case L2CAP_ECHO_RSP:
3023 break;
3024
3025 case L2CAP_INFO_REQ:
3026 err = l2cap_information_req(conn, cmd, data);
3027 break;
3028
3029 case L2CAP_INFO_RSP:
3030 err = l2cap_information_rsp(conn, cmd, data);
3031 break;
3032
3033 default:
3034 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3035 err = -EINVAL;
3036 break;
3037 }
3038
3039 return err;
3040}
3041
3042static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3043 struct l2cap_cmd_hdr *cmd, u8 *data)
3044{
3045 switch (cmd->code) {
3046 case L2CAP_COMMAND_REJ:
3047 return 0;
3048
3049 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003050 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003051
3052 case L2CAP_CONN_PARAM_UPDATE_RSP:
3053 return 0;
3054
3055 default:
3056 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3057 return -EINVAL;
3058 }
3059}
3060
3061static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3062 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063{
3064 u8 *data = skb->data;
3065 int len = skb->len;
3066 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003067 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068
3069 l2cap_raw_recv(conn, skb);
3070
3071 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003072 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3074 data += L2CAP_CMD_HDR_SIZE;
3075 len -= L2CAP_CMD_HDR_SIZE;
3076
Al Viro88219a02007-07-29 00:17:25 -07003077 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078
Al Viro88219a02007-07-29 00:17:25 -07003079 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 -07003080
Al Viro88219a02007-07-29 00:17:25 -07003081 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082 BT_DBG("corrupted command");
3083 break;
3084 }
3085
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003086 if (conn->hcon->type == LE_LINK)
3087 err = l2cap_le_sig_cmd(conn, &cmd, data);
3088 else
3089 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003090
3091 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003092 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003093
3094 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095
3096 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003097 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3099 }
3100
Al Viro88219a02007-07-29 00:17:25 -07003101 data += cmd_len;
3102 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103 }
3104
3105 kfree_skb(skb);
3106}
3107
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003108static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003109{
3110 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003111 int hdr_size;
3112
3113 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3114 hdr_size = L2CAP_EXT_HDR_SIZE;
3115 else
3116 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003117
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003118 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003119 skb_trim(skb, skb->len - 2);
3120 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3121 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3122
3123 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003124 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003125 }
3126 return 0;
3127}
3128
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003129static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003130{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003131 u16 control = 0;
3132
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003133 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003134
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003135 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003136
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003137 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003138 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003139 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003140 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003141 }
3142
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003143 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003144 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003145
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003146 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003147
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003148 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003149 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003150 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003151 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003152 }
3153}
3154
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003155static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003156{
3157 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003158 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003159
3160 bt_cb(skb)->tx_seq = tx_seq;
3161 bt_cb(skb)->sar = sar;
3162
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003163 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003164 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003165 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003166 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003167 }
3168
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003169 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003170 if (tx_seq_offset < 0)
3171 tx_seq_offset += 64;
3172
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003173 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003174 if (bt_cb(next_skb)->tx_seq == tx_seq)
3175 return -EINVAL;
3176
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003177 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003178 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003179 if (next_tx_seq_offset < 0)
3180 next_tx_seq_offset += 64;
3181
3182 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003183 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003184 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003185 }
3186
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003187 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003188 break;
3189
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003190 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003191
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003192 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003193
3194 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003195}
3196
Mat Martineau84084a32011-07-22 14:54:00 -07003197static void append_skb_frag(struct sk_buff *skb,
3198 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003199{
Mat Martineau84084a32011-07-22 14:54:00 -07003200 /* skb->len reflects data in skb as well as all fragments
3201 * skb->data_len reflects only data in fragments
3202 */
3203 if (!skb_has_frag_list(skb))
3204 skb_shinfo(skb)->frag_list = new_frag;
3205
3206 new_frag->next = NULL;
3207
3208 (*last_frag)->next = new_frag;
3209 *last_frag = new_frag;
3210
3211 skb->len += new_frag->len;
3212 skb->data_len += new_frag->len;
3213 skb->truesize += new_frag->truesize;
3214}
3215
3216static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
3217{
3218 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003219
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003220 switch (__get_ctrl_sar(chan, control)) {
3221 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003222 if (chan->sdu)
3223 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003224
Mat Martineau84084a32011-07-22 14:54:00 -07003225 err = chan->ops->recv(chan->data, skb);
3226 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003227
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003228 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003229 if (chan->sdu)
3230 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003231
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003232 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003233 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003234
Mat Martineau84084a32011-07-22 14:54:00 -07003235 if (chan->sdu_len > chan->imtu) {
3236 err = -EMSGSIZE;
3237 break;
3238 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003239
Mat Martineau84084a32011-07-22 14:54:00 -07003240 if (skb->len >= chan->sdu_len)
3241 break;
3242
3243 chan->sdu = skb;
3244 chan->sdu_last_frag = skb;
3245
3246 skb = NULL;
3247 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003248 break;
3249
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003250 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003251 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003252 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003253
Mat Martineau84084a32011-07-22 14:54:00 -07003254 append_skb_frag(chan->sdu, skb,
3255 &chan->sdu_last_frag);
3256 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003257
Mat Martineau84084a32011-07-22 14:54:00 -07003258 if (chan->sdu->len >= chan->sdu_len)
3259 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003260
Mat Martineau84084a32011-07-22 14:54:00 -07003261 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003262 break;
3263
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003264 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003265 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003266 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003267
Mat Martineau84084a32011-07-22 14:54:00 -07003268 append_skb_frag(chan->sdu, skb,
3269 &chan->sdu_last_frag);
3270 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003271
Mat Martineau84084a32011-07-22 14:54:00 -07003272 if (chan->sdu->len != chan->sdu_len)
3273 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003274
Mat Martineau84084a32011-07-22 14:54:00 -07003275 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003276
Mat Martineau84084a32011-07-22 14:54:00 -07003277 if (!err) {
3278 /* Reassembly complete */
3279 chan->sdu = NULL;
3280 chan->sdu_last_frag = NULL;
3281 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003282 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003283 break;
3284 }
3285
Mat Martineau84084a32011-07-22 14:54:00 -07003286 if (err) {
3287 kfree_skb(skb);
3288 kfree_skb(chan->sdu);
3289 chan->sdu = NULL;
3290 chan->sdu_last_frag = NULL;
3291 chan->sdu_len = 0;
3292 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003293
Mat Martineau84084a32011-07-22 14:54:00 -07003294 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003295}
3296
Mat Martineau26f880d2011-07-07 09:39:01 -07003297static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003298{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003299 u16 control;
3300
Mat Martineau26f880d2011-07-07 09:39:01 -07003301 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003302
Mat Martineau26f880d2011-07-07 09:39:01 -07003303 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
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 |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Mat Martineau26f880d2011-07-07 09:39:01 -07003307 l2cap_send_sframe(chan, control);
3308
3309 set_bit(CONN_RNR_SENT, &chan->conn_state);
3310
3311 __clear_ack_timer(chan);
3312}
3313
3314static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3315{
3316 u16 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003317
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003318 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003319 goto done;
3320
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003321 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003322 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003323 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003324 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003325 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003326
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003327 __clear_retrans_timer(chan);
3328 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003329
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003330 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003331
3332done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003333 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3334 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003335
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003336 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003337}
3338
Mat Martineaue3281402011-07-07 09:39:02 -07003339void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003340{
Mat Martineaue3281402011-07-07 09:39:02 -07003341 if (chan->mode == L2CAP_MODE_ERTM) {
3342 if (busy)
3343 l2cap_ertm_enter_local_busy(chan);
3344 else
3345 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003346 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003347}
3348
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003349static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003350{
3351 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003352 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003353
Mat Martineaue3281402011-07-07 09:39:02 -07003354 while ((skb = skb_peek(&chan->srej_q)) &&
3355 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3356 int err;
3357
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003358 if (bt_cb(skb)->tx_seq != tx_seq)
3359 break;
3360
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003361 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003362 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003363 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003364
3365 if (err < 0) {
3366 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3367 break;
3368 }
3369
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003370 chan->buffer_seq_srej =
3371 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003372 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003373 }
3374}
3375
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003376static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003377{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003378 struct srej_list *l, *tmp;
3379 u16 control;
3380
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003381 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003382 if (l->tx_seq == tx_seq) {
3383 list_del(&l->list);
3384 kfree(l);
3385 return;
3386 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003387 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003388 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003389 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003390 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003391 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003392 }
3393}
3394
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003395static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003396{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003397 struct srej_list *new;
3398 u16 control;
3399
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003400 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003401 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003402 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003403 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003404
3405 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003406 new->tx_seq = chan->expected_tx_seq;
3407 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003408 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003409 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003410 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003411}
3412
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003413static 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 -03003414{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003415 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003416 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003417 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003418 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003419 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003420 int err = 0;
3421
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003422 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3423 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003424
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003425 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003426 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003427 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003428 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003429 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003430 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003431 }
3432
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003433 chan->expected_ack_seq = req_seq;
3434 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003435
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003436 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003437 if (tx_seq_offset < 0)
3438 tx_seq_offset += 64;
3439
3440 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003441 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003442 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003443 goto drop;
3444 }
3445
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003446 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003447 goto drop;
3448
Mat Martineau02f1b642011-06-29 14:35:19 -07003449 if (tx_seq == chan->expected_tx_seq)
3450 goto expected;
3451
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003452 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003453 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003454
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003455 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003456 struct srej_list, list);
3457 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003458 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003459 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003460
3461 list_del(&first->list);
3462 kfree(first);
3463
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003464 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003465 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003466 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003467 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003468 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003469 }
3470 } else {
3471 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003472
3473 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003474 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003475 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003476
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003477 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003478 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003479 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003480 return 0;
3481 }
3482 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003483 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003484 }
3485 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003486 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003487 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003488 if (expected_tx_seq_offset < 0)
3489 expected_tx_seq_offset += 64;
3490
3491 /* duplicated tx_seq */
3492 if (tx_seq_offset < expected_tx_seq_offset)
3493 goto drop;
3494
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003495 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003496
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003497 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003498
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003499 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003500 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003501
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003502 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003503 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003504
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003505 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003506
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003507 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003508
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003509 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003510 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003511 return 0;
3512
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003513expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003514 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003515
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003516 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003517 bt_cb(skb)->tx_seq = tx_seq;
3518 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003519 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003520 return 0;
3521 }
3522
Mat Martineau84084a32011-07-22 14:54:00 -07003523 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Mat Martineaufadd1922011-07-07 09:39:03 -07003524 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Mat Martineaue3281402011-07-07 09:39:02 -07003525 if (err < 0) {
3526 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3527 return err;
3528 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003529
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003530 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003531 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003532 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003533 }
3534
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003535 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003536
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003537 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3538 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003539 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003540
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003541 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003542
3543drop:
3544 kfree_skb(skb);
3545 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003546}
3547
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003548static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003549{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003550 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan,
3551 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003552
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003553 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003554 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003555
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003556 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003557 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3558 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3559 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003560 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003561 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003562
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003563 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003564 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003565 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003566 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003567 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003568
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003569 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003570 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003571
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003572 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003573 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003574
3575 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003576 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003577 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003578 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003579
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003580 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3581 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003582 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003583 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003584 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003585 }
3586}
3587
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003588static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003589{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003590 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003591
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003592 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003593
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003594 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003595
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003596 chan->expected_ack_seq = tx_seq;
3597 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003598
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003599 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003600 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003601 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003602 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003603 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003604
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003605 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3606 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003607 }
3608}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003609static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003610{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003611 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003612
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003613 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003614
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003615 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003616
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003617 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003618 chan->expected_ack_seq = tx_seq;
3619 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003620
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003621 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003622 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003623
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003624 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003625
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003626 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003627 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003628 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003629 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003630 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003631 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003632 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003633 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003634 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003635 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003636 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003637 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003638 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003639 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003640 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003641 }
3642 }
3643}
3644
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003645static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003646{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003647 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003648
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003649 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003650
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003651 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003652 chan->expected_ack_seq = tx_seq;
3653 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003654
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003655 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003656 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003657
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003658 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003659 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003660 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003661 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003662 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003663 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003664
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003665 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003666 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003667 } else {
3668 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
3669 l2cap_send_sframe(chan, rx_control);
3670 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003671}
3672
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003673static 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 -03003674{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003675 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003676
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003677 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003678 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003679 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003680 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003681 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003682 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003683 }
3684
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003685 switch (__get_ctrl_super(chan, rx_control)) {
3686 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003687 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003688 break;
3689
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003690 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003691 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003692 break;
3693
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003694 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003695 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003696 break;
3697
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003698 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003699 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003700 break;
3701 }
3702
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003703 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003704 return 0;
3705}
3706
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003707static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3708{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003709 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003710 u16 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003711 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003712 int len, next_tx_seq_offset, req_seq_offset;
3713
3714 control = get_unaligned_le16(skb->data);
3715 skb_pull(skb, 2);
3716 len = skb->len;
3717
3718 /*
3719 * We can just drop the corrupted I-frame here.
3720 * Receiver will miss it and start proper recovery
3721 * procedures and ask retransmission.
3722 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003723 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003724 goto drop;
3725
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03003726 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003727 len -= 2;
3728
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003729 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003730 len -= 2;
3731
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003732 if (len > chan->mps) {
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
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003737 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003738 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003739 if (req_seq_offset < 0)
3740 req_seq_offset += 64;
3741
3742 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003743 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003744 if (next_tx_seq_offset < 0)
3745 next_tx_seq_offset += 64;
3746
3747 /* check for invalid req-seq */
3748 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003749 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003750 goto drop;
3751 }
3752
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03003753 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003754 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003755 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003756 goto drop;
3757 }
3758
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003759 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003760 } else {
3761 if (len != 0) {
3762 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003763 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003764 goto drop;
3765 }
3766
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003767 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003768 }
3769
3770 return 0;
3771
3772drop:
3773 kfree_skb(skb);
3774 return 0;
3775}
3776
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3778{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003779 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003780 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003781 u16 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003782 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003783 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003785 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003786 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003787 BT_DBG("unknown cid 0x%4.4x", cid);
3788 goto drop;
3789 }
3790
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003791 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003792
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003793 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003795 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796 goto drop;
3797
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003798 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003799 case L2CAP_MODE_BASIC:
3800 /* If socket recv buffers overflows we drop data here
3801 * which is *bad* because L2CAP has to be reliable.
3802 * But we don't have any other choice. L2CAP doesn't
3803 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003805 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003806 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003808 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003809 goto done;
3810 break;
3811
3812 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003813 if (!sock_owned_by_user(sk)) {
3814 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003815 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003816 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003817 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003818 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003819
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003820 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003821
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003822 case L2CAP_MODE_STREAMING:
3823 control = get_unaligned_le16(skb->data);
3824 skb_pull(skb, 2);
3825 len = skb->len;
3826
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003827 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003828 goto drop;
3829
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003830 if (__is_sar_start(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003831 len -= 2;
3832
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003833 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003834 len -= 2;
3835
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03003836 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003837 goto drop;
3838
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003839 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003840
Mat Martineau84084a32011-07-22 14:54:00 -07003841 if (chan->expected_tx_seq != tx_seq) {
3842 /* Frame(s) missing - must discard partial SDU */
3843 kfree_skb(chan->sdu);
3844 chan->sdu = NULL;
3845 chan->sdu_last_frag = NULL;
3846 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003847
Mat Martineau84084a32011-07-22 14:54:00 -07003848 /* TODO: Notify userland of missing data */
3849 }
3850
3851 chan->expected_tx_seq = (tx_seq + 1) % 64;
3852
3853 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
3854 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003855
3856 goto done;
3857
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003858 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003859 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003860 break;
3861 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862
3863drop:
3864 kfree_skb(skb);
3865
3866done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003867 if (sk)
3868 bh_unlock_sock(sk);
3869
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870 return 0;
3871}
3872
Al Viro8e036fc2007-07-29 00:16:36 -07003873static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003875 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003876 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003878 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3879 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880 goto drop;
3881
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003882 sk = chan->sk;
3883
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003884 bh_lock_sock(sk);
3885
Linus Torvalds1da177e2005-04-16 15:20:36 -07003886 BT_DBG("sk %p, len %d", sk, skb->len);
3887
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003888 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889 goto drop;
3890
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003891 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892 goto drop;
3893
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003894 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895 goto done;
3896
3897drop:
3898 kfree_skb(skb);
3899
3900done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003901 if (sk)
3902 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903 return 0;
3904}
3905
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003906static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3907{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003908 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003909 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003910
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003911 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3912 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003913 goto drop;
3914
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003915 sk = chan->sk;
3916
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003917 bh_lock_sock(sk);
3918
3919 BT_DBG("sk %p, len %d", sk, skb->len);
3920
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003921 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003922 goto drop;
3923
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003924 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003925 goto drop;
3926
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003927 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003928 goto done;
3929
3930drop:
3931 kfree_skb(skb);
3932
3933done:
3934 if (sk)
3935 bh_unlock_sock(sk);
3936 return 0;
3937}
3938
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3940{
3941 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003942 u16 cid, len;
3943 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944
3945 skb_pull(skb, L2CAP_HDR_SIZE);
3946 cid = __le16_to_cpu(lh->cid);
3947 len = __le16_to_cpu(lh->len);
3948
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003949 if (len != skb->len) {
3950 kfree_skb(skb);
3951 return;
3952 }
3953
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3955
3956 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003957 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003958 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959 l2cap_sig_channel(conn, skb);
3960 break;
3961
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003962 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003963 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964 skb_pull(skb, 2);
3965 l2cap_conless_channel(conn, psm, skb);
3966 break;
3967
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003968 case L2CAP_CID_LE_DATA:
3969 l2cap_att_channel(conn, cid, skb);
3970 break;
3971
Anderson Brigliab501d6a2011-06-07 18:46:31 -03003972 case L2CAP_CID_SMP:
3973 if (smp_sig_channel(conn, skb))
3974 l2cap_conn_del(conn->hcon, EACCES);
3975 break;
3976
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977 default:
3978 l2cap_data_channel(conn, cid, skb);
3979 break;
3980 }
3981}
3982
3983/* ---- L2CAP interface with lower layer (HCI) ---- */
3984
3985static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3986{
3987 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003988 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989
3990 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003991 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992
3993 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3994
3995 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003996 read_lock(&chan_list_lock);
3997 list_for_each_entry(c, &chan_list, global_l) {
3998 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003999
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004000 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004001 continue;
4002
4003 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004004 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004005 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004006 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004008 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4009 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004010 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004011 lm2 |= HCI_LM_MASTER;
4012 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004014 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004015
4016 return exact ? lm1 : lm2;
4017}
4018
4019static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4020{
Marcel Holtmann01394182006-07-03 10:02:46 +02004021 struct l2cap_conn *conn;
4022
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4024
Ville Tervoacd7d372011-02-10 22:38:49 -03004025 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004026 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027
4028 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029 conn = l2cap_conn_add(hcon, status);
4030 if (conn)
4031 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004032 } else
Joe Perchese1750722011-06-29 18:18:29 -07004033 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034
4035 return 0;
4036}
4037
Marcel Holtmann2950f212009-02-12 14:02:50 +01004038static int l2cap_disconn_ind(struct hci_conn *hcon)
4039{
4040 struct l2cap_conn *conn = hcon->l2cap_data;
4041
4042 BT_DBG("hcon %p", hcon);
4043
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03004044 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004045 return 0x13;
4046
4047 return conn->disc_reason;
4048}
4049
4050static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051{
4052 BT_DBG("hcon %p reason %d", hcon, reason);
4053
Ville Tervoacd7d372011-02-10 22:38:49 -03004054 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004055 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056
Joe Perchese1750722011-06-29 18:18:29 -07004057 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004058
Linus Torvalds1da177e2005-04-16 15:20:36 -07004059 return 0;
4060}
4061
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004062static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004063{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004064 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004065 return;
4066
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004067 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004068 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004069 __clear_chan_timer(chan);
4070 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004071 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004072 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004073 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004074 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004075 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004076 }
4077}
4078
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004079static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004081 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004082 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083
Marcel Holtmann01394182006-07-03 10:02:46 +02004084 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004086
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087 BT_DBG("conn %p", conn);
4088
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004089 if (hcon->type == LE_LINK) {
4090 smp_distribute_keys(conn, 0);
4091 del_timer(&conn->security_timer);
4092 }
4093
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004094 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004096 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004097 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004098
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099 bh_lock_sock(sk);
4100
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004101 BT_DBG("chan->scid %d", chan->scid);
4102
4103 if (chan->scid == L2CAP_CID_LE_DATA) {
4104 if (!status && encrypt) {
4105 chan->sec_level = hcon->sec_level;
4106 l2cap_chan_ready(sk);
4107 }
4108
4109 bh_unlock_sock(sk);
4110 continue;
4111 }
4112
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004113 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004114 bh_unlock_sock(sk);
4115 continue;
4116 }
4117
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004118 if (!status && (chan->state == BT_CONNECTED ||
4119 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004120 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004121 bh_unlock_sock(sk);
4122 continue;
4123 }
4124
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004125 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004126 if (!status) {
4127 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004128 req.scid = cpu_to_le16(chan->scid);
4129 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004130
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004131 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004132 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004133
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004134 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004135 L2CAP_CONN_REQ, sizeof(req), &req);
4136 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004137 __clear_chan_timer(chan);
4138 __set_chan_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004139 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004140 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004141 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004142 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004143
4144 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004145 if (bt_sk(sk)->defer_setup) {
4146 struct sock *parent = bt_sk(sk)->parent;
4147 res = L2CAP_CR_PEND;
4148 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004149 if (parent)
4150 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004151 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004152 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004153 res = L2CAP_CR_SUCCESS;
4154 stat = L2CAP_CS_NO_INFO;
4155 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004156 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004157 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004158 __set_chan_timer(chan, HZ / 10);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004159 res = L2CAP_CR_SEC_BLOCK;
4160 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004161 }
4162
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004163 rsp.scid = cpu_to_le16(chan->dcid);
4164 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004165 rsp.result = cpu_to_le16(res);
4166 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004167 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4168 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169 }
4170
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171 bh_unlock_sock(sk);
4172 }
4173
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004174 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004175
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176 return 0;
4177}
4178
4179static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4180{
4181 struct l2cap_conn *conn = hcon->l2cap_data;
4182
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004183 if (!conn)
4184 conn = l2cap_conn_add(hcon, 0);
4185
4186 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004187 goto drop;
4188
4189 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4190
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004191 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004193 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004194 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195 int len;
4196
4197 if (conn->rx_len) {
4198 BT_ERR("Unexpected start frame (len %d)", skb->len);
4199 kfree_skb(conn->rx_skb);
4200 conn->rx_skb = NULL;
4201 conn->rx_len = 0;
4202 l2cap_conn_unreliable(conn, ECOMM);
4203 }
4204
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004205 /* Start fragment always begin with Basic L2CAP header */
4206 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207 BT_ERR("Frame is too short (len %d)", skb->len);
4208 l2cap_conn_unreliable(conn, ECOMM);
4209 goto drop;
4210 }
4211
4212 hdr = (struct l2cap_hdr *) skb->data;
4213 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004214 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004215
4216 if (len == skb->len) {
4217 /* Complete frame received */
4218 l2cap_recv_frame(conn, skb);
4219 return 0;
4220 }
4221
4222 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4223
4224 if (skb->len > len) {
4225 BT_ERR("Frame is too long (len %d, expected len %d)",
4226 skb->len, len);
4227 l2cap_conn_unreliable(conn, ECOMM);
4228 goto drop;
4229 }
4230
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004231 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004232
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004233 if (chan && chan->sk) {
4234 struct sock *sk = chan->sk;
4235
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004236 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004237 BT_ERR("Frame exceeding recv MTU (len %d, "
4238 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004239 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004240 bh_unlock_sock(sk);
4241 l2cap_conn_unreliable(conn, ECOMM);
4242 goto drop;
4243 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004244 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004245 }
4246
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004248 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4249 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250 goto drop;
4251
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004252 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004253 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254 conn->rx_len = len - skb->len;
4255 } else {
4256 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4257
4258 if (!conn->rx_len) {
4259 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4260 l2cap_conn_unreliable(conn, ECOMM);
4261 goto drop;
4262 }
4263
4264 if (skb->len > conn->rx_len) {
4265 BT_ERR("Fragment is too long (len %d, expected %d)",
4266 skb->len, conn->rx_len);
4267 kfree_skb(conn->rx_skb);
4268 conn->rx_skb = NULL;
4269 conn->rx_len = 0;
4270 l2cap_conn_unreliable(conn, ECOMM);
4271 goto drop;
4272 }
4273
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004274 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004275 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276 conn->rx_len -= skb->len;
4277
4278 if (!conn->rx_len) {
4279 /* Complete frame received */
4280 l2cap_recv_frame(conn, conn->rx_skb);
4281 conn->rx_skb = NULL;
4282 }
4283 }
4284
4285drop:
4286 kfree_skb(skb);
4287 return 0;
4288}
4289
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004290static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004292 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004294 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004296 list_for_each_entry(c, &chan_list, global_l) {
4297 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004298
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004299 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 +01004300 batostr(&bt_sk(sk)->src),
4301 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004302 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004303 c->scid, c->dcid, c->imtu, c->omtu,
4304 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004305}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004307 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004308
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004309 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310}
4311
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004312static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4313{
4314 return single_open(file, l2cap_debugfs_show, inode->i_private);
4315}
4316
4317static const struct file_operations l2cap_debugfs_fops = {
4318 .open = l2cap_debugfs_open,
4319 .read = seq_read,
4320 .llseek = seq_lseek,
4321 .release = single_release,
4322};
4323
4324static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004325
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326static struct hci_proto l2cap_hci_proto = {
4327 .name = "L2CAP",
4328 .id = HCI_PROTO_L2CAP,
4329 .connect_ind = l2cap_connect_ind,
4330 .connect_cfm = l2cap_connect_cfm,
4331 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004332 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004333 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334 .recv_acldata = l2cap_recv_acldata
4335};
4336
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004337int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338{
4339 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004340
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004341 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342 if (err < 0)
4343 return err;
4344
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345 err = hci_register_proto(&l2cap_hci_proto);
4346 if (err < 0) {
4347 BT_ERR("L2CAP protocol registration failed");
4348 bt_sock_unregister(BTPROTO_L2CAP);
4349 goto error;
4350 }
4351
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004352 if (bt_debugfs) {
4353 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4354 bt_debugfs, NULL, &l2cap_debugfs_fops);
4355 if (!l2cap_debugfs)
4356 BT_ERR("Failed to create L2CAP debug file");
4357 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004358
Linus Torvalds1da177e2005-04-16 15:20:36 -07004359 return 0;
4360
4361error:
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004362 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004363 return err;
4364}
4365
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004366void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004368 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369
Linus Torvalds1da177e2005-04-16 15:20:36 -07004370 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4371 BT_ERR("L2CAP protocol unregistration failed");
4372
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004373 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374}
4375
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004376module_param(disable_ertm, bool, 0644);
4377MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03004378
4379module_param(enable_hs, bool, 0644);
4380MODULE_PARM_DESC(enable_hs, "Enable High Speed");