blob: 3158cec9e274cac980107adb2a07c6371674e86a [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;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300569 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200570 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300571
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300572 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300573 return;
574
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300575 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300576 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300577
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300578 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300579
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300580 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300581 control |= L2CAP_CTRL_FRAME_TYPE;
582
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300583 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300584 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300585
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300586 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300587 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300588
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300589 skb = bt_skb_alloc(count, GFP_ATOMIC);
590 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300591 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300592
593 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300594 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300595 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300596 put_unaligned_le16(control, skb_put(skb, 2));
597
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300598 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300599 u16 fcs = crc16(0, (u8 *)lh, count - 2);
600 put_unaligned_le16(fcs, skb_put(skb, 2));
601 }
602
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200603 if (lmp_no_flush_capable(conn->hcon->hdev))
604 flags = ACL_START_NO_FLUSH;
605 else
606 flags = ACL_START;
607
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700608 bt_cb(skb)->force_active = chan->force_active;
609
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300610 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300611}
612
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300613static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300614{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300615 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300616 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300617 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300618 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300619 control |= L2CAP_SUPER_RCV_READY;
620
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300621 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300622
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300623 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300624}
625
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300626static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300627{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300628 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300629}
630
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300631static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200632{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300633 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200634
635 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100636 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
637 return;
638
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300639 if (l2cap_check_security(chan) &&
640 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200641 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300642 req.scid = cpu_to_le16(chan->scid);
643 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200644
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300645 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300646 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200647
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300648 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
649 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200650 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200651 } else {
652 struct l2cap_info_req req;
653 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
654
655 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
656 conn->info_ident = l2cap_get_ident(conn);
657
658 mod_timer(&conn->info_timer, jiffies +
659 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
660
661 l2cap_send_cmd(conn, conn->info_ident,
662 L2CAP_INFO_REQ, sizeof(req), &req);
663 }
664}
665
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300666static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
667{
668 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300669 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300670 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
671
672 switch (mode) {
673 case L2CAP_MODE_ERTM:
674 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
675 case L2CAP_MODE_STREAMING:
676 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
677 default:
678 return 0x00;
679 }
680}
681
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300682static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300683{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300684 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300685 struct l2cap_disconn_req req;
686
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300687 if (!conn)
688 return;
689
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300690 sk = chan->sk;
691
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300692 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300693 __clear_retrans_timer(chan);
694 __clear_monitor_timer(chan);
695 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300696 }
697
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300698 req.dcid = cpu_to_le16(chan->dcid);
699 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300700 l2cap_send_cmd(conn, l2cap_get_ident(conn),
701 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300702
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300703 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300704 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300705}
706
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200708static void l2cap_conn_start(struct l2cap_conn *conn)
709{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300710 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200711
712 BT_DBG("conn %p", conn);
713
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300714 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200715
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300716 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300717 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300718
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200719 bh_lock_sock(sk);
720
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300721 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200722 bh_unlock_sock(sk);
723 continue;
724 }
725
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300726 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300727 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300728
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300729 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300730 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300731 bh_unlock_sock(sk);
732 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200733 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300734
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300735 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
736 && test_bit(CONF_STATE2_DEVICE,
737 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300738 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300739 * so release the lock */
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300740 read_unlock(&conn->chan_lock);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300741 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300742 read_lock(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300743 bh_unlock_sock(sk);
744 continue;
745 }
746
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300747 req.scid = cpu_to_le16(chan->scid);
748 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300749
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300750 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300751 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300752
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300753 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
754 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300755
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300756 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200757 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300758 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300759 rsp.scid = cpu_to_le16(chan->dcid);
760 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200761
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300762 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100763 if (bt_sk(sk)->defer_setup) {
764 struct sock *parent = bt_sk(sk)->parent;
765 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
766 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000767 if (parent)
768 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100769
770 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300771 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100772 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
773 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
774 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200775 } else {
776 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
777 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
778 }
779
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300780 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
781 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300782
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300783 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300784 rsp.result != L2CAP_CR_SUCCESS) {
785 bh_unlock_sock(sk);
786 continue;
787 }
788
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300789 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300790 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300791 l2cap_build_conf_req(chan, buf), buf);
792 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200793 }
794
795 bh_unlock_sock(sk);
796 }
797
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300798 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200799}
800
Ville Tervob62f3282011-02-10 22:38:50 -0300801/* Find socket with cid and source bdaddr.
802 * Returns closest match, locked.
803 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300804static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300805{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300806 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300807
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300808 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300809
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300810 list_for_each_entry(c, &chan_list, global_l) {
811 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300812
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300813 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300814 continue;
815
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300816 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300817 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300818 if (!bacmp(&bt_sk(sk)->src, src)) {
819 read_unlock(&chan_list_lock);
820 return c;
821 }
Ville Tervob62f3282011-02-10 22:38:50 -0300822
823 /* Closest match */
824 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300825 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300826 }
827 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300828
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300829 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300830
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300831 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300832}
833
834static void l2cap_le_conn_ready(struct l2cap_conn *conn)
835{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300836 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300837 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300838
839 BT_DBG("");
840
841 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300842 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300843 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300844 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300845 return;
846
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300847 parent = pchan->sk;
848
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300849 bh_lock_sock(parent);
850
Ville Tervob62f3282011-02-10 22:38:50 -0300851 /* Check for backlog size */
852 if (sk_acceptq_is_full(parent)) {
853 BT_DBG("backlog full %d", parent->sk_ack_backlog);
854 goto clean;
855 }
856
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300857 chan = pchan->ops->new_connection(pchan->data);
858 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300859 goto clean;
860
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300861 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300862
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300863 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300864
865 hci_conn_hold(conn->hcon);
866
Ville Tervob62f3282011-02-10 22:38:50 -0300867 bacpy(&bt_sk(sk)->src, conn->src);
868 bacpy(&bt_sk(sk)->dst, conn->dst);
869
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300870 bt_accept_enqueue(parent, sk);
871
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300872 __l2cap_chan_add(conn, chan);
873
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300874 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300875
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300876 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300877 parent->sk_data_ready(parent, 0);
878
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300879 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300880
881clean:
882 bh_unlock_sock(parent);
883}
884
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300885static void l2cap_chan_ready(struct sock *sk)
886{
887 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
888 struct sock *parent = bt_sk(sk)->parent;
889
890 BT_DBG("sk %p, parent %p", sk, parent);
891
892 chan->conf_state = 0;
893 __clear_chan_timer(chan);
894
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300895 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300896 sk->sk_state_change(sk);
897
898 if (parent)
899 parent->sk_data_ready(parent, 0);
900}
901
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200902static void l2cap_conn_ready(struct l2cap_conn *conn)
903{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300904 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200905
906 BT_DBG("conn %p", conn);
907
Ville Tervob62f3282011-02-10 22:38:50 -0300908 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
909 l2cap_le_conn_ready(conn);
910
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300911 if (conn->hcon->out && conn->hcon->type == LE_LINK)
912 smp_conn_security(conn, conn->hcon->pending_sec_level);
913
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300914 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200915
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300916 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300917 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300918
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200919 bh_lock_sock(sk);
920
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300921 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300922 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300923 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300924
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300925 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300926 __clear_chan_timer(chan);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300927 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200928 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300929
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300930 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300931 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200932
933 bh_unlock_sock(sk);
934 }
935
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300936 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200937}
938
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200939/* Notify sockets that we cannot guaranty reliability anymore */
940static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
941{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300942 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200943
944 BT_DBG("conn %p", conn);
945
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300946 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200947
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300948 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300949 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300950
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300951 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200952 sk->sk_err = err;
953 }
954
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300955 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200956}
957
958static void l2cap_info_timeout(unsigned long arg)
959{
960 struct l2cap_conn *conn = (void *) arg;
961
Marcel Holtmann984947d2009-02-06 23:35:19 +0100962 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100963 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100964
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200965 l2cap_conn_start(conn);
966}
967
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300968static void l2cap_conn_del(struct hci_conn *hcon, int err)
969{
970 struct l2cap_conn *conn = hcon->l2cap_data;
971 struct l2cap_chan *chan, *l;
972 struct sock *sk;
973
974 if (!conn)
975 return;
976
977 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
978
979 kfree_skb(conn->rx_skb);
980
981 /* Kill channels */
982 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
983 sk = chan->sk;
984 bh_lock_sock(sk);
985 l2cap_chan_del(chan, err);
986 bh_unlock_sock(sk);
987 chan->ops->close(chan->data);
988 }
989
990 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
991 del_timer_sync(&conn->info_timer);
992
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300993 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) {
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300994 del_timer(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300995 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300996 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300997
998 hcon->l2cap_data = NULL;
999 kfree(conn);
1000}
1001
1002static void security_timeout(unsigned long arg)
1003{
1004 struct l2cap_conn *conn = (void *) arg;
1005
1006 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1007}
1008
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1010{
Marcel Holtmann01394182006-07-03 10:02:46 +02001011 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012
Marcel Holtmann01394182006-07-03 10:02:46 +02001013 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 return conn;
1015
Marcel Holtmann01394182006-07-03 10:02:46 +02001016 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1017 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019
1020 hcon->l2cap_data = conn;
1021 conn->hcon = hcon;
1022
Marcel Holtmann01394182006-07-03 10:02:46 +02001023 BT_DBG("hcon %p conn %p", hcon, conn);
1024
Ville Tervoacd7d372011-02-10 22:38:49 -03001025 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1026 conn->mtu = hcon->hdev->le_mtu;
1027 else
1028 conn->mtu = hcon->hdev->acl_mtu;
1029
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 conn->src = &hcon->hdev->bdaddr;
1031 conn->dst = &hcon->dst;
1032
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001033 conn->feat_mask = 0;
1034
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001036 rwlock_init(&conn->chan_lock);
1037
1038 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001040 if (hcon->type == LE_LINK)
1041 setup_timer(&conn->security_timer, security_timeout,
1042 (unsigned long) conn);
1043 else
Ville Tervob62f3282011-02-10 22:38:50 -03001044 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +00001045 (unsigned long) conn);
1046
Marcel Holtmann2950f212009-02-12 14:02:50 +01001047 conn->disc_reason = 0x13;
1048
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 return conn;
1050}
1051
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001052static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001054 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001055 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001056 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057}
1058
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060
1061/* Find socket with psm and source bdaddr.
1062 * Returns closest match.
1063 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001064static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001066 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001068 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001069
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001070 list_for_each_entry(c, &chan_list, global_l) {
1071 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001072
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001073 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 continue;
1075
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001076 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001078 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001079 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001080 return c;
1081 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082
1083 /* Closest match */
1084 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001085 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 }
1087 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001089 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001090
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001091 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092}
1093
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001094int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001096 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 bdaddr_t *src = &bt_sk(sk)->src;
1098 bdaddr_t *dst = &bt_sk(sk)->dst;
1099 struct l2cap_conn *conn;
1100 struct hci_conn *hcon;
1101 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001102 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001103 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001105 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001106 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001108 hdev = hci_get_route(dst, src);
1109 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 return -EHOSTUNREACH;
1111
1112 hci_dev_lock_bh(hdev);
1113
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001114 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001115
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001116 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001117 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001118 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001119 else
1120 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001121 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001122
Ville Tervo30e76272011-02-22 16:10:53 -03001123 if (IS_ERR(hcon)) {
1124 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001126 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127
1128 conn = l2cap_conn_add(hcon, 0);
1129 if (!conn) {
1130 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001131 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 goto done;
1133 }
1134
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 /* Update source addr of the socket */
1136 bacpy(src, conn->src);
1137
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001138 l2cap_chan_add(conn, chan);
1139
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001140 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001141 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
1143 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001144 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001145 __clear_chan_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001146 if (l2cap_check_security(chan))
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001147 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001148 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001149 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 }
1151
Ville Tervo30e76272011-02-22 16:10:53 -03001152 err = 0;
1153
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154done:
1155 hci_dev_unlock_bh(hdev);
1156 hci_dev_put(hdev);
1157 return err;
1158}
1159
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001160int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001161{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001162 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001163 DECLARE_WAITQUEUE(wait, current);
1164 int err = 0;
1165 int timeo = HZ/5;
1166
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001167 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001168 set_current_state(TASK_INTERRUPTIBLE);
1169 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001170 if (!timeo)
1171 timeo = HZ/5;
1172
1173 if (signal_pending(current)) {
1174 err = sock_intr_errno(timeo);
1175 break;
1176 }
1177
1178 release_sock(sk);
1179 timeo = schedule_timeout(timeo);
1180 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001181 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001182
1183 err = sock_error(sk);
1184 if (err)
1185 break;
1186 }
1187 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001188 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001189 return err;
1190}
1191
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001192static void l2cap_monitor_timeout(unsigned long arg)
1193{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001194 struct l2cap_chan *chan = (void *) arg;
1195 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001196
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001197 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001198
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001199 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001200 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001201 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001202 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001203 return;
1204 }
1205
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001206 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001207 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001208
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001209 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001210 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001211}
1212
1213static void l2cap_retrans_timeout(unsigned long arg)
1214{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001215 struct l2cap_chan *chan = (void *) arg;
1216 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001217
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001218 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001219
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001220 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001221 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001222 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001223
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001224 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001225
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001226 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001227 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001228}
1229
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001230static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001231{
1232 struct sk_buff *skb;
1233
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001234 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001235 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001236 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001237 break;
1238
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001239 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001240 kfree_skb(skb);
1241
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001242 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001243 }
1244
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001245 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001246 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001247}
1248
Szymon Janc67c9e842011-07-28 16:24:33 +02001249static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001250{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001251 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001252 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001253
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001254 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001255
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001256 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001257 flags = ACL_START_NO_FLUSH;
1258 else
1259 flags = ACL_START;
1260
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -07001261 bt_cb(skb)->force_active = chan->force_active;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001262 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001263}
1264
Szymon Janc67c9e842011-07-28 16:24:33 +02001265static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001266{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001267 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001268 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001269
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001270 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001271 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001272 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001273 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001274
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001275 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001276 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1277 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001278 }
1279
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001280 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001281
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001282 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001283 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001284}
1285
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001286static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001287{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001288 struct sk_buff *skb, *tx_skb;
1289 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001290
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001291 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001292 if (!skb)
1293 return;
1294
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001295 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001296 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001297 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001298
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001299 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001300 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001301
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001302 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001303
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001304 if (chan->remote_max_tx &&
1305 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001306 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001307 return;
1308 }
1309
1310 tx_skb = skb_clone(skb, GFP_ATOMIC);
1311 bt_cb(skb)->retries++;
1312 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001313 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001314
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001315 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001316 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001317
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001318 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001319 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001320
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001321 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1322
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001323 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001324 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1325 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1326 }
1327
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001328 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001329}
1330
Szymon Janc67c9e842011-07-28 16:24:33 +02001331static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001332{
1333 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001334 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001335 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001336
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03001337 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001338 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001339
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001340 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001341
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001342 if (chan->remote_max_tx &&
1343 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001344 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001345 break;
1346 }
1347
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001348 tx_skb = skb_clone(skb, GFP_ATOMIC);
1349
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001350 bt_cb(skb)->retries++;
1351
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001352 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001353 control &= L2CAP_CTRL_SAR;
1354
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001355 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001356 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001357
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001358 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1359 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001360 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1361
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001362
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001363 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001364 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1365 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1366 }
1367
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001368 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001369
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001370 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001371
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001372 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1373 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001374
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301375 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001376 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301377
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001378 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001379
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001380 if (skb_queue_is_last(&chan->tx_q, skb))
1381 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001382 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001383 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001384
1385 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001386 }
1387
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001388 return nsent;
1389}
1390
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001391static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001392{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001393 int ret;
1394
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001395 if (!skb_queue_empty(&chan->tx_q))
1396 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001397
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001398 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001399 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001400 return ret;
1401}
1402
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001403static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001404{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001405 u16 control = 0;
1406
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001407 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001408
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001409 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001410 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001411 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001412 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001413 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001414 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001415
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001416 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001417 return;
1418
1419 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001420 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001421}
1422
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001423static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001424{
1425 struct srej_list *tail;
1426 u16 control;
1427
1428 control = L2CAP_SUPER_SELECT_REJECT;
1429 control |= L2CAP_CTRL_FINAL;
1430
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001431 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001432 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1433
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001434 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001435}
1436
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001437static 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 -07001438{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001439 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001440 struct sk_buff **frag;
1441 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001443 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001444 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445
1446 sent += count;
1447 len -= count;
1448
1449 /* Continuation fragments (no L2CAP header) */
1450 frag = &skb_shinfo(skb)->frag_list;
1451 while (len) {
1452 count = min_t(unsigned int, conn->mtu, len);
1453
1454 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1455 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001456 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001457 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1458 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459
1460 sent += count;
1461 len -= count;
1462
1463 frag = &(*frag)->next;
1464 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465
1466 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001467}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
Szymon Janc67c9e842011-07-28 16:24:33 +02001469static 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 -03001470{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001471 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001472 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001473 struct sk_buff *skb;
1474 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1475 struct l2cap_hdr *lh;
1476
1477 BT_DBG("sk %p len %d", sk, (int)len);
1478
1479 count = min_t(unsigned int, (conn->mtu - hlen), len);
1480 skb = bt_skb_send_alloc(sk, count + hlen,
1481 msg->msg_flags & MSG_DONTWAIT, &err);
1482 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001483 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001484
1485 /* Create L2CAP header */
1486 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001487 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001488 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001489 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001490
1491 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1492 if (unlikely(err < 0)) {
1493 kfree_skb(skb);
1494 return ERR_PTR(err);
1495 }
1496 return skb;
1497}
1498
Szymon Janc67c9e842011-07-28 16:24:33 +02001499static 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 -03001500{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001501 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001502 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001503 struct sk_buff *skb;
1504 int err, count, hlen = L2CAP_HDR_SIZE;
1505 struct l2cap_hdr *lh;
1506
1507 BT_DBG("sk %p len %d", sk, (int)len);
1508
1509 count = min_t(unsigned int, (conn->mtu - hlen), len);
1510 skb = bt_skb_send_alloc(sk, count + hlen,
1511 msg->msg_flags & MSG_DONTWAIT, &err);
1512 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001513 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001514
1515 /* Create L2CAP header */
1516 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001517 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001518 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1519
1520 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1521 if (unlikely(err < 0)) {
1522 kfree_skb(skb);
1523 return ERR_PTR(err);
1524 }
1525 return skb;
1526}
1527
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001528static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1529 struct msghdr *msg, size_t len,
1530 u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001531{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001532 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001533 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001534 struct sk_buff *skb;
1535 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1536 struct l2cap_hdr *lh;
1537
1538 BT_DBG("sk %p len %d", sk, (int)len);
1539
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001540 if (!conn)
1541 return ERR_PTR(-ENOTCONN);
1542
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001543 if (sdulen)
1544 hlen += 2;
1545
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001546 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001547 hlen += 2;
1548
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001549 count = min_t(unsigned int, (conn->mtu - hlen), len);
1550 skb = bt_skb_send_alloc(sk, count + hlen,
1551 msg->msg_flags & MSG_DONTWAIT, &err);
1552 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001553 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001554
1555 /* Create L2CAP header */
1556 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001557 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001558 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1559 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001560 if (sdulen)
1561 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001562
1563 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1564 if (unlikely(err < 0)) {
1565 kfree_skb(skb);
1566 return ERR_PTR(err);
1567 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001568
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001569 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001570 put_unaligned_le16(0, skb_put(skb, 2));
1571
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001572 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001573 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574}
1575
Szymon Janc67c9e842011-07-28 16:24:33 +02001576static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001577{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001578 struct sk_buff *skb;
1579 struct sk_buff_head sar_queue;
1580 u16 control;
1581 size_t size = 0;
1582
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001583 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001584 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001585 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001586 if (IS_ERR(skb))
1587 return PTR_ERR(skb);
1588
1589 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001590 len -= chan->remote_mps;
1591 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001592
1593 while (len > 0) {
1594 size_t buflen;
1595
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001596 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001597 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001598 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001599 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001600 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001601 buflen = len;
1602 }
1603
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001604 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001605 if (IS_ERR(skb)) {
1606 skb_queue_purge(&sar_queue);
1607 return PTR_ERR(skb);
1608 }
1609
1610 __skb_queue_tail(&sar_queue, skb);
1611 len -= buflen;
1612 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001613 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001614 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1615 if (chan->tx_send_head == NULL)
1616 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001617
1618 return size;
1619}
1620
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001621int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1622{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001623 struct sk_buff *skb;
1624 u16 control;
1625 int err;
1626
1627 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001628 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001629 skb = l2cap_create_connless_pdu(chan, msg, len);
1630 if (IS_ERR(skb))
1631 return PTR_ERR(skb);
1632
1633 l2cap_do_send(chan, skb);
1634 return len;
1635 }
1636
1637 switch (chan->mode) {
1638 case L2CAP_MODE_BASIC:
1639 /* Check outgoing MTU */
1640 if (len > chan->omtu)
1641 return -EMSGSIZE;
1642
1643 /* Create a basic PDU */
1644 skb = l2cap_create_basic_pdu(chan, msg, len);
1645 if (IS_ERR(skb))
1646 return PTR_ERR(skb);
1647
1648 l2cap_do_send(chan, skb);
1649 err = len;
1650 break;
1651
1652 case L2CAP_MODE_ERTM:
1653 case L2CAP_MODE_STREAMING:
1654 /* Entire SDU fits into one PDU */
1655 if (len <= chan->remote_mps) {
1656 control = L2CAP_SDU_UNSEGMENTED;
1657 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1658 0);
1659 if (IS_ERR(skb))
1660 return PTR_ERR(skb);
1661
1662 __skb_queue_tail(&chan->tx_q, skb);
1663
1664 if (chan->tx_send_head == NULL)
1665 chan->tx_send_head = skb;
1666
1667 } else {
1668 /* Segment SDU into multiples PDUs */
1669 err = l2cap_sar_segment_sdu(chan, msg, len);
1670 if (err < 0)
1671 return err;
1672 }
1673
1674 if (chan->mode == L2CAP_MODE_STREAMING) {
1675 l2cap_streaming_send(chan);
1676 err = len;
1677 break;
1678 }
1679
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001680 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1681 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001682 err = len;
1683 break;
1684 }
1685
1686 err = l2cap_ertm_send(chan);
1687 if (err >= 0)
1688 err = len;
1689
1690 break;
1691
1692 default:
1693 BT_DBG("bad state %1.1x", chan->mode);
1694 err = -EBADFD;
1695 }
1696
1697 return err;
1698}
1699
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700/* Copy frame to all raw sockets on that connection */
1701static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1702{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001704 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705
1706 BT_DBG("conn %p", conn);
1707
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001708 read_lock(&conn->chan_lock);
1709 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001710 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001711 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 continue;
1713
1714 /* Don't send frame to the socket it came from */
1715 if (skb->sk == sk)
1716 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001717 nskb = skb_clone(skb, GFP_ATOMIC);
1718 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 continue;
1720
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001721 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 kfree_skb(nskb);
1723 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001724 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725}
1726
1727/* ---- L2CAP signalling commands ---- */
1728static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1729 u8 code, u8 ident, u16 dlen, void *data)
1730{
1731 struct sk_buff *skb, **frag;
1732 struct l2cap_cmd_hdr *cmd;
1733 struct l2cap_hdr *lh;
1734 int len, count;
1735
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001736 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1737 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738
1739 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1740 count = min_t(unsigned int, conn->mtu, len);
1741
1742 skb = bt_skb_alloc(count, GFP_ATOMIC);
1743 if (!skb)
1744 return NULL;
1745
1746 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001747 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001748
1749 if (conn->hcon->type == LE_LINK)
1750 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1751 else
1752 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753
1754 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1755 cmd->code = code;
1756 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001757 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758
1759 if (dlen) {
1760 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1761 memcpy(skb_put(skb, count), data, count);
1762 data += count;
1763 }
1764
1765 len -= skb->len;
1766
1767 /* Continuation fragments (no L2CAP header) */
1768 frag = &skb_shinfo(skb)->frag_list;
1769 while (len) {
1770 count = min_t(unsigned int, conn->mtu, len);
1771
1772 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1773 if (!*frag)
1774 goto fail;
1775
1776 memcpy(skb_put(*frag, count), data, count);
1777
1778 len -= count;
1779 data += count;
1780
1781 frag = &(*frag)->next;
1782 }
1783
1784 return skb;
1785
1786fail:
1787 kfree_skb(skb);
1788 return NULL;
1789}
1790
1791static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1792{
1793 struct l2cap_conf_opt *opt = *ptr;
1794 int len;
1795
1796 len = L2CAP_CONF_OPT_SIZE + opt->len;
1797 *ptr += len;
1798
1799 *type = opt->type;
1800 *olen = opt->len;
1801
1802 switch (opt->len) {
1803 case 1:
1804 *val = *((u8 *) opt->val);
1805 break;
1806
1807 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001808 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 break;
1810
1811 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001812 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 break;
1814
1815 default:
1816 *val = (unsigned long) opt->val;
1817 break;
1818 }
1819
1820 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1821 return len;
1822}
1823
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1825{
1826 struct l2cap_conf_opt *opt = *ptr;
1827
1828 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1829
1830 opt->type = type;
1831 opt->len = len;
1832
1833 switch (len) {
1834 case 1:
1835 *((u8 *) opt->val) = val;
1836 break;
1837
1838 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001839 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 break;
1841
1842 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001843 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 break;
1845
1846 default:
1847 memcpy(opt->val, (void *) val, len);
1848 break;
1849 }
1850
1851 *ptr += L2CAP_CONF_OPT_SIZE + len;
1852}
1853
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001854static void l2cap_ack_timeout(unsigned long arg)
1855{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001856 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001857
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001858 bh_lock_sock(chan->sk);
1859 l2cap_send_ack(chan);
1860 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001861}
1862
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001863static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001864{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001865 struct sock *sk = chan->sk;
1866
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001867 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001868 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001869 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001870 chan->num_acked = 0;
1871 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001872
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001873 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1874 (unsigned long) chan);
1875 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1876 (unsigned long) chan);
1877 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001878
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001879 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001880
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001881 INIT_LIST_HEAD(&chan->srej_l);
1882
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001883
1884 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001885}
1886
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001887static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1888{
1889 switch (mode) {
1890 case L2CAP_MODE_STREAMING:
1891 case L2CAP_MODE_ERTM:
1892 if (l2cap_mode_supported(mode, remote_feat_mask))
1893 return mode;
1894 /* fall through */
1895 default:
1896 return L2CAP_MODE_BASIC;
1897 }
1898}
1899
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001900static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001903 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 void *ptr = req->data;
1905
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001906 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001908 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001909 goto done;
1910
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001911 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001912 case L2CAP_MODE_STREAMING:
1913 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001914 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001915 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001916
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001917 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001918 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001919 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001920 break;
1921 }
1922
1923done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001924 if (chan->imtu != L2CAP_DEFAULT_MTU)
1925 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001926
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001927 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001928 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001929 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1930 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001931 break;
1932
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001933 rfc.mode = L2CAP_MODE_BASIC;
1934 rfc.txwin_size = 0;
1935 rfc.max_transmit = 0;
1936 rfc.retrans_timeout = 0;
1937 rfc.monitor_timeout = 0;
1938 rfc.max_pdu_size = 0;
1939
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001940 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1941 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001942 break;
1943
1944 case L2CAP_MODE_ERTM:
1945 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001946 rfc.txwin_size = chan->tx_win;
1947 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001948 rfc.retrans_timeout = 0;
1949 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001950 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001951 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1952 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001953
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001954 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1955 (unsigned long) &rfc);
1956
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001957 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001958 break;
1959
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001960 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001961 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001962 chan->fcs = L2CAP_FCS_NONE;
1963 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001964 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001965 break;
1966
1967 case L2CAP_MODE_STREAMING:
1968 rfc.mode = L2CAP_MODE_STREAMING;
1969 rfc.txwin_size = 0;
1970 rfc.max_transmit = 0;
1971 rfc.retrans_timeout = 0;
1972 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001973 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001974 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1975 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001976
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001977 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1978 (unsigned long) &rfc);
1979
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001980 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001981 break;
1982
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001983 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001984 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001985 chan->fcs = L2CAP_FCS_NONE;
1986 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001987 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001988 break;
1989 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001991 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001992 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993
1994 return ptr - data;
1995}
1996
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001997static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001999 struct l2cap_conf_rsp *rsp = data;
2000 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002001 void *req = chan->conf_req;
2002 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002003 int type, hint, olen;
2004 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002005 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002006 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002007 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002009 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002010
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002011 while (len >= L2CAP_CONF_OPT_SIZE) {
2012 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002014 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002015 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002016
2017 switch (type) {
2018 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002019 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002020 break;
2021
2022 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002023 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002024 break;
2025
2026 case L2CAP_CONF_QOS:
2027 break;
2028
Marcel Holtmann6464f352007-10-20 13:39:51 +02002029 case L2CAP_CONF_RFC:
2030 if (olen == sizeof(rfc))
2031 memcpy(&rfc, (void *) val, olen);
2032 break;
2033
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002034 case L2CAP_CONF_FCS:
2035 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002036 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002037
2038 break;
2039
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002040 default:
2041 if (hint)
2042 break;
2043
2044 result = L2CAP_CONF_UNKNOWN;
2045 *((u8 *) ptr++) = type;
2046 break;
2047 }
2048 }
2049
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002050 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002051 goto done;
2052
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002053 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002054 case L2CAP_MODE_STREAMING:
2055 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002056 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002057 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002058 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002059 break;
2060 }
2061
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002062 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002063 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002064
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002065 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002066 }
2067
2068done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002069 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002070 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002071 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002072
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002073 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002074 return -ECONNREFUSED;
2075
2076 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2077 sizeof(rfc), (unsigned long) &rfc);
2078 }
2079
2080
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002081 if (result == L2CAP_CONF_SUCCESS) {
2082 /* Configure output options and let the other side know
2083 * which ones we don't like. */
2084
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002085 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2086 result = L2CAP_CONF_UNACCEPT;
2087 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002088 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002089 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002090 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002091 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002092
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002093 switch (rfc.mode) {
2094 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002095 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002096 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002097 break;
2098
2099 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002100 chan->remote_tx_win = rfc.txwin_size;
2101 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002102
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002103 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2104 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002105
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002106 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002107
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002108 rfc.retrans_timeout =
2109 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2110 rfc.monitor_timeout =
2111 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002112
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002113 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002114
2115 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2116 sizeof(rfc), (unsigned long) &rfc);
2117
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002118 break;
2119
2120 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002121 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2122 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002123
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002124 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002125
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002126 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002127
2128 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2129 sizeof(rfc), (unsigned long) &rfc);
2130
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002131 break;
2132
2133 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002134 result = L2CAP_CONF_UNACCEPT;
2135
2136 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002137 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002138 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002139
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002140 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002141 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002142 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002143 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002144 rsp->result = cpu_to_le16(result);
2145 rsp->flags = cpu_to_le16(0x0000);
2146
2147 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148}
2149
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002150static 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 -03002151{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002152 struct l2cap_conf_req *req = data;
2153 void *ptr = req->data;
2154 int type, olen;
2155 unsigned long val;
2156 struct l2cap_conf_rfc rfc;
2157
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002158 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002159
2160 while (len >= L2CAP_CONF_OPT_SIZE) {
2161 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2162
2163 switch (type) {
2164 case L2CAP_CONF_MTU:
2165 if (val < L2CAP_DEFAULT_MIN_MTU) {
2166 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002167 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002168 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002169 chan->imtu = val;
2170 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002171 break;
2172
2173 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002174 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002175 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002176 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002177 break;
2178
2179 case L2CAP_CONF_RFC:
2180 if (olen == sizeof(rfc))
2181 memcpy(&rfc, (void *)val, olen);
2182
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002183 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002184 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002185 return -ECONNREFUSED;
2186
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002187 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002188
2189 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2190 sizeof(rfc), (unsigned long) &rfc);
2191 break;
2192 }
2193 }
2194
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002195 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002196 return -ECONNREFUSED;
2197
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002198 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002199
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002200 if (*result == L2CAP_CONF_SUCCESS) {
2201 switch (rfc.mode) {
2202 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002203 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2204 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2205 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002206 break;
2207 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002208 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002209 }
2210 }
2211
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002212 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002213 req->flags = cpu_to_le16(0x0000);
2214
2215 return ptr - data;
2216}
2217
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002218static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219{
2220 struct l2cap_conf_rsp *rsp = data;
2221 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002223 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002225 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002226 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002227 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228
2229 return ptr - data;
2230}
2231
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002232void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002233{
2234 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002235 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002236 u8 buf[128];
2237
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002238 rsp.scid = cpu_to_le16(chan->dcid);
2239 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002240 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2241 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2242 l2cap_send_cmd(conn, chan->ident,
2243 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2244
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002245 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002246 return;
2247
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002248 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2249 l2cap_build_conf_req(chan, buf), buf);
2250 chan->num_conf_req++;
2251}
2252
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002253static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002254{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002255 int type, olen;
2256 unsigned long val;
2257 struct l2cap_conf_rfc rfc;
2258
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002259 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002260
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002261 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002262 return;
2263
2264 while (len >= L2CAP_CONF_OPT_SIZE) {
2265 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2266
2267 switch (type) {
2268 case L2CAP_CONF_RFC:
2269 if (olen == sizeof(rfc))
2270 memcpy(&rfc, (void *)val, olen);
2271 goto done;
2272 }
2273 }
2274
2275done:
2276 switch (rfc.mode) {
2277 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002278 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2279 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2280 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002281 break;
2282 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002283 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002284 }
2285}
2286
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002287static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2288{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002289 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002290
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002291 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002292 return 0;
2293
2294 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2295 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002296 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002297
2298 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002299 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002300
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002301 l2cap_conn_start(conn);
2302 }
2303
2304 return 0;
2305}
2306
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2308{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2310 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002311 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002312 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002313 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314
2315 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002316 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317
2318 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2319
2320 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002321 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2322 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323 result = L2CAP_CR_BAD_PSM;
2324 goto sendresp;
2325 }
2326
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002327 parent = pchan->sk;
2328
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002329 bh_lock_sock(parent);
2330
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002331 /* Check if the ACL is secure enough (if not SDP) */
2332 if (psm != cpu_to_le16(0x0001) &&
2333 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002334 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002335 result = L2CAP_CR_SEC_BLOCK;
2336 goto response;
2337 }
2338
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339 result = L2CAP_CR_NO_MEM;
2340
2341 /* Check for backlog size */
2342 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002343 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 goto response;
2345 }
2346
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002347 chan = pchan->ops->new_connection(pchan->data);
2348 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 goto response;
2350
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002351 sk = chan->sk;
2352
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002353 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354
2355 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002356 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2357 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002359 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 goto response;
2361 }
2362
2363 hci_conn_hold(conn->hcon);
2364
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 bacpy(&bt_sk(sk)->src, conn->src);
2366 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002367 chan->psm = psm;
2368 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002370 bt_accept_enqueue(parent, sk);
2371
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002372 __l2cap_chan_add(conn, chan);
2373
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002374 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002376 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002378 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379
Marcel Holtmann984947d2009-02-06 23:35:19 +01002380 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002381 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002382 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002383 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002384 result = L2CAP_CR_PEND;
2385 status = L2CAP_CS_AUTHOR_PEND;
2386 parent->sk_data_ready(parent, 0);
2387 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002388 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002389 result = L2CAP_CR_SUCCESS;
2390 status = L2CAP_CS_NO_INFO;
2391 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002392 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002393 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002394 result = L2CAP_CR_PEND;
2395 status = L2CAP_CS_AUTHEN_PEND;
2396 }
2397 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002398 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002399 result = L2CAP_CR_PEND;
2400 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 }
2402
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002403 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404
2405response:
2406 bh_unlock_sock(parent);
2407
2408sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002409 rsp.scid = cpu_to_le16(scid);
2410 rsp.dcid = cpu_to_le16(dcid);
2411 rsp.result = cpu_to_le16(result);
2412 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002414
2415 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2416 struct l2cap_info_req info;
2417 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2418
2419 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2420 conn->info_ident = l2cap_get_ident(conn);
2421
2422 mod_timer(&conn->info_timer, jiffies +
2423 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2424
2425 l2cap_send_cmd(conn, conn->info_ident,
2426 L2CAP_INFO_REQ, sizeof(info), &info);
2427 }
2428
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002429 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002430 result == L2CAP_CR_SUCCESS) {
2431 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002432 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002433 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002434 l2cap_build_conf_req(chan, buf), buf);
2435 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002436 }
2437
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438 return 0;
2439}
2440
2441static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2442{
2443 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2444 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002445 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446 struct sock *sk;
2447 u8 req[128];
2448
2449 scid = __le16_to_cpu(rsp->scid);
2450 dcid = __le16_to_cpu(rsp->dcid);
2451 result = __le16_to_cpu(rsp->result);
2452 status = __le16_to_cpu(rsp->status);
2453
2454 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2455
2456 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002457 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002458 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002459 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002461 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002462 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002463 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 }
2465
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002466 sk = chan->sk;
2467
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468 switch (result) {
2469 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002470 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002471 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002472 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002473 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002474
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002475 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002476 break;
2477
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002479 l2cap_build_conf_req(chan, req), req);
2480 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481 break;
2482
2483 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002484 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485 break;
2486
2487 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002488 /* don't delete l2cap channel if sk is owned by user */
2489 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002490 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002491 __clear_chan_timer(chan);
2492 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002493 break;
2494 }
2495
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002496 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 break;
2498 }
2499
2500 bh_unlock_sock(sk);
2501 return 0;
2502}
2503
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002504static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002505{
2506 /* FCS is enabled only in ERTM or streaming mode, if one or both
2507 * sides request it.
2508 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002509 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002510 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002511 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002512 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002513}
2514
Al Viro88219a02007-07-29 00:17:25 -07002515static 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 -07002516{
2517 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2518 u16 dcid, flags;
2519 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002520 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002522 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523
2524 dcid = __le16_to_cpu(req->dcid);
2525 flags = __le16_to_cpu(req->flags);
2526
2527 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2528
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002529 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002530 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531 return -ENOENT;
2532
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002533 sk = chan->sk;
2534
David S. Miller033b1142011-07-21 13:38:42 -07002535 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002536 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002537
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002538 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2539 rej.scid = cpu_to_le16(chan->scid);
2540 rej.dcid = cpu_to_le16(chan->dcid);
2541
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002542 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2543 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002544 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002545 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002546
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002547 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002548 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002549 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002550 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002551 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002552 L2CAP_CONF_REJECT, flags), rsp);
2553 goto unlock;
2554 }
2555
2556 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002557 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2558 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559
2560 if (flags & 0x0001) {
2561 /* Incomplete config. Send empty response. */
2562 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002563 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002564 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565 goto unlock;
2566 }
2567
2568 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002569 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002570 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002571 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002573 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002575 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002576 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002577
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002578 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002579 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002580
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002581 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002582 goto unlock;
2583
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002584 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002585 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002586
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002587 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002588
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002589 chan->next_tx_seq = 0;
2590 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002591 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002592 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002593 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002594
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002596 goto unlock;
2597 }
2598
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002599 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002600 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002602 l2cap_build_conf_req(chan, buf), buf);
2603 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604 }
2605
2606unlock:
2607 bh_unlock_sock(sk);
2608 return 0;
2609}
2610
2611static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2612{
2613 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2614 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002615 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002617 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618
2619 scid = __le16_to_cpu(rsp->scid);
2620 flags = __le16_to_cpu(rsp->flags);
2621 result = __le16_to_cpu(rsp->result);
2622
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002623 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2624 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002626 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002627 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628 return 0;
2629
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002630 sk = chan->sk;
2631
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 switch (result) {
2633 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002634 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635 break;
2636
2637 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002638 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002639 char req[64];
2640
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002641 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002642 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002643 goto done;
2644 }
2645
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002646 /* throw out any old stored conf requests */
2647 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002648 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2649 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002650 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002651 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002652 goto done;
2653 }
2654
2655 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2656 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002657 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002658 if (result != L2CAP_CONF_SUCCESS)
2659 goto done;
2660 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661 }
2662
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002663 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002664 sk->sk_err = ECONNRESET;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002665 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002666 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667 goto done;
2668 }
2669
2670 if (flags & 0x01)
2671 goto done;
2672
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002673 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002675 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002676 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002677
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002678 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002679 chan->next_tx_seq = 0;
2680 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002681 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002682 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002683 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002684
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685 l2cap_chan_ready(sk);
2686 }
2687
2688done:
2689 bh_unlock_sock(sk);
2690 return 0;
2691}
2692
2693static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2694{
2695 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2696 struct l2cap_disconn_rsp rsp;
2697 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002698 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699 struct sock *sk;
2700
2701 scid = __le16_to_cpu(req->scid);
2702 dcid = __le16_to_cpu(req->dcid);
2703
2704 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2705
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002706 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002707 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708 return 0;
2709
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002710 sk = chan->sk;
2711
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002712 rsp.dcid = cpu_to_le16(chan->scid);
2713 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2715
2716 sk->sk_shutdown = SHUTDOWN_MASK;
2717
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002718 /* don't delete l2cap channel if sk is owned by user */
2719 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002720 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002721 __clear_chan_timer(chan);
2722 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002723 bh_unlock_sock(sk);
2724 return 0;
2725 }
2726
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002727 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 bh_unlock_sock(sk);
2729
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002730 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731 return 0;
2732}
2733
2734static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2735{
2736 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2737 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002738 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 struct sock *sk;
2740
2741 scid = __le16_to_cpu(rsp->scid);
2742 dcid = __le16_to_cpu(rsp->dcid);
2743
2744 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2745
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002746 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002747 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 return 0;
2749
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002750 sk = chan->sk;
2751
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002752 /* don't delete l2cap channel if sk is owned by user */
2753 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002754 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002755 __clear_chan_timer(chan);
2756 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002757 bh_unlock_sock(sk);
2758 return 0;
2759 }
2760
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002761 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 bh_unlock_sock(sk);
2763
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002764 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 return 0;
2766}
2767
2768static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2769{
2770 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 u16 type;
2772
2773 type = __le16_to_cpu(req->type);
2774
2775 BT_DBG("type 0x%4.4x", type);
2776
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002777 if (type == L2CAP_IT_FEAT_MASK) {
2778 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002779 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002780 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2781 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2782 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002783 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002784 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2785 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03002786 if (enable_hs)
2787 feat_mask |= L2CAP_FEAT_EXT_FLOW;
2788
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002789 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002790 l2cap_send_cmd(conn, cmd->ident,
2791 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002792 } else if (type == L2CAP_IT_FIXED_CHAN) {
2793 u8 buf[12];
2794 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2795 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2796 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2797 memcpy(buf + 4, l2cap_fixed_chan, 8);
2798 l2cap_send_cmd(conn, cmd->ident,
2799 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002800 } else {
2801 struct l2cap_info_rsp rsp;
2802 rsp.type = cpu_to_le16(type);
2803 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2804 l2cap_send_cmd(conn, cmd->ident,
2805 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2806 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807
2808 return 0;
2809}
2810
2811static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2812{
2813 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2814 u16 type, result;
2815
2816 type = __le16_to_cpu(rsp->type);
2817 result = __le16_to_cpu(rsp->result);
2818
2819 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2820
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002821 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2822 if (cmd->ident != conn->info_ident ||
2823 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2824 return 0;
2825
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002826 del_timer(&conn->info_timer);
2827
Ville Tervoadb08ed2010-08-04 09:43:33 +03002828 if (result != L2CAP_IR_SUCCESS) {
2829 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2830 conn->info_ident = 0;
2831
2832 l2cap_conn_start(conn);
2833
2834 return 0;
2835 }
2836
Marcel Holtmann984947d2009-02-06 23:35:19 +01002837 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002838 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002839
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002840 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002841 struct l2cap_info_req req;
2842 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2843
2844 conn->info_ident = l2cap_get_ident(conn);
2845
2846 l2cap_send_cmd(conn, conn->info_ident,
2847 L2CAP_INFO_REQ, sizeof(req), &req);
2848 } else {
2849 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2850 conn->info_ident = 0;
2851
2852 l2cap_conn_start(conn);
2853 }
2854 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002855 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002856 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002857
2858 l2cap_conn_start(conn);
2859 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002860
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861 return 0;
2862}
2863
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002864static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002865 u16 to_multiplier)
2866{
2867 u16 max_latency;
2868
2869 if (min > max || min < 6 || max > 3200)
2870 return -EINVAL;
2871
2872 if (to_multiplier < 10 || to_multiplier > 3200)
2873 return -EINVAL;
2874
2875 if (max >= to_multiplier * 8)
2876 return -EINVAL;
2877
2878 max_latency = (to_multiplier * 8 / max) - 1;
2879 if (latency > 499 || latency > max_latency)
2880 return -EINVAL;
2881
2882 return 0;
2883}
2884
2885static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2886 struct l2cap_cmd_hdr *cmd, u8 *data)
2887{
2888 struct hci_conn *hcon = conn->hcon;
2889 struct l2cap_conn_param_update_req *req;
2890 struct l2cap_conn_param_update_rsp rsp;
2891 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002892 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002893
2894 if (!(hcon->link_mode & HCI_LM_MASTER))
2895 return -EINVAL;
2896
2897 cmd_len = __le16_to_cpu(cmd->len);
2898 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2899 return -EPROTO;
2900
2901 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002902 min = __le16_to_cpu(req->min);
2903 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002904 latency = __le16_to_cpu(req->latency);
2905 to_multiplier = __le16_to_cpu(req->to_multiplier);
2906
2907 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2908 min, max, latency, to_multiplier);
2909
2910 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002911
2912 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2913 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002914 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2915 else
2916 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2917
2918 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2919 sizeof(rsp), &rsp);
2920
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002921 if (!err)
2922 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2923
Claudio Takahaside731152011-02-11 19:28:55 -02002924 return 0;
2925}
2926
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002927static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2928 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2929{
2930 int err = 0;
2931
2932 switch (cmd->code) {
2933 case L2CAP_COMMAND_REJ:
2934 l2cap_command_rej(conn, cmd, data);
2935 break;
2936
2937 case L2CAP_CONN_REQ:
2938 err = l2cap_connect_req(conn, cmd, data);
2939 break;
2940
2941 case L2CAP_CONN_RSP:
2942 err = l2cap_connect_rsp(conn, cmd, data);
2943 break;
2944
2945 case L2CAP_CONF_REQ:
2946 err = l2cap_config_req(conn, cmd, cmd_len, data);
2947 break;
2948
2949 case L2CAP_CONF_RSP:
2950 err = l2cap_config_rsp(conn, cmd, data);
2951 break;
2952
2953 case L2CAP_DISCONN_REQ:
2954 err = l2cap_disconnect_req(conn, cmd, data);
2955 break;
2956
2957 case L2CAP_DISCONN_RSP:
2958 err = l2cap_disconnect_rsp(conn, cmd, data);
2959 break;
2960
2961 case L2CAP_ECHO_REQ:
2962 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2963 break;
2964
2965 case L2CAP_ECHO_RSP:
2966 break;
2967
2968 case L2CAP_INFO_REQ:
2969 err = l2cap_information_req(conn, cmd, data);
2970 break;
2971
2972 case L2CAP_INFO_RSP:
2973 err = l2cap_information_rsp(conn, cmd, data);
2974 break;
2975
2976 default:
2977 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2978 err = -EINVAL;
2979 break;
2980 }
2981
2982 return err;
2983}
2984
2985static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2986 struct l2cap_cmd_hdr *cmd, u8 *data)
2987{
2988 switch (cmd->code) {
2989 case L2CAP_COMMAND_REJ:
2990 return 0;
2991
2992 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002993 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002994
2995 case L2CAP_CONN_PARAM_UPDATE_RSP:
2996 return 0;
2997
2998 default:
2999 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3000 return -EINVAL;
3001 }
3002}
3003
3004static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3005 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006{
3007 u8 *data = skb->data;
3008 int len = skb->len;
3009 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003010 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003011
3012 l2cap_raw_recv(conn, skb);
3013
3014 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003015 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3017 data += L2CAP_CMD_HDR_SIZE;
3018 len -= L2CAP_CMD_HDR_SIZE;
3019
Al Viro88219a02007-07-29 00:17:25 -07003020 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021
Al Viro88219a02007-07-29 00:17:25 -07003022 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 -07003023
Al Viro88219a02007-07-29 00:17:25 -07003024 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025 BT_DBG("corrupted command");
3026 break;
3027 }
3028
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003029 if (conn->hcon->type == LE_LINK)
3030 err = l2cap_le_sig_cmd(conn, &cmd, data);
3031 else
3032 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033
3034 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003035 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003036
3037 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038
3039 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003040 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3042 }
3043
Al Viro88219a02007-07-29 00:17:25 -07003044 data += cmd_len;
3045 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003046 }
3047
3048 kfree_skb(skb);
3049}
3050
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003051static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003052{
3053 u16 our_fcs, rcv_fcs;
3054 int hdr_size = L2CAP_HDR_SIZE + 2;
3055
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003056 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003057 skb_trim(skb, skb->len - 2);
3058 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3059 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3060
3061 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003062 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003063 }
3064 return 0;
3065}
3066
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003067static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003068{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003069 u16 control = 0;
3070
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003071 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003072
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003073 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003074
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003075 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003076 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003077 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003078 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003079 }
3080
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003081 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003082 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003083
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003084 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003085
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003086 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003087 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003088 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003089 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003090 }
3091}
3092
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003093static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u8 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003094{
3095 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003096 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003097
3098 bt_cb(skb)->tx_seq = tx_seq;
3099 bt_cb(skb)->sar = sar;
3100
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003101 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003102 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003103 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003104 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003105 }
3106
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003107 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003108 if (tx_seq_offset < 0)
3109 tx_seq_offset += 64;
3110
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003111 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003112 if (bt_cb(next_skb)->tx_seq == tx_seq)
3113 return -EINVAL;
3114
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003115 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003116 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003117 if (next_tx_seq_offset < 0)
3118 next_tx_seq_offset += 64;
3119
3120 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003121 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003122 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003123 }
3124
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003125 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003126 break;
3127
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003128 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003129
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003130 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003131
3132 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003133}
3134
Mat Martineau84084a32011-07-22 14:54:00 -07003135static void append_skb_frag(struct sk_buff *skb,
3136 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003137{
Mat Martineau84084a32011-07-22 14:54:00 -07003138 /* skb->len reflects data in skb as well as all fragments
3139 * skb->data_len reflects only data in fragments
3140 */
3141 if (!skb_has_frag_list(skb))
3142 skb_shinfo(skb)->frag_list = new_frag;
3143
3144 new_frag->next = NULL;
3145
3146 (*last_frag)->next = new_frag;
3147 *last_frag = new_frag;
3148
3149 skb->len += new_frag->len;
3150 skb->data_len += new_frag->len;
3151 skb->truesize += new_frag->truesize;
3152}
3153
3154static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
3155{
3156 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003157
3158 switch (control & L2CAP_CTRL_SAR) {
3159 case L2CAP_SDU_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003160 if (chan->sdu)
3161 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003162
Mat Martineau84084a32011-07-22 14:54:00 -07003163 err = chan->ops->recv(chan->data, skb);
3164 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003165
3166 case L2CAP_SDU_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003167 if (chan->sdu)
3168 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003169
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003170 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003171 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003172
Mat Martineau84084a32011-07-22 14:54:00 -07003173 if (chan->sdu_len > chan->imtu) {
3174 err = -EMSGSIZE;
3175 break;
3176 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003177
Mat Martineau84084a32011-07-22 14:54:00 -07003178 if (skb->len >= chan->sdu_len)
3179 break;
3180
3181 chan->sdu = skb;
3182 chan->sdu_last_frag = skb;
3183
3184 skb = NULL;
3185 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003186 break;
3187
3188 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003189 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003190 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003191
Mat Martineau84084a32011-07-22 14:54:00 -07003192 append_skb_frag(chan->sdu, skb,
3193 &chan->sdu_last_frag);
3194 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003195
Mat Martineau84084a32011-07-22 14:54:00 -07003196 if (chan->sdu->len >= chan->sdu_len)
3197 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003198
Mat Martineau84084a32011-07-22 14:54:00 -07003199 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003200 break;
3201
3202 case L2CAP_SDU_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003203 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003204 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003205
Mat Martineau84084a32011-07-22 14:54:00 -07003206 append_skb_frag(chan->sdu, skb,
3207 &chan->sdu_last_frag);
3208 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003209
Mat Martineau84084a32011-07-22 14:54:00 -07003210 if (chan->sdu->len != chan->sdu_len)
3211 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003212
Mat Martineau84084a32011-07-22 14:54:00 -07003213 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003214
Mat Martineau84084a32011-07-22 14:54:00 -07003215 if (!err) {
3216 /* Reassembly complete */
3217 chan->sdu = NULL;
3218 chan->sdu_last_frag = NULL;
3219 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003220 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003221 break;
3222 }
3223
Mat Martineau84084a32011-07-22 14:54:00 -07003224 if (err) {
3225 kfree_skb(skb);
3226 kfree_skb(chan->sdu);
3227 chan->sdu = NULL;
3228 chan->sdu_last_frag = NULL;
3229 chan->sdu_len = 0;
3230 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003231
Mat Martineau84084a32011-07-22 14:54:00 -07003232 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003233}
3234
Mat Martineau26f880d2011-07-07 09:39:01 -07003235static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003236{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003237 u16 control;
3238
Mat Martineau26f880d2011-07-07 09:39:01 -07003239 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003240
Mat Martineau26f880d2011-07-07 09:39:01 -07003241 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3242
3243 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3244 control |= L2CAP_SUPER_RCV_NOT_READY;
3245 l2cap_send_sframe(chan, control);
3246
3247 set_bit(CONN_RNR_SENT, &chan->conn_state);
3248
3249 __clear_ack_timer(chan);
3250}
3251
3252static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3253{
3254 u16 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003255
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003256 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003257 goto done;
3258
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003259 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003260 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003261 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003262 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003263
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003264 __clear_retrans_timer(chan);
3265 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003266
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003267 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003268
3269done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003270 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3271 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003272
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003273 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003274}
3275
Mat Martineaue3281402011-07-07 09:39:02 -07003276void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003277{
Mat Martineaue3281402011-07-07 09:39:02 -07003278 if (chan->mode == L2CAP_MODE_ERTM) {
3279 if (busy)
3280 l2cap_ertm_enter_local_busy(chan);
3281 else
3282 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003283 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003284}
3285
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003286static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003287{
3288 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003289 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003290
Mat Martineaue3281402011-07-07 09:39:02 -07003291 while ((skb = skb_peek(&chan->srej_q)) &&
3292 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3293 int err;
3294
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003295 if (bt_cb(skb)->tx_seq != tx_seq)
3296 break;
3297
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003298 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003299 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Mat Martineau84084a32011-07-22 14:54:00 -07003300 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003301
3302 if (err < 0) {
3303 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3304 break;
3305 }
3306
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003307 chan->buffer_seq_srej =
3308 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003309 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003310 }
3311}
3312
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003313static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003314{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003315 struct srej_list *l, *tmp;
3316 u16 control;
3317
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003318 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003319 if (l->tx_seq == tx_seq) {
3320 list_del(&l->list);
3321 kfree(l);
3322 return;
3323 }
3324 control = L2CAP_SUPER_SELECT_REJECT;
3325 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003326 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003327 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003328 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003329 }
3330}
3331
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003332static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003333{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003334 struct srej_list *new;
3335 u16 control;
3336
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003337 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003338 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003339 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003340 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003341
3342 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003343 new->tx_seq = chan->expected_tx_seq;
3344 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003345 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003346 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003347 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003348}
3349
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003350static 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 -03003351{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003352 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003353 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003354 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003355 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003356 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003357 int err = 0;
3358
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003359 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3360 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003361
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003362 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003363 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003364 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003365 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003366 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003367 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003368 }
3369
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003370 chan->expected_ack_seq = req_seq;
3371 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003372
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003373 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003374 if (tx_seq_offset < 0)
3375 tx_seq_offset += 64;
3376
3377 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003378 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003379 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003380 goto drop;
3381 }
3382
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003383 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003384 goto drop;
3385
Mat Martineau02f1b642011-06-29 14:35:19 -07003386 if (tx_seq == chan->expected_tx_seq)
3387 goto expected;
3388
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003389 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003390 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003391
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003392 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003393 struct srej_list, list);
3394 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003395 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003396 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003397
3398 list_del(&first->list);
3399 kfree(first);
3400
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003401 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003402 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003403 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003404 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003405 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003406 }
3407 } else {
3408 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003409
3410 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003411 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003412 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003413
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003414 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003415 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003416 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003417 return 0;
3418 }
3419 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003420 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003421 }
3422 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003423 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003424 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003425 if (expected_tx_seq_offset < 0)
3426 expected_tx_seq_offset += 64;
3427
3428 /* duplicated tx_seq */
3429 if (tx_seq_offset < expected_tx_seq_offset)
3430 goto drop;
3431
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003432 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003433
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003434 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003435
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003436 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003437 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003438
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003439 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003440 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003441
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003442 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003443
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003444 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003445
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003446 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003447 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003448 return 0;
3449
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003450expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003451 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003452
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003453 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003454 bt_cb(skb)->tx_seq = tx_seq;
3455 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003456 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003457 return 0;
3458 }
3459
Mat Martineau84084a32011-07-22 14:54:00 -07003460 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Mat Martineaufadd1922011-07-07 09:39:03 -07003461 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Mat Martineaue3281402011-07-07 09:39:02 -07003462 if (err < 0) {
3463 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3464 return err;
3465 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003466
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003467 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003468 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003469 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003470 }
3471
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003472 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003473
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003474 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3475 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003476 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003477
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003478 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003479
3480drop:
3481 kfree_skb(skb);
3482 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003483}
3484
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003485static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003486{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003487 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003488 rx_control);
3489
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003490 chan->expected_ack_seq = __get_reqseq(rx_control);
3491 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003492
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003493 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003494 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3495 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3496 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003497 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003498 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003499
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003500 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003501 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003502 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003503 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003504 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003505
3506 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003507 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003508
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003509 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003510 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003511
3512 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003513 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003514 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003515 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003516
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003517 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3518 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003519 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003520 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003521 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003522 }
3523}
3524
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003525static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003526{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003527 u8 tx_seq = __get_reqseq(rx_control);
3528
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003529 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003530
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003531 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003532
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003533 chan->expected_ack_seq = tx_seq;
3534 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003535
3536 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003537 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003538 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003539 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003540 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003541
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003542 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3543 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003544 }
3545}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003546static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003547{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003548 u8 tx_seq = __get_reqseq(rx_control);
3549
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003550 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003551
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003552 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003553
3554 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003555 chan->expected_ack_seq = tx_seq;
3556 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003557
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003558 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003559 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003560
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003561 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003562
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003563 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003564 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003565 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003566 }
3567 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003568 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003569 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003570 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003571 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003572 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003573 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003574 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003575 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003576 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003577 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003578 }
3579 }
3580}
3581
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003582static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003583{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003584 u8 tx_seq = __get_reqseq(rx_control);
3585
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003586 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003587
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003588 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003589 chan->expected_ack_seq = tx_seq;
3590 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003591
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003592 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003593 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003594
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003595 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003596 __clear_retrans_timer(chan);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003597 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003598 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003599 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003600 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003601
3602 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003603 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003604 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003605 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003606}
3607
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003608static 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 -03003609{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003610 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003611
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003612 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003613 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003614 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003615 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003616 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003617 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003618 }
3619
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003620 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3621 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003622 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003623 break;
3624
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003625 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003626 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003627 break;
3628
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003629 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003630 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003631 break;
3632
3633 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003634 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003635 break;
3636 }
3637
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003638 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003639 return 0;
3640}
3641
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003642static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3643{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003644 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003645 u16 control;
3646 u8 req_seq;
3647 int len, next_tx_seq_offset, req_seq_offset;
3648
3649 control = get_unaligned_le16(skb->data);
3650 skb_pull(skb, 2);
3651 len = skb->len;
3652
3653 /*
3654 * We can just drop the corrupted I-frame here.
3655 * Receiver will miss it and start proper recovery
3656 * procedures and ask retransmission.
3657 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003658 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003659 goto drop;
3660
3661 if (__is_sar_start(control) && __is_iframe(control))
3662 len -= 2;
3663
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003664 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003665 len -= 2;
3666
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003667 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003668 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003669 goto drop;
3670 }
3671
3672 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003673 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003674 if (req_seq_offset < 0)
3675 req_seq_offset += 64;
3676
3677 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003678 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003679 if (next_tx_seq_offset < 0)
3680 next_tx_seq_offset += 64;
3681
3682 /* check for invalid req-seq */
3683 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003684 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003685 goto drop;
3686 }
3687
3688 if (__is_iframe(control)) {
3689 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003690 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003691 goto drop;
3692 }
3693
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003694 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003695 } else {
3696 if (len != 0) {
3697 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003698 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003699 goto drop;
3700 }
3701
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003702 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003703 }
3704
3705 return 0;
3706
3707drop:
3708 kfree_skb(skb);
3709 return 0;
3710}
3711
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3713{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003714 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003715 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003716 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003717 u8 tx_seq;
3718 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003719
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003720 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003721 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722 BT_DBG("unknown cid 0x%4.4x", cid);
3723 goto drop;
3724 }
3725
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003726 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003727
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003728 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003729
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003730 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003731 goto drop;
3732
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003733 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003734 case L2CAP_MODE_BASIC:
3735 /* If socket recv buffers overflows we drop data here
3736 * which is *bad* because L2CAP has to be reliable.
3737 * But we don't have any other choice. L2CAP doesn't
3738 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003739
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003740 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003741 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003743 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003744 goto done;
3745 break;
3746
3747 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003748 if (!sock_owned_by_user(sk)) {
3749 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003750 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003751 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003752 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003753 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003754
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003755 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003756
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003757 case L2CAP_MODE_STREAMING:
3758 control = get_unaligned_le16(skb->data);
3759 skb_pull(skb, 2);
3760 len = skb->len;
3761
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003762 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003763 goto drop;
3764
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003765 if (__is_sar_start(control))
3766 len -= 2;
3767
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003768 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003769 len -= 2;
3770
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003771 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003772 goto drop;
3773
3774 tx_seq = __get_txseq(control);
3775
Mat Martineau84084a32011-07-22 14:54:00 -07003776 if (chan->expected_tx_seq != tx_seq) {
3777 /* Frame(s) missing - must discard partial SDU */
3778 kfree_skb(chan->sdu);
3779 chan->sdu = NULL;
3780 chan->sdu_last_frag = NULL;
3781 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003782
Mat Martineau84084a32011-07-22 14:54:00 -07003783 /* TODO: Notify userland of missing data */
3784 }
3785
3786 chan->expected_tx_seq = (tx_seq + 1) % 64;
3787
3788 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
3789 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003790
3791 goto done;
3792
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003793 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003794 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003795 break;
3796 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797
3798drop:
3799 kfree_skb(skb);
3800
3801done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003802 if (sk)
3803 bh_unlock_sock(sk);
3804
Linus Torvalds1da177e2005-04-16 15:20:36 -07003805 return 0;
3806}
3807
Al Viro8e036fc2007-07-29 00:16:36 -07003808static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003810 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003811 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003813 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3814 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815 goto drop;
3816
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003817 sk = chan->sk;
3818
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003819 bh_lock_sock(sk);
3820
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821 BT_DBG("sk %p, len %d", sk, skb->len);
3822
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003823 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824 goto drop;
3825
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003826 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827 goto drop;
3828
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003829 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830 goto done;
3831
3832drop:
3833 kfree_skb(skb);
3834
3835done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003836 if (sk)
3837 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838 return 0;
3839}
3840
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003841static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3842{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003843 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003844 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003845
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003846 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3847 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003848 goto drop;
3849
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003850 sk = chan->sk;
3851
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003852 bh_lock_sock(sk);
3853
3854 BT_DBG("sk %p, len %d", sk, skb->len);
3855
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003856 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003857 goto drop;
3858
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003859 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003860 goto drop;
3861
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003862 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003863 goto done;
3864
3865drop:
3866 kfree_skb(skb);
3867
3868done:
3869 if (sk)
3870 bh_unlock_sock(sk);
3871 return 0;
3872}
3873
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3875{
3876 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003877 u16 cid, len;
3878 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879
3880 skb_pull(skb, L2CAP_HDR_SIZE);
3881 cid = __le16_to_cpu(lh->cid);
3882 len = __le16_to_cpu(lh->len);
3883
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003884 if (len != skb->len) {
3885 kfree_skb(skb);
3886 return;
3887 }
3888
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3890
3891 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003892 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003893 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894 l2cap_sig_channel(conn, skb);
3895 break;
3896
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003897 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003898 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899 skb_pull(skb, 2);
3900 l2cap_conless_channel(conn, psm, skb);
3901 break;
3902
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003903 case L2CAP_CID_LE_DATA:
3904 l2cap_att_channel(conn, cid, skb);
3905 break;
3906
Anderson Brigliab501d6a2011-06-07 18:46:31 -03003907 case L2CAP_CID_SMP:
3908 if (smp_sig_channel(conn, skb))
3909 l2cap_conn_del(conn->hcon, EACCES);
3910 break;
3911
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912 default:
3913 l2cap_data_channel(conn, cid, skb);
3914 break;
3915 }
3916}
3917
3918/* ---- L2CAP interface with lower layer (HCI) ---- */
3919
3920static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3921{
3922 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003923 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924
3925 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003926 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927
3928 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3929
3930 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003931 read_lock(&chan_list_lock);
3932 list_for_each_entry(c, &chan_list, global_l) {
3933 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003934
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003935 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003936 continue;
3937
3938 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003939 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003940 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003941 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003943 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3944 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003945 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003946 lm2 |= HCI_LM_MASTER;
3947 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003949 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950
3951 return exact ? lm1 : lm2;
3952}
3953
3954static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3955{
Marcel Holtmann01394182006-07-03 10:02:46 +02003956 struct l2cap_conn *conn;
3957
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3959
Ville Tervoacd7d372011-02-10 22:38:49 -03003960 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003961 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962
3963 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964 conn = l2cap_conn_add(hcon, status);
3965 if (conn)
3966 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003967 } else
Joe Perchese1750722011-06-29 18:18:29 -07003968 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969
3970 return 0;
3971}
3972
Marcel Holtmann2950f212009-02-12 14:02:50 +01003973static int l2cap_disconn_ind(struct hci_conn *hcon)
3974{
3975 struct l2cap_conn *conn = hcon->l2cap_data;
3976
3977 BT_DBG("hcon %p", hcon);
3978
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03003979 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01003980 return 0x13;
3981
3982 return conn->disc_reason;
3983}
3984
3985static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986{
3987 BT_DBG("hcon %p reason %d", hcon, reason);
3988
Ville Tervoacd7d372011-02-10 22:38:49 -03003989 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003990 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991
Joe Perchese1750722011-06-29 18:18:29 -07003992 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003993
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994 return 0;
3995}
3996
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003997static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003998{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03003999 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004000 return;
4001
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004002 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004003 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004004 __clear_chan_timer(chan);
4005 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004006 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004007 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004008 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004009 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004010 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004011 }
4012}
4013
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004014static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004015{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004016 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004017 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018
Marcel Holtmann01394182006-07-03 10:02:46 +02004019 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004021
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022 BT_DBG("conn %p", conn);
4023
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004024 if (hcon->type == LE_LINK) {
4025 smp_distribute_keys(conn, 0);
4026 del_timer(&conn->security_timer);
4027 }
4028
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004029 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004030
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004031 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004032 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004033
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034 bh_lock_sock(sk);
4035
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004036 BT_DBG("chan->scid %d", chan->scid);
4037
4038 if (chan->scid == L2CAP_CID_LE_DATA) {
4039 if (!status && encrypt) {
4040 chan->sec_level = hcon->sec_level;
4041 l2cap_chan_ready(sk);
4042 }
4043
4044 bh_unlock_sock(sk);
4045 continue;
4046 }
4047
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004048 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004049 bh_unlock_sock(sk);
4050 continue;
4051 }
4052
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004053 if (!status && (chan->state == BT_CONNECTED ||
4054 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004055 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004056 bh_unlock_sock(sk);
4057 continue;
4058 }
4059
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004060 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004061 if (!status) {
4062 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004063 req.scid = cpu_to_le16(chan->scid);
4064 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004065
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004066 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004067 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004068
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004069 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004070 L2CAP_CONN_REQ, sizeof(req), &req);
4071 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004072 __clear_chan_timer(chan);
4073 __set_chan_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004074 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004075 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004076 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004077 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004078
4079 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004080 if (bt_sk(sk)->defer_setup) {
4081 struct sock *parent = bt_sk(sk)->parent;
4082 res = L2CAP_CR_PEND;
4083 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004084 if (parent)
4085 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004086 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004087 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004088 res = L2CAP_CR_SUCCESS;
4089 stat = L2CAP_CS_NO_INFO;
4090 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004091 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004092 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004093 __set_chan_timer(chan, HZ / 10);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004094 res = L2CAP_CR_SEC_BLOCK;
4095 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004096 }
4097
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004098 rsp.scid = cpu_to_le16(chan->dcid);
4099 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004100 rsp.result = cpu_to_le16(res);
4101 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004102 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4103 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104 }
4105
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106 bh_unlock_sock(sk);
4107 }
4108
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004109 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004110
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111 return 0;
4112}
4113
4114static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4115{
4116 struct l2cap_conn *conn = hcon->l2cap_data;
4117
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004118 if (!conn)
4119 conn = l2cap_conn_add(hcon, 0);
4120
4121 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122 goto drop;
4123
4124 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4125
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004126 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004128 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004129 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130 int len;
4131
4132 if (conn->rx_len) {
4133 BT_ERR("Unexpected start frame (len %d)", skb->len);
4134 kfree_skb(conn->rx_skb);
4135 conn->rx_skb = NULL;
4136 conn->rx_len = 0;
4137 l2cap_conn_unreliable(conn, ECOMM);
4138 }
4139
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004140 /* Start fragment always begin with Basic L2CAP header */
4141 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142 BT_ERR("Frame is too short (len %d)", skb->len);
4143 l2cap_conn_unreliable(conn, ECOMM);
4144 goto drop;
4145 }
4146
4147 hdr = (struct l2cap_hdr *) skb->data;
4148 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004149 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150
4151 if (len == skb->len) {
4152 /* Complete frame received */
4153 l2cap_recv_frame(conn, skb);
4154 return 0;
4155 }
4156
4157 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4158
4159 if (skb->len > len) {
4160 BT_ERR("Frame is too long (len %d, expected len %d)",
4161 skb->len, len);
4162 l2cap_conn_unreliable(conn, ECOMM);
4163 goto drop;
4164 }
4165
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004166 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004167
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004168 if (chan && chan->sk) {
4169 struct sock *sk = chan->sk;
4170
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004171 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004172 BT_ERR("Frame exceeding recv MTU (len %d, "
4173 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004174 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004175 bh_unlock_sock(sk);
4176 l2cap_conn_unreliable(conn, ECOMM);
4177 goto drop;
4178 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004179 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004180 }
4181
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004183 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4184 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185 goto drop;
4186
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004187 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004188 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189 conn->rx_len = len - skb->len;
4190 } else {
4191 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4192
4193 if (!conn->rx_len) {
4194 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4195 l2cap_conn_unreliable(conn, ECOMM);
4196 goto drop;
4197 }
4198
4199 if (skb->len > conn->rx_len) {
4200 BT_ERR("Fragment is too long (len %d, expected %d)",
4201 skb->len, conn->rx_len);
4202 kfree_skb(conn->rx_skb);
4203 conn->rx_skb = NULL;
4204 conn->rx_len = 0;
4205 l2cap_conn_unreliable(conn, ECOMM);
4206 goto drop;
4207 }
4208
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004209 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004210 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211 conn->rx_len -= skb->len;
4212
4213 if (!conn->rx_len) {
4214 /* Complete frame received */
4215 l2cap_recv_frame(conn, conn->rx_skb);
4216 conn->rx_skb = NULL;
4217 }
4218 }
4219
4220drop:
4221 kfree_skb(skb);
4222 return 0;
4223}
4224
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004225static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004227 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004229 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004231 list_for_each_entry(c, &chan_list, global_l) {
4232 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004234 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 +01004235 batostr(&bt_sk(sk)->src),
4236 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004237 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004238 c->scid, c->dcid, c->imtu, c->omtu,
4239 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004240}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004241
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004242 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004243
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004244 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245}
4246
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004247static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4248{
4249 return single_open(file, l2cap_debugfs_show, inode->i_private);
4250}
4251
4252static const struct file_operations l2cap_debugfs_fops = {
4253 .open = l2cap_debugfs_open,
4254 .read = seq_read,
4255 .llseek = seq_lseek,
4256 .release = single_release,
4257};
4258
4259static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260
Linus Torvalds1da177e2005-04-16 15:20:36 -07004261static struct hci_proto l2cap_hci_proto = {
4262 .name = "L2CAP",
4263 .id = HCI_PROTO_L2CAP,
4264 .connect_ind = l2cap_connect_ind,
4265 .connect_cfm = l2cap_connect_cfm,
4266 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004267 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004268 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269 .recv_acldata = l2cap_recv_acldata
4270};
4271
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004272int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273{
4274 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004275
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004276 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004277 if (err < 0)
4278 return err;
4279
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280 err = hci_register_proto(&l2cap_hci_proto);
4281 if (err < 0) {
4282 BT_ERR("L2CAP protocol registration failed");
4283 bt_sock_unregister(BTPROTO_L2CAP);
4284 goto error;
4285 }
4286
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004287 if (bt_debugfs) {
4288 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4289 bt_debugfs, NULL, &l2cap_debugfs_fops);
4290 if (!l2cap_debugfs)
4291 BT_ERR("Failed to create L2CAP debug file");
4292 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293
Linus Torvalds1da177e2005-04-16 15:20:36 -07004294 return 0;
4295
4296error:
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004297 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004298 return err;
4299}
4300
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004301void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004302{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004303 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004304
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4306 BT_ERR("L2CAP protocol unregistration failed");
4307
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004308 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309}
4310
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004311module_param(disable_ertm, bool, 0644);
4312MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03004313
4314module_param(enable_hs, bool, 0644);
4315MODULE_PARM_DESC(enable_hs, "Enable High Speed");