blob: 22133464d65b491735e39c51b2c4846cc265dfbd [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. Padovan89bc500e2011-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. Padovan89bc500e2011-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. Padovan89bc500e2011-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. Padovan89bc500e2011-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. Padovan89bc500e2011-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. Padovan89bc500e2011-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
Andrei Emeltchenko8f7975b2011-10-13 16:18:54 +0300341 chan->local_id = L2CAP_BESTEFFORT_ID;
342 chan->local_stype = L2CAP_SERV_BESTEFFORT;
343 chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE;
344 chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME;
345 chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT;
346 chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO;
347
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300348 chan_hold(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300349
350 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200351}
352
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900353/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200354 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300355static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200356{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300357 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300358 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200359 struct sock *parent = bt_sk(sk)->parent;
360
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300361 __clear_chan_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200362
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300363 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200364
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900365 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300366 /* Delete from channel list */
367 write_lock_bh(&conn->chan_lock);
368 list_del(&chan->list);
369 write_unlock_bh(&conn->chan_lock);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300370 chan_put(chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300371
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300372 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200373 hci_conn_put(conn->hcon);
374 }
375
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300376 l2cap_state_change(chan, BT_CLOSED);
Marcel Holtmann01394182006-07-03 10:02:46 +0200377 sock_set_flag(sk, SOCK_ZAPPED);
378
379 if (err)
380 sk->sk_err = err;
381
382 if (parent) {
383 bt_accept_unlink(sk);
384 parent->sk_data_ready(parent, 0);
385 } else
386 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300387
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300388 if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
389 test_bit(CONF_INPUT_DONE, &chan->conf_state)))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300390 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300391
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300392 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300393
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300394 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300395 struct srej_list *l, *tmp;
396
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300397 __clear_retrans_timer(chan);
398 __clear_monitor_timer(chan);
399 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300400
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300401 skb_queue_purge(&chan->srej_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300402
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300403 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300404 list_del(&l->list);
405 kfree(l);
406 }
407 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200408}
409
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300410static void l2cap_chan_cleanup_listen(struct sock *parent)
411{
412 struct sock *sk;
413
414 BT_DBG("parent %p", parent);
415
416 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300417 while ((sk = bt_accept_dequeue(parent, NULL))) {
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300418 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300419 __clear_chan_timer(chan);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300420 lock_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300421 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300422 release_sock(sk);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300423 chan->ops->close(chan->data);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300424 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300425}
426
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300427void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300428{
429 struct l2cap_conn *conn = chan->conn;
430 struct sock *sk = chan->sk;
431
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300432 BT_DBG("chan %p state %d socket %p", chan, chan->state, sk->sk_socket);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300433
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300434 switch (chan->state) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300435 case BT_LISTEN:
436 l2cap_chan_cleanup_listen(sk);
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300437
438 l2cap_state_change(chan, BT_CLOSED);
439 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300440 break;
441
442 case BT_CONNECTED:
443 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300444 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300445 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300446 __clear_chan_timer(chan);
447 __set_chan_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300448 l2cap_send_disconn_req(conn, chan, reason);
449 } else
450 l2cap_chan_del(chan, reason);
451 break;
452
453 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300454 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300455 conn->hcon->type == ACL_LINK) {
456 struct l2cap_conn_rsp rsp;
457 __u16 result;
458
459 if (bt_sk(sk)->defer_setup)
460 result = L2CAP_CR_SEC_BLOCK;
461 else
462 result = L2CAP_CR_BAD_PSM;
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300463 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300464
465 rsp.scid = cpu_to_le16(chan->dcid);
466 rsp.dcid = cpu_to_le16(chan->scid);
467 rsp.result = cpu_to_le16(result);
468 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
469 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
470 sizeof(rsp), &rsp);
471 }
472
473 l2cap_chan_del(chan, reason);
474 break;
475
476 case BT_CONNECT:
477 case BT_DISCONN:
478 l2cap_chan_del(chan, reason);
479 break;
480
481 default:
482 sock_set_flag(sk, SOCK_ZAPPED);
483 break;
484 }
485}
486
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300487static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530488{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300489 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300490 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530491 case BT_SECURITY_HIGH:
492 return HCI_AT_DEDICATED_BONDING_MITM;
493 case BT_SECURITY_MEDIUM:
494 return HCI_AT_DEDICATED_BONDING;
495 default:
496 return HCI_AT_NO_BONDING;
497 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300498 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300499 if (chan->sec_level == BT_SECURITY_LOW)
500 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530501
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300502 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530503 return HCI_AT_NO_BONDING_MITM;
504 else
505 return HCI_AT_NO_BONDING;
506 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300507 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530508 case BT_SECURITY_HIGH:
509 return HCI_AT_GENERAL_BONDING_MITM;
510 case BT_SECURITY_MEDIUM:
511 return HCI_AT_GENERAL_BONDING;
512 default:
513 return HCI_AT_NO_BONDING;
514 }
515 }
516}
517
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200518/* Service level security */
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300519static inline int l2cap_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200520{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300521 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100522 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200523
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300524 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100525
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300526 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200527}
528
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200529static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200530{
531 u8 id;
532
533 /* Get next available identificator.
534 * 1 - 128 are used by kernel.
535 * 129 - 199 are reserved.
536 * 200 - 254 are used by utilities like l2ping, etc.
537 */
538
539 spin_lock_bh(&conn->lock);
540
541 if (++conn->tx_ident > 128)
542 conn->tx_ident = 1;
543
544 id = conn->tx_ident;
545
546 spin_unlock_bh(&conn->lock);
547
548 return id;
549}
550
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300551static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200552{
553 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200554 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200555
556 BT_DBG("code 0x%2.2x", code);
557
558 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300559 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200560
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200561 if (lmp_no_flush_capable(conn->hcon->hdev))
562 flags = ACL_START_NO_FLUSH;
563 else
564 flags = ACL_START;
565
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700566 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
567
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200568 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200569}
570
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300571static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300572{
573 struct sk_buff *skb;
574 struct l2cap_hdr *lh;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300575 struct l2cap_conn *conn = chan->conn;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300576 int count, hlen;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200577 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300578
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300579 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300580 return;
581
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +0300582 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
583 hlen = L2CAP_EXT_HDR_SIZE;
584 else
585 hlen = L2CAP_ENH_HDR_SIZE;
586
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300587 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300588 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300589
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300590 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300591
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300592 count = min_t(unsigned int, conn->mtu, hlen);
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +0300593
594 control |= __set_sframe(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300595
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300596 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +0300597 control |= __set_ctrl_final(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300598
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300599 if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +0300600 control |= __set_ctrl_poll(chan);
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300601
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300602 skb = bt_skb_alloc(count, GFP_ATOMIC);
603 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300604 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300605
606 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300607 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300608 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300609 put_unaligned_le16(control, skb_put(skb, 2));
610
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300611 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300612 u16 fcs = crc16(0, (u8 *)lh, count - 2);
613 put_unaligned_le16(fcs, skb_put(skb, 2));
614 }
615
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200616 if (lmp_no_flush_capable(conn->hcon->hdev))
617 flags = ACL_START_NO_FLUSH;
618 else
619 flags = ACL_START;
620
Andrei Emeltchenko15770b12011-10-11 14:04:33 +0300621 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700622
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300623 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300624}
625
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300626static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300627{
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300628 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300629 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -0300630 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300631 } else
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +0300632 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300633
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +0300634 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300635
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300636 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300637}
638
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300639static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300640{
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300641 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300642}
643
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300644static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200645{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300646 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200647
648 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100649 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
650 return;
651
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300652 if (l2cap_check_security(chan) &&
653 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200654 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300655 req.scid = cpu_to_le16(chan->scid);
656 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200657
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300658 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300659 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200660
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300661 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
662 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200663 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200664 } else {
665 struct l2cap_info_req req;
666 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
667
668 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
669 conn->info_ident = l2cap_get_ident(conn);
670
671 mod_timer(&conn->info_timer, jiffies +
672 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
673
674 l2cap_send_cmd(conn, conn->info_ident,
675 L2CAP_INFO_REQ, sizeof(req), &req);
676 }
677}
678
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300679static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
680{
681 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300682 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300683 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
684
685 switch (mode) {
686 case L2CAP_MODE_ERTM:
687 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
688 case L2CAP_MODE_STREAMING:
689 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
690 default:
691 return 0x00;
692 }
693}
694
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300695static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300696{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300697 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300698 struct l2cap_disconn_req req;
699
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300700 if (!conn)
701 return;
702
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300703 sk = chan->sk;
704
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300705 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -0300706 __clear_retrans_timer(chan);
707 __clear_monitor_timer(chan);
708 __clear_ack_timer(chan);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300709 }
710
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300711 req.dcid = cpu_to_le16(chan->dcid);
712 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300713 l2cap_send_cmd(conn, l2cap_get_ident(conn),
714 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300715
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300716 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300717 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300718}
719
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200721static void l2cap_conn_start(struct l2cap_conn *conn)
722{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300723 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200724
725 BT_DBG("conn %p", conn);
726
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300727 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200728
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300729 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300730 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300731
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200732 bh_lock_sock(sk);
733
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300734 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200735 bh_unlock_sock(sk);
736 continue;
737 }
738
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300739 if (chan->state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300740 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300741
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300742 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300743 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300744 bh_unlock_sock(sk);
745 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200746 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300747
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300748 if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
749 && test_bit(CONF_STATE2_DEVICE,
750 &chan->conf_state)) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300751 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300752 * so release the lock */
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300753 read_unlock(&conn->chan_lock);
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300754 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan2461daa2011-06-17 12:57:25 -0300755 read_lock(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300756 bh_unlock_sock(sk);
757 continue;
758 }
759
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300760 req.scid = cpu_to_le16(chan->scid);
761 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300762
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300763 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300764 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300765
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300766 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
767 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300768
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300769 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200770 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300771 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300772 rsp.scid = cpu_to_le16(chan->dcid);
773 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200774
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300775 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100776 if (bt_sk(sk)->defer_setup) {
777 struct sock *parent = bt_sk(sk)->parent;
778 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
779 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +0000780 if (parent)
781 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100782
783 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300784 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100785 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
786 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
787 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200788 } else {
789 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
790 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
791 }
792
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300793 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
794 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300795
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300796 if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300797 rsp.result != L2CAP_CR_SUCCESS) {
798 bh_unlock_sock(sk);
799 continue;
800 }
801
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -0300802 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300803 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300804 l2cap_build_conf_req(chan, buf), buf);
805 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200806 }
807
808 bh_unlock_sock(sk);
809 }
810
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300811 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200812}
813
Ville Tervob62f3282011-02-10 22:38:50 -0300814/* Find socket with cid and source bdaddr.
815 * Returns closest match, locked.
816 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300817static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300818{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300819 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300820
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300821 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300822
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300823 list_for_each_entry(c, &chan_list, global_l) {
824 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300825
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300826 if (state && c->state != state)
Ville Tervob62f3282011-02-10 22:38:50 -0300827 continue;
828
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300829 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300830 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300831 if (!bacmp(&bt_sk(sk)->src, src)) {
832 read_unlock(&chan_list_lock);
833 return c;
834 }
Ville Tervob62f3282011-02-10 22:38:50 -0300835
836 /* Closest match */
837 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300838 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300839 }
840 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300841
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300842 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300843
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300844 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300845}
846
847static void l2cap_le_conn_ready(struct l2cap_conn *conn)
848{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300849 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300850 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300851
852 BT_DBG("");
853
854 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300855 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300856 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300857 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300858 return;
859
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300860 parent = pchan->sk;
861
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300862 bh_lock_sock(parent);
863
Ville Tervob62f3282011-02-10 22:38:50 -0300864 /* Check for backlog size */
865 if (sk_acceptq_is_full(parent)) {
866 BT_DBG("backlog full %d", parent->sk_ack_backlog);
867 goto clean;
868 }
869
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300870 chan = pchan->ops->new_connection(pchan->data);
871 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300872 goto clean;
873
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300874 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300875
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300876 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300877
878 hci_conn_hold(conn->hcon);
879
Ville Tervob62f3282011-02-10 22:38:50 -0300880 bacpy(&bt_sk(sk)->src, conn->src);
881 bacpy(&bt_sk(sk)->dst, conn->dst);
882
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300883 bt_accept_enqueue(parent, sk);
884
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300885 __l2cap_chan_add(conn, chan);
886
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300887 __set_chan_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300888
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300889 l2cap_state_change(chan, BT_CONNECTED);
Ville Tervob62f3282011-02-10 22:38:50 -0300890 parent->sk_data_ready(parent, 0);
891
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300892 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300893
894clean:
895 bh_unlock_sock(parent);
896}
897
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300898static void l2cap_chan_ready(struct sock *sk)
899{
900 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
901 struct sock *parent = bt_sk(sk)->parent;
902
903 BT_DBG("sk %p, parent %p", sk, parent);
904
905 chan->conf_state = 0;
906 __clear_chan_timer(chan);
907
Vinicius Costa Gomes43f3dc42011-06-20 18:53:18 -0300908 l2cap_state_change(chan, BT_CONNECTED);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300909 sk->sk_state_change(sk);
910
911 if (parent)
912 parent->sk_data_ready(parent, 0);
913}
914
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200915static void l2cap_conn_ready(struct l2cap_conn *conn)
916{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300917 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200918
919 BT_DBG("conn %p", conn);
920
Ville Tervob62f3282011-02-10 22:38:50 -0300921 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
922 l2cap_le_conn_ready(conn);
923
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -0300924 if (conn->hcon->out && conn->hcon->type == LE_LINK)
925 smp_conn_security(conn, conn->hcon->pending_sec_level);
926
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300927 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200928
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300929 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300930 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300931
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200932 bh_lock_sock(sk);
933
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300934 if (conn->hcon->type == LE_LINK) {
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300935 if (smp_conn_security(conn, chan->sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300936 l2cap_chan_ready(sk);
Ville Tervoacd7d372011-02-10 22:38:49 -0300937
Vinicius Costa Gomes63128452011-06-17 22:46:26 -0300938 } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300939 __clear_chan_timer(chan);
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300940 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200941 sk->sk_state_change(sk);
Anderson Brigliab501d6a2011-06-07 18:46:31 -0300942
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -0300943 } else if (chan->state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300944 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200945
946 bh_unlock_sock(sk);
947 }
948
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300949 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200950}
951
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200952/* Notify sockets that we cannot guaranty reliability anymore */
953static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
954{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300955 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200956
957 BT_DBG("conn %p", conn);
958
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300959 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200960
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300961 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300962 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300963
Andrei Emeltchenkoecf61bd2011-10-11 14:04:32 +0300964 if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200965 sk->sk_err = err;
966 }
967
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300968 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200969}
970
971static void l2cap_info_timeout(unsigned long arg)
972{
973 struct l2cap_conn *conn = (void *) arg;
974
Marcel Holtmann984947d2009-02-06 23:35:19 +0100975 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100976 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100977
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200978 l2cap_conn_start(conn);
979}
980
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -0300981static void l2cap_conn_del(struct hci_conn *hcon, int err)
982{
983 struct l2cap_conn *conn = hcon->l2cap_data;
984 struct l2cap_chan *chan, *l;
985 struct sock *sk;
986
987 if (!conn)
988 return;
989
990 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
991
992 kfree_skb(conn->rx_skb);
993
994 /* Kill channels */
995 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
996 sk = chan->sk;
997 bh_lock_sock(sk);
998 l2cap_chan_del(chan, err);
999 bh_unlock_sock(sk);
1000 chan->ops->close(chan->data);
1001 }
1002
1003 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1004 del_timer_sync(&conn->info_timer);
1005
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001006 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) {
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001007 del_timer(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001008 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001009 }
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001010
1011 hcon->l2cap_data = NULL;
1012 kfree(conn);
1013}
1014
1015static void security_timeout(unsigned long arg)
1016{
1017 struct l2cap_conn *conn = (void *) arg;
1018
1019 l2cap_conn_del(conn->hcon, ETIMEDOUT);
1020}
1021
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
1023{
Marcel Holtmann01394182006-07-03 10:02:46 +02001024 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025
Marcel Holtmann01394182006-07-03 10:02:46 +02001026 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 return conn;
1028
Marcel Holtmann01394182006-07-03 10:02:46 +02001029 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
1030 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032
1033 hcon->l2cap_data = conn;
1034 conn->hcon = hcon;
1035
Marcel Holtmann01394182006-07-03 10:02:46 +02001036 BT_DBG("hcon %p conn %p", hcon, conn);
1037
Ville Tervoacd7d372011-02-10 22:38:49 -03001038 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1039 conn->mtu = hcon->hdev->le_mtu;
1040 else
1041 conn->mtu = hcon->hdev->acl_mtu;
1042
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 conn->src = &hcon->hdev->bdaddr;
1044 conn->dst = &hcon->dst;
1045
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001046 conn->feat_mask = 0;
1047
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001049 rwlock_init(&conn->chan_lock);
1050
1051 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -03001053 if (hcon->type == LE_LINK)
1054 setup_timer(&conn->security_timer, security_timeout,
1055 (unsigned long) conn);
1056 else
Ville Tervob62f3282011-02-10 22:38:50 -03001057 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +00001058 (unsigned long) conn);
1059
Marcel Holtmann2950f212009-02-12 14:02:50 +01001060 conn->disc_reason = 0x13;
1061
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 return conn;
1063}
1064
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001065static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001067 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001068 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001069 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070}
1071
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073
1074/* Find socket with psm and source bdaddr.
1075 * Returns closest match.
1076 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001077static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001079 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001081 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001082
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001083 list_for_each_entry(c, &chan_list, global_l) {
1084 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001085
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03001086 if (state && c->state != state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 continue;
1088
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001089 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001091 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001092 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001093 return c;
1094 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095
1096 /* Closest match */
1097 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001098 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 }
1100 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001102 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001103
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001104 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105}
1106
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001107int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001109 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 bdaddr_t *src = &bt_sk(sk)->src;
1111 bdaddr_t *dst = &bt_sk(sk)->dst;
1112 struct l2cap_conn *conn;
1113 struct hci_conn *hcon;
1114 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001115 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001116 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001118 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001119 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001121 hdev = hci_get_route(dst, src);
1122 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 return -EHOSTUNREACH;
1124
1125 hci_dev_lock_bh(hdev);
1126
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001127 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001128
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001129 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001130 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001131 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001132 else
1133 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001134 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001135
Ville Tervo30e76272011-02-22 16:10:53 -03001136 if (IS_ERR(hcon)) {
1137 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001139 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140
1141 conn = l2cap_conn_add(hcon, 0);
1142 if (!conn) {
1143 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001144 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 goto done;
1146 }
1147
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 /* Update source addr of the socket */
1149 bacpy(src, conn->src);
1150
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001151 l2cap_chan_add(conn, chan);
1152
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03001153 l2cap_state_change(chan, BT_CONNECT);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001154 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155
1156 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001157 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03001158 __clear_chan_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001159 if (l2cap_check_security(chan))
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03001160 l2cap_state_change(chan, BT_CONNECTED);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001161 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001162 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 }
1164
Ville Tervo30e76272011-02-22 16:10:53 -03001165 err = 0;
1166
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167done:
1168 hci_dev_unlock_bh(hdev);
1169 hci_dev_put(hdev);
1170 return err;
1171}
1172
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001173int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001174{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001175 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001176 DECLARE_WAITQUEUE(wait, current);
1177 int err = 0;
1178 int timeo = HZ/5;
1179
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001180 add_wait_queue(sk_sleep(sk), &wait);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001181 set_current_state(TASK_INTERRUPTIBLE);
1182 while (chan->unacked_frames > 0 && chan->conn) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001183 if (!timeo)
1184 timeo = HZ/5;
1185
1186 if (signal_pending(current)) {
1187 err = sock_intr_errno(timeo);
1188 break;
1189 }
1190
1191 release_sock(sk);
1192 timeo = schedule_timeout(timeo);
1193 lock_sock(sk);
Peter Hurleya71a0cf2011-07-25 18:36:26 -04001194 set_current_state(TASK_INTERRUPTIBLE);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001195
1196 err = sock_error(sk);
1197 if (err)
1198 break;
1199 }
1200 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001201 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001202 return err;
1203}
1204
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001205static void l2cap_monitor_timeout(unsigned long arg)
1206{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001207 struct l2cap_chan *chan = (void *) arg;
1208 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001209
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001210 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001211
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001212 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001213 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001214 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001215 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001216 return;
1217 }
1218
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001219 chan->retry_count++;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001220 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001221
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001222 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001223 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001224}
1225
1226static void l2cap_retrans_timeout(unsigned long arg)
1227{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001228 struct l2cap_chan *chan = (void *) arg;
1229 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001230
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001231 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001232
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001233 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001234 chan->retry_count = 1;
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001235 __set_monitor_timer(chan);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001236
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001237 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001238
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001239 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001240 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001241}
1242
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001243static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001244{
1245 struct sk_buff *skb;
1246
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001247 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001248 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001249 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001250 break;
1251
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001252 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001253 kfree_skb(skb);
1254
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001255 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001256 }
1257
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001258 if (!chan->unacked_frames)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001259 __clear_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001260}
1261
Szymon Janc67c9e842011-07-28 16:24:33 +02001262static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001263{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001264 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001265 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001266
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001267 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001268
Andrei Emeltchenkod57b0e82011-10-11 14:04:31 +03001269 if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
1270 lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001271 flags = ACL_START_NO_FLUSH;
1272 else
1273 flags = ACL_START;
1274
Andrei Emeltchenko15770b12011-10-11 14:04:33 +03001275 bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001276 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001277}
1278
Szymon Janc67c9e842011-07-28 16:24:33 +02001279static void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001280{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001281 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001282 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001283
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001284 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001285 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001286 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001287 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001288
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001289 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001290 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1291 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001292 }
1293
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001294 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001295
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001296 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001297 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001298}
1299
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001300static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001301{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001302 struct sk_buff *skb, *tx_skb;
1303 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001304
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001305 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001306 if (!skb)
1307 return;
1308
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001309 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001310 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001311 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001312
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001313 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001314 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001315
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001316 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001317
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001318 if (chan->remote_max_tx &&
1319 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001320 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001321 return;
1322 }
1323
1324 tx_skb = skb_clone(skb, GFP_ATOMIC);
1325 bt_cb(skb)->retries++;
1326 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001327 control &= __get_sar_mask(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001328
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001329 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001330 control |= __set_ctrl_final(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001331
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001332 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001333 control |= __set_txseq(chan, tx_seq);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001334
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001335 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1336
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001337 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001338 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1339 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1340 }
1341
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001342 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001343}
1344
Szymon Janc67c9e842011-07-28 16:24:33 +02001345static int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001346{
1347 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001348 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001349 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001350
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03001351 if (chan->state != BT_CONNECTED)
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001352 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001353
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001354 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001355
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001356 if (chan->remote_max_tx &&
1357 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001358 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001359 break;
1360 }
1361
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001362 tx_skb = skb_clone(skb, GFP_ATOMIC);
1363
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001364 bt_cb(skb)->retries++;
1365
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001366 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001367 control &= __get_sar_mask(chan);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001368
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001369 if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001370 control |= __set_ctrl_final(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001371
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001372 control |= __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03001373 control |= __set_txseq(chan, chan->next_tx_seq);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001374 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1375
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001376
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001377 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001378 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1379 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1380 }
1381
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001382 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001383
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03001384 __set_retrans_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001385
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001386 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1387 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001388
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301389 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001390 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301391
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001392 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001393
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001394 if (skb_queue_is_last(&chan->tx_q, skb))
1395 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001396 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001397 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001398
1399 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001400 }
1401
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001402 return nsent;
1403}
1404
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001405static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001406{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001407 int ret;
1408
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001409 if (!skb_queue_empty(&chan->tx_q))
1410 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001411
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001412 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001413 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001414 return ret;
1415}
1416
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001417static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001418{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001419 u16 control = 0;
1420
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001421 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001422
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001423 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001424 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001425 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001426 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001427 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001428 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001429
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001430 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001431 return;
1432
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001433 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001434 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001435}
1436
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001437static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001438{
1439 struct srej_list *tail;
1440 u16 control;
1441
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03001442 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03001443 control |= __set_ctrl_final(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001444
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001445 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03001446 control |= __set_reqseq(chan, tail->tx_seq);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001447
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001448 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001449}
1450
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001451static 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 -07001452{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001453 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001454 struct sk_buff **frag;
1455 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001457 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001458 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459
1460 sent += count;
1461 len -= count;
1462
1463 /* Continuation fragments (no L2CAP header) */
1464 frag = &skb_shinfo(skb)->frag_list;
1465 while (len) {
1466 count = min_t(unsigned int, conn->mtu, len);
1467
1468 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1469 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001470 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001471 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1472 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473
1474 sent += count;
1475 len -= count;
1476
1477 frag = &(*frag)->next;
1478 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479
1480 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001481}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482
Szymon Janc67c9e842011-07-28 16:24:33 +02001483static 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 -03001484{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001485 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001486 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001487 struct sk_buff *skb;
1488 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1489 struct l2cap_hdr *lh;
1490
1491 BT_DBG("sk %p len %d", sk, (int)len);
1492
1493 count = min_t(unsigned int, (conn->mtu - hlen), len);
1494 skb = bt_skb_send_alloc(sk, count + hlen,
1495 msg->msg_flags & MSG_DONTWAIT, &err);
1496 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001497 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001498
1499 /* Create L2CAP header */
1500 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001501 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001502 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001503 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001504
1505 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1506 if (unlikely(err < 0)) {
1507 kfree_skb(skb);
1508 return ERR_PTR(err);
1509 }
1510 return skb;
1511}
1512
Szymon Janc67c9e842011-07-28 16:24:33 +02001513static 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 -03001514{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001515 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001516 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001517 struct sk_buff *skb;
1518 int err, count, hlen = L2CAP_HDR_SIZE;
1519 struct l2cap_hdr *lh;
1520
1521 BT_DBG("sk %p len %d", sk, (int)len);
1522
1523 count = min_t(unsigned int, (conn->mtu - hlen), len);
1524 skb = bt_skb_send_alloc(sk, count + hlen,
1525 msg->msg_flags & MSG_DONTWAIT, &err);
1526 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001527 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001528
1529 /* Create L2CAP header */
1530 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001531 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001532 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1533
1534 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1535 if (unlikely(err < 0)) {
1536 kfree_skb(skb);
1537 return ERR_PTR(err);
1538 }
1539 return skb;
1540}
1541
Luiz Augusto von Dentzab0ff762011-09-12 20:00:50 +03001542static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1543 struct msghdr *msg, size_t len,
1544 u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001545{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001546 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001547 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001548 struct sk_buff *skb;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001549 int err, count, hlen;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001550 struct l2cap_hdr *lh;
1551
1552 BT_DBG("sk %p len %d", sk, (int)len);
1553
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001554 if (!conn)
1555 return ERR_PTR(-ENOTCONN);
1556
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03001557 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1558 hlen = L2CAP_EXT_HDR_SIZE;
1559 else
1560 hlen = L2CAP_ENH_HDR_SIZE;
1561
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001562 if (sdulen)
1563 hlen += 2;
1564
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001565 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001566 hlen += 2;
1567
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001568 count = min_t(unsigned int, (conn->mtu - hlen), len);
1569 skb = bt_skb_send_alloc(sk, count + hlen,
1570 msg->msg_flags & MSG_DONTWAIT, &err);
1571 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001572 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001573
1574 /* Create L2CAP header */
1575 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001576 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001577 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1578 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001579 if (sdulen)
1580 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001581
1582 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1583 if (unlikely(err < 0)) {
1584 kfree_skb(skb);
1585 return ERR_PTR(err);
1586 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001587
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001588 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001589 put_unaligned_le16(0, skb_put(skb, 2));
1590
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001591 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001592 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593}
1594
Szymon Janc67c9e842011-07-28 16:24:33 +02001595static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001596{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001597 struct sk_buff *skb;
1598 struct sk_buff_head sar_queue;
1599 u16 control;
1600 size_t size = 0;
1601
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001602 skb_queue_head_init(&sar_queue);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001603 control = __set_ctrl_sar(chan, L2CAP_SAR_START);
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001604 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001605 if (IS_ERR(skb))
1606 return PTR_ERR(skb);
1607
1608 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001609 len -= chan->remote_mps;
1610 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001611
1612 while (len > 0) {
1613 size_t buflen;
1614
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001615 if (len > chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001616 control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001617 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001618 } else {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001619 control = __set_ctrl_sar(chan, L2CAP_SAR_END);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001620 buflen = len;
1621 }
1622
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001623 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001624 if (IS_ERR(skb)) {
1625 skb_queue_purge(&sar_queue);
1626 return PTR_ERR(skb);
1627 }
1628
1629 __skb_queue_tail(&sar_queue, skb);
1630 len -= buflen;
1631 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001632 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001633 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1634 if (chan->tx_send_head == NULL)
1635 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001636
1637 return size;
1638}
1639
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001640int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1641{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001642 struct sk_buff *skb;
1643 u16 control;
1644 int err;
1645
1646 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001647 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001648 skb = l2cap_create_connless_pdu(chan, msg, len);
1649 if (IS_ERR(skb))
1650 return PTR_ERR(skb);
1651
1652 l2cap_do_send(chan, skb);
1653 return len;
1654 }
1655
1656 switch (chan->mode) {
1657 case L2CAP_MODE_BASIC:
1658 /* Check outgoing MTU */
1659 if (len > chan->omtu)
1660 return -EMSGSIZE;
1661
1662 /* Create a basic PDU */
1663 skb = l2cap_create_basic_pdu(chan, msg, len);
1664 if (IS_ERR(skb))
1665 return PTR_ERR(skb);
1666
1667 l2cap_do_send(chan, skb);
1668 err = len;
1669 break;
1670
1671 case L2CAP_MODE_ERTM:
1672 case L2CAP_MODE_STREAMING:
1673 /* Entire SDU fits into one PDU */
1674 if (len <= chan->remote_mps) {
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03001675 control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001676 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1677 0);
1678 if (IS_ERR(skb))
1679 return PTR_ERR(skb);
1680
1681 __skb_queue_tail(&chan->tx_q, skb);
1682
1683 if (chan->tx_send_head == NULL)
1684 chan->tx_send_head = skb;
1685
1686 } else {
1687 /* Segment SDU into multiples PDUs */
1688 err = l2cap_sar_segment_sdu(chan, msg, len);
1689 if (err < 0)
1690 return err;
1691 }
1692
1693 if (chan->mode == L2CAP_MODE_STREAMING) {
1694 l2cap_streaming_send(chan);
1695 err = len;
1696 break;
1697 }
1698
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03001699 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1700 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001701 err = len;
1702 break;
1703 }
1704
1705 err = l2cap_ertm_send(chan);
1706 if (err >= 0)
1707 err = len;
1708
1709 break;
1710
1711 default:
1712 BT_DBG("bad state %1.1x", chan->mode);
1713 err = -EBADFD;
1714 }
1715
1716 return err;
1717}
1718
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719/* Copy frame to all raw sockets on that connection */
1720static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1721{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001723 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724
1725 BT_DBG("conn %p", conn);
1726
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001727 read_lock(&conn->chan_lock);
1728 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001729 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001730 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 continue;
1732
1733 /* Don't send frame to the socket it came from */
1734 if (skb->sk == sk)
1735 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001736 nskb = skb_clone(skb, GFP_ATOMIC);
1737 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 continue;
1739
Gustavo F. Padovan23070492011-05-16 17:57:22 -03001740 if (chan->ops->recv(chan->data, nskb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 kfree_skb(nskb);
1742 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001743 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744}
1745
1746/* ---- L2CAP signalling commands ---- */
1747static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1748 u8 code, u8 ident, u16 dlen, void *data)
1749{
1750 struct sk_buff *skb, **frag;
1751 struct l2cap_cmd_hdr *cmd;
1752 struct l2cap_hdr *lh;
1753 int len, count;
1754
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001755 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1756 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757
1758 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1759 count = min_t(unsigned int, conn->mtu, len);
1760
1761 skb = bt_skb_alloc(count, GFP_ATOMIC);
1762 if (!skb)
1763 return NULL;
1764
1765 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001766 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001767
1768 if (conn->hcon->type == LE_LINK)
1769 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1770 else
1771 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772
1773 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1774 cmd->code = code;
1775 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001776 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777
1778 if (dlen) {
1779 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1780 memcpy(skb_put(skb, count), data, count);
1781 data += count;
1782 }
1783
1784 len -= skb->len;
1785
1786 /* Continuation fragments (no L2CAP header) */
1787 frag = &skb_shinfo(skb)->frag_list;
1788 while (len) {
1789 count = min_t(unsigned int, conn->mtu, len);
1790
1791 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1792 if (!*frag)
1793 goto fail;
1794
1795 memcpy(skb_put(*frag, count), data, count);
1796
1797 len -= count;
1798 data += count;
1799
1800 frag = &(*frag)->next;
1801 }
1802
1803 return skb;
1804
1805fail:
1806 kfree_skb(skb);
1807 return NULL;
1808}
1809
1810static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1811{
1812 struct l2cap_conf_opt *opt = *ptr;
1813 int len;
1814
1815 len = L2CAP_CONF_OPT_SIZE + opt->len;
1816 *ptr += len;
1817
1818 *type = opt->type;
1819 *olen = opt->len;
1820
1821 switch (opt->len) {
1822 case 1:
1823 *val = *((u8 *) opt->val);
1824 break;
1825
1826 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001827 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 break;
1829
1830 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001831 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 break;
1833
1834 default:
1835 *val = (unsigned long) opt->val;
1836 break;
1837 }
1838
1839 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1840 return len;
1841}
1842
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1844{
1845 struct l2cap_conf_opt *opt = *ptr;
1846
1847 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1848
1849 opt->type = type;
1850 opt->len = len;
1851
1852 switch (len) {
1853 case 1:
1854 *((u8 *) opt->val) = val;
1855 break;
1856
1857 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001858 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 break;
1860
1861 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001862 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 break;
1864
1865 default:
1866 memcpy(opt->val, (void *) val, len);
1867 break;
1868 }
1869
1870 *ptr += L2CAP_CONF_OPT_SIZE + len;
1871}
1872
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001873static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
1874{
1875 struct l2cap_conf_efs efs;
1876
1877 switch(chan->mode) {
1878 case L2CAP_MODE_ERTM:
1879 efs.id = chan->local_id;
1880 efs.stype = chan->local_stype;
1881 efs.msdu = cpu_to_le16(chan->local_msdu);
1882 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1883 efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
1884 efs.flush_to = cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
1885 break;
1886
1887 case L2CAP_MODE_STREAMING:
1888 efs.id = 1;
1889 efs.stype = L2CAP_SERV_BESTEFFORT;
1890 efs.msdu = cpu_to_le16(chan->local_msdu);
1891 efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
1892 efs.acc_lat = 0;
1893 efs.flush_to = 0;
1894 break;
1895
1896 default:
1897 return;
1898 }
1899
1900 l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
1901 (unsigned long) &efs);
1902}
1903
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001904static void l2cap_ack_timeout(unsigned long arg)
1905{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001906 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001907
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001908 bh_lock_sock(chan->sk);
1909 l2cap_send_ack(chan);
1910 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001911}
1912
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001913static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001914{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001915 struct sock *sk = chan->sk;
1916
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001917 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001918 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001919 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001920 chan->num_acked = 0;
1921 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001922
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001923 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1924 (unsigned long) chan);
1925 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1926 (unsigned long) chan);
1927 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001928
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001929 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001930
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001931 INIT_LIST_HEAD(&chan->srej_l);
1932
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001933
1934 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001935}
1936
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001937static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1938{
1939 switch (mode) {
1940 case L2CAP_MODE_STREAMING:
1941 case L2CAP_MODE_ERTM:
1942 if (l2cap_mode_supported(mode, remote_feat_mask))
1943 return mode;
1944 /* fall through */
1945 default:
1946 return L2CAP_MODE_BASIC;
1947 }
1948}
1949
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001950static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
1951{
1952 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
1953}
1954
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001955static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
1956{
1957 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
1958}
1959
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001960static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
1961{
1962 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
1963 __l2cap_ews_supported(chan))
1964 /* use extended control field */
1965 set_bit(FLAG_EXT_CTRL, &chan->flags);
1966 else
1967 chan->tx_win = min_t(u16, chan->tx_win,
1968 L2CAP_DEFAULT_TX_WINDOW);
1969}
1970
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001971static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001974 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975 void *ptr = req->data;
1976
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001977 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001979 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001980 goto done;
1981
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001982 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001983 case L2CAP_MODE_STREAMING:
1984 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001985 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001986 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001987
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03001988 if (__l2cap_efs_supported(chan))
1989 set_bit(FLAG_EFS_ENABLE, &chan->flags);
1990
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001991 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001992 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001993 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001994 break;
1995 }
1996
1997done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001998 if (chan->imtu != L2CAP_DEFAULT_MTU)
1999 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02002000
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002001 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002002 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002003 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
2004 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002005 break;
2006
Gustavo F. Padovan62547752010-06-08 20:05:31 -03002007 rfc.mode = L2CAP_MODE_BASIC;
2008 rfc.txwin_size = 0;
2009 rfc.max_transmit = 0;
2010 rfc.retrans_timeout = 0;
2011 rfc.monitor_timeout = 0;
2012 rfc.max_pdu_size = 0;
2013
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002014 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2015 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002016 break;
2017
2018 case L2CAP_MODE_ERTM:
2019 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002020 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002021 rfc.retrans_timeout = 0;
2022 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002023 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002024 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
2025 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002026
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002027 l2cap_txwin_setup(chan);
2028
2029 rfc.txwin_size = min_t(u16, chan->tx_win,
2030 L2CAP_DEFAULT_TX_WINDOW);
2031
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002032 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2033 (unsigned long) &rfc);
2034
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002035 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2036 l2cap_add_opt_efs(&ptr, chan);
2037
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002038 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002039 break;
2040
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002041 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002042 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002043 chan->fcs = L2CAP_FCS_NONE;
2044 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002045 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002046
2047 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2048 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2049 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002050 break;
2051
2052 case L2CAP_MODE_STREAMING:
2053 rfc.mode = L2CAP_MODE_STREAMING;
2054 rfc.txwin_size = 0;
2055 rfc.max_transmit = 0;
2056 rfc.retrans_timeout = 0;
2057 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002058 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002059 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
2060 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002061
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002062 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2063 (unsigned long) &rfc);
2064
Andrei Emeltchenkof89cef02011-10-13 16:18:55 +03002065 if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2066 l2cap_add_opt_efs(&ptr, chan);
2067
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002068 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002069 break;
2070
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002071 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002072 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002073 chan->fcs = L2CAP_FCS_NONE;
2074 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002075 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002076 break;
2077 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002079 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002080 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081
2082 return ptr - data;
2083}
2084
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002085static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002087 struct l2cap_conf_rsp *rsp = data;
2088 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002089 void *req = chan->conf_req;
2090 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002091 int type, hint, olen;
2092 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002093 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002094 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002095 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002097 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002098
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002099 while (len >= L2CAP_CONF_OPT_SIZE) {
2100 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002102 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002103 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002104
2105 switch (type) {
2106 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002107 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002108 break;
2109
2110 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002111 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002112 break;
2113
2114 case L2CAP_CONF_QOS:
2115 break;
2116
Marcel Holtmann6464f352007-10-20 13:39:51 +02002117 case L2CAP_CONF_RFC:
2118 if (olen == sizeof(rfc))
2119 memcpy(&rfc, (void *) val, olen);
2120 break;
2121
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002122 case L2CAP_CONF_FCS:
2123 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002124 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002125
2126 break;
2127
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002128 case L2CAP_CONF_EWS:
2129 if (!enable_hs)
2130 return -ECONNREFUSED;
2131
2132 set_bit(FLAG_EXT_CTRL, &chan->flags);
2133 set_bit(CONF_EWS_RECV, &chan->conf_state);
2134 chan->remote_tx_win = val;
2135 break;
2136
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002137 default:
2138 if (hint)
2139 break;
2140
2141 result = L2CAP_CONF_UNKNOWN;
2142 *((u8 *) ptr++) = type;
2143 break;
2144 }
2145 }
2146
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002147 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002148 goto done;
2149
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002150 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002151 case L2CAP_MODE_STREAMING:
2152 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002153 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002154 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002155 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002156 break;
2157 }
2158
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002159 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002160 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002161
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002162 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002163 }
2164
2165done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002166 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002167 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002168 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002169
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002170 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002171 return -ECONNREFUSED;
2172
2173 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2174 sizeof(rfc), (unsigned long) &rfc);
2175 }
2176
2177
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002178 if (result == L2CAP_CONF_SUCCESS) {
2179 /* Configure output options and let the other side know
2180 * which ones we don't like. */
2181
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002182 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2183 result = L2CAP_CONF_UNACCEPT;
2184 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002185 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002186 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002187 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002188 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002189
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002190 switch (rfc.mode) {
2191 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002192 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002193 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002194 break;
2195
2196 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002197 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2198 chan->remote_tx_win = rfc.txwin_size;
2199 else
2200 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2201
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002202 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002203
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002204 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2205 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002206
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002207 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002208
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002209 rfc.retrans_timeout =
2210 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2211 rfc.monitor_timeout =
2212 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002213
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002214 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002215
2216 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2217 sizeof(rfc), (unsigned long) &rfc);
2218
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002219 break;
2220
2221 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002222 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2223 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002224
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002225 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002226
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002227 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002228
2229 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2230 sizeof(rfc), (unsigned long) &rfc);
2231
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002232 break;
2233
2234 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002235 result = L2CAP_CONF_UNACCEPT;
2236
2237 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002238 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002239 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002240
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002241 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002242 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002243 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002244 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002245 rsp->result = cpu_to_le16(result);
2246 rsp->flags = cpu_to_le16(0x0000);
2247
2248 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249}
2250
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002251static 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 -03002252{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002253 struct l2cap_conf_req *req = data;
2254 void *ptr = req->data;
2255 int type, olen;
2256 unsigned long val;
2257 struct l2cap_conf_rfc rfc;
2258
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002259 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002260
2261 while (len >= L2CAP_CONF_OPT_SIZE) {
2262 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2263
2264 switch (type) {
2265 case L2CAP_CONF_MTU:
2266 if (val < L2CAP_DEFAULT_MIN_MTU) {
2267 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002268 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002269 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002270 chan->imtu = val;
2271 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002272 break;
2273
2274 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002275 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002276 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002277 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002278 break;
2279
2280 case L2CAP_CONF_RFC:
2281 if (olen == sizeof(rfc))
2282 memcpy(&rfc, (void *)val, olen);
2283
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002284 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002285 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002286 return -ECONNREFUSED;
2287
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002288 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002289
2290 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2291 sizeof(rfc), (unsigned long) &rfc);
2292 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002293
2294 case L2CAP_CONF_EWS:
2295 chan->tx_win = min_t(u16, val,
2296 L2CAP_DEFAULT_EXT_WINDOW);
2297 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS,
2298 2, chan->tx_win);
2299 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002300 }
2301 }
2302
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002303 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002304 return -ECONNREFUSED;
2305
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002306 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002307
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002308 if (*result == L2CAP_CONF_SUCCESS) {
2309 switch (rfc.mode) {
2310 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002311 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2312 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2313 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002314 break;
2315 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002316 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002317 }
2318 }
2319
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002320 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002321 req->flags = cpu_to_le16(0x0000);
2322
2323 return ptr - data;
2324}
2325
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002326static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327{
2328 struct l2cap_conf_rsp *rsp = data;
2329 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002331 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002333 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002334 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002335 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336
2337 return ptr - data;
2338}
2339
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002340void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002341{
2342 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002343 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002344 u8 buf[128];
2345
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002346 rsp.scid = cpu_to_le16(chan->dcid);
2347 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002348 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2349 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2350 l2cap_send_cmd(conn, chan->ident,
2351 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2352
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002353 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002354 return;
2355
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002356 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2357 l2cap_build_conf_req(chan, buf), buf);
2358 chan->num_conf_req++;
2359}
2360
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002361static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002362{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002363 int type, olen;
2364 unsigned long val;
2365 struct l2cap_conf_rfc rfc;
2366
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002367 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002368
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002369 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002370 return;
2371
2372 while (len >= L2CAP_CONF_OPT_SIZE) {
2373 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2374
2375 switch (type) {
2376 case L2CAP_CONF_RFC:
2377 if (olen == sizeof(rfc))
2378 memcpy(&rfc, (void *)val, olen);
2379 goto done;
2380 }
2381 }
2382
2383done:
2384 switch (rfc.mode) {
2385 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002386 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2387 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2388 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002389 break;
2390 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002391 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002392 }
2393}
2394
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002395static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2396{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002397 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002398
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002399 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002400 return 0;
2401
2402 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2403 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002404 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002405
2406 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002407 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002408
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002409 l2cap_conn_start(conn);
2410 }
2411
2412 return 0;
2413}
2414
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2416{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2418 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002419 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002420 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002421 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422
2423 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002424 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425
2426 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2427
2428 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002429 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2430 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431 result = L2CAP_CR_BAD_PSM;
2432 goto sendresp;
2433 }
2434
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002435 parent = pchan->sk;
2436
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002437 bh_lock_sock(parent);
2438
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002439 /* Check if the ACL is secure enough (if not SDP) */
2440 if (psm != cpu_to_le16(0x0001) &&
2441 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002442 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002443 result = L2CAP_CR_SEC_BLOCK;
2444 goto response;
2445 }
2446
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 result = L2CAP_CR_NO_MEM;
2448
2449 /* Check for backlog size */
2450 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002451 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 goto response;
2453 }
2454
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002455 chan = pchan->ops->new_connection(pchan->data);
2456 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 goto response;
2458
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002459 sk = chan->sk;
2460
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002461 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462
2463 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002464 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2465 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002467 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468 goto response;
2469 }
2470
2471 hci_conn_hold(conn->hcon);
2472
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473 bacpy(&bt_sk(sk)->src, conn->src);
2474 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002475 chan->psm = psm;
2476 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002478 bt_accept_enqueue(parent, sk);
2479
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002480 __l2cap_chan_add(conn, chan);
2481
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002482 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002484 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002486 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487
Marcel Holtmann984947d2009-02-06 23:35:19 +01002488 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002489 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002490 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002491 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002492 result = L2CAP_CR_PEND;
2493 status = L2CAP_CS_AUTHOR_PEND;
2494 parent->sk_data_ready(parent, 0);
2495 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002496 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002497 result = L2CAP_CR_SUCCESS;
2498 status = L2CAP_CS_NO_INFO;
2499 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002500 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002501 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002502 result = L2CAP_CR_PEND;
2503 status = L2CAP_CS_AUTHEN_PEND;
2504 }
2505 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002506 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002507 result = L2CAP_CR_PEND;
2508 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509 }
2510
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002511 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512
2513response:
2514 bh_unlock_sock(parent);
2515
2516sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002517 rsp.scid = cpu_to_le16(scid);
2518 rsp.dcid = cpu_to_le16(dcid);
2519 rsp.result = cpu_to_le16(result);
2520 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002522
2523 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2524 struct l2cap_info_req info;
2525 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2526
2527 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2528 conn->info_ident = l2cap_get_ident(conn);
2529
2530 mod_timer(&conn->info_timer, jiffies +
2531 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2532
2533 l2cap_send_cmd(conn, conn->info_ident,
2534 L2CAP_INFO_REQ, sizeof(info), &info);
2535 }
2536
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002537 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002538 result == L2CAP_CR_SUCCESS) {
2539 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002540 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002541 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002542 l2cap_build_conf_req(chan, buf), buf);
2543 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002544 }
2545
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546 return 0;
2547}
2548
2549static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2550{
2551 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2552 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002553 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554 struct sock *sk;
2555 u8 req[128];
2556
2557 scid = __le16_to_cpu(rsp->scid);
2558 dcid = __le16_to_cpu(rsp->dcid);
2559 result = __le16_to_cpu(rsp->result);
2560 status = __le16_to_cpu(rsp->status);
2561
2562 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2563
2564 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002565 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002566 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002567 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002569 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002570 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002571 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572 }
2573
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002574 sk = chan->sk;
2575
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576 switch (result) {
2577 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002578 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002579 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002580 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002581 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002582
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002583 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002584 break;
2585
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002587 l2cap_build_conf_req(chan, req), req);
2588 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589 break;
2590
2591 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002592 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593 break;
2594
2595 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002596 /* don't delete l2cap channel if sk is owned by user */
2597 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002598 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002599 __clear_chan_timer(chan);
2600 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002601 break;
2602 }
2603
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002604 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605 break;
2606 }
2607
2608 bh_unlock_sock(sk);
2609 return 0;
2610}
2611
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002612static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002613{
2614 /* FCS is enabled only in ERTM or streaming mode, if one or both
2615 * sides request it.
2616 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002617 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002618 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002619 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002620 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002621}
2622
Al Viro88219a02007-07-29 00:17:25 -07002623static 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 -07002624{
2625 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2626 u16 dcid, flags;
2627 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002628 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002630 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631
2632 dcid = __le16_to_cpu(req->dcid);
2633 flags = __le16_to_cpu(req->flags);
2634
2635 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2636
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002637 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002638 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639 return -ENOENT;
2640
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002641 sk = chan->sk;
2642
David S. Miller033b1142011-07-21 13:38:42 -07002643 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002644 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002645
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002646 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2647 rej.scid = cpu_to_le16(chan->scid);
2648 rej.dcid = cpu_to_le16(chan->dcid);
2649
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002650 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2651 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002652 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002653 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002654
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002655 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002656 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002657 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002658 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002659 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002660 L2CAP_CONF_REJECT, flags), rsp);
2661 goto unlock;
2662 }
2663
2664 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002665 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2666 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667
2668 if (flags & 0x0001) {
2669 /* Incomplete config. Send empty response. */
2670 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002671 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002672 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673 goto unlock;
2674 }
2675
2676 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002677 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002678 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002679 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002681 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002683 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002684 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002685
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002686 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002687 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002688
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002689 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002690 goto unlock;
2691
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002692 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002693 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002694
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002695 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002696
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002697 chan->next_tx_seq = 0;
2698 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002699 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002700 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002701 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002702
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002704 goto unlock;
2705 }
2706
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002707 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002708 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002710 l2cap_build_conf_req(chan, buf), buf);
2711 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712 }
2713
2714unlock:
2715 bh_unlock_sock(sk);
2716 return 0;
2717}
2718
2719static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2720{
2721 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2722 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002723 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002725 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726
2727 scid = __le16_to_cpu(rsp->scid);
2728 flags = __le16_to_cpu(rsp->flags);
2729 result = __le16_to_cpu(rsp->result);
2730
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002731 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2732 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002734 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002735 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736 return 0;
2737
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002738 sk = chan->sk;
2739
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 switch (result) {
2741 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002742 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743 break;
2744
2745 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002746 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002747 char req[64];
2748
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002749 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002750 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002751 goto done;
2752 }
2753
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002754 /* throw out any old stored conf requests */
2755 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002756 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2757 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002758 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002759 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002760 goto done;
2761 }
2762
2763 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2764 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002765 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002766 if (result != L2CAP_CONF_SUCCESS)
2767 goto done;
2768 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 }
2770
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002771 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002772 sk->sk_err = ECONNRESET;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002773 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002774 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 goto done;
2776 }
2777
2778 if (flags & 0x01)
2779 goto done;
2780
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002781 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002782
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002783 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002784 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002785
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002786 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002787 chan->next_tx_seq = 0;
2788 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002789 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002790 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002791 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002792
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793 l2cap_chan_ready(sk);
2794 }
2795
2796done:
2797 bh_unlock_sock(sk);
2798 return 0;
2799}
2800
2801static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2802{
2803 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2804 struct l2cap_disconn_rsp rsp;
2805 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002806 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807 struct sock *sk;
2808
2809 scid = __le16_to_cpu(req->scid);
2810 dcid = __le16_to_cpu(req->dcid);
2811
2812 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2813
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002814 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002815 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816 return 0;
2817
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002818 sk = chan->sk;
2819
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002820 rsp.dcid = cpu_to_le16(chan->scid);
2821 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2823
2824 sk->sk_shutdown = SHUTDOWN_MASK;
2825
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002826 /* don't delete l2cap channel if sk is owned by user */
2827 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002828 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002829 __clear_chan_timer(chan);
2830 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002831 bh_unlock_sock(sk);
2832 return 0;
2833 }
2834
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002835 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836 bh_unlock_sock(sk);
2837
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002838 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002839 return 0;
2840}
2841
2842static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2843{
2844 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2845 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002846 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847 struct sock *sk;
2848
2849 scid = __le16_to_cpu(rsp->scid);
2850 dcid = __le16_to_cpu(rsp->dcid);
2851
2852 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2853
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002854 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002855 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856 return 0;
2857
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002858 sk = chan->sk;
2859
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002860 /* don't delete l2cap channel if sk is owned by user */
2861 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03002862 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002863 __clear_chan_timer(chan);
2864 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002865 bh_unlock_sock(sk);
2866 return 0;
2867 }
2868
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002869 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870 bh_unlock_sock(sk);
2871
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002872 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002873 return 0;
2874}
2875
2876static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2877{
2878 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879 u16 type;
2880
2881 type = __le16_to_cpu(req->type);
2882
2883 BT_DBG("type 0x%4.4x", type);
2884
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002885 if (type == L2CAP_IT_FEAT_MASK) {
2886 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002887 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002888 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2889 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2890 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002891 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002892 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2893 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03002894 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002895 feat_mask |= L2CAP_FEAT_EXT_FLOW
2896 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03002897
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002898 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002899 l2cap_send_cmd(conn, cmd->ident,
2900 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002901 } else if (type == L2CAP_IT_FIXED_CHAN) {
2902 u8 buf[12];
2903 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2904 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2905 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2906 memcpy(buf + 4, l2cap_fixed_chan, 8);
2907 l2cap_send_cmd(conn, cmd->ident,
2908 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002909 } else {
2910 struct l2cap_info_rsp rsp;
2911 rsp.type = cpu_to_le16(type);
2912 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2913 l2cap_send_cmd(conn, cmd->ident,
2914 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2915 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916
2917 return 0;
2918}
2919
2920static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2921{
2922 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2923 u16 type, result;
2924
2925 type = __le16_to_cpu(rsp->type);
2926 result = __le16_to_cpu(rsp->result);
2927
2928 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2929
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002930 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2931 if (cmd->ident != conn->info_ident ||
2932 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2933 return 0;
2934
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002935 del_timer(&conn->info_timer);
2936
Ville Tervoadb08ed2010-08-04 09:43:33 +03002937 if (result != L2CAP_IR_SUCCESS) {
2938 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2939 conn->info_ident = 0;
2940
2941 l2cap_conn_start(conn);
2942
2943 return 0;
2944 }
2945
Marcel Holtmann984947d2009-02-06 23:35:19 +01002946 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002947 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002948
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002949 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002950 struct l2cap_info_req req;
2951 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2952
2953 conn->info_ident = l2cap_get_ident(conn);
2954
2955 l2cap_send_cmd(conn, conn->info_ident,
2956 L2CAP_INFO_REQ, sizeof(req), &req);
2957 } else {
2958 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2959 conn->info_ident = 0;
2960
2961 l2cap_conn_start(conn);
2962 }
2963 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002964 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002965 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002966
2967 l2cap_conn_start(conn);
2968 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002969
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970 return 0;
2971}
2972
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002973static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002974 u16 to_multiplier)
2975{
2976 u16 max_latency;
2977
2978 if (min > max || min < 6 || max > 3200)
2979 return -EINVAL;
2980
2981 if (to_multiplier < 10 || to_multiplier > 3200)
2982 return -EINVAL;
2983
2984 if (max >= to_multiplier * 8)
2985 return -EINVAL;
2986
2987 max_latency = (to_multiplier * 8 / max) - 1;
2988 if (latency > 499 || latency > max_latency)
2989 return -EINVAL;
2990
2991 return 0;
2992}
2993
2994static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2995 struct l2cap_cmd_hdr *cmd, u8 *data)
2996{
2997 struct hci_conn *hcon = conn->hcon;
2998 struct l2cap_conn_param_update_req *req;
2999 struct l2cap_conn_param_update_rsp rsp;
3000 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003001 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02003002
3003 if (!(hcon->link_mode & HCI_LM_MASTER))
3004 return -EINVAL;
3005
3006 cmd_len = __le16_to_cpu(cmd->len);
3007 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3008 return -EPROTO;
3009
3010 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03003011 min = __le16_to_cpu(req->min);
3012 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02003013 latency = __le16_to_cpu(req->latency);
3014 to_multiplier = __le16_to_cpu(req->to_multiplier);
3015
3016 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3017 min, max, latency, to_multiplier);
3018
3019 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003020
3021 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
3022 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02003023 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3024 else
3025 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3026
3027 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3028 sizeof(rsp), &rsp);
3029
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02003030 if (!err)
3031 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
3032
Claudio Takahaside731152011-02-11 19:28:55 -02003033 return 0;
3034}
3035
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003036static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
3037 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
3038{
3039 int err = 0;
3040
3041 switch (cmd->code) {
3042 case L2CAP_COMMAND_REJ:
3043 l2cap_command_rej(conn, cmd, data);
3044 break;
3045
3046 case L2CAP_CONN_REQ:
3047 err = l2cap_connect_req(conn, cmd, data);
3048 break;
3049
3050 case L2CAP_CONN_RSP:
3051 err = l2cap_connect_rsp(conn, cmd, data);
3052 break;
3053
3054 case L2CAP_CONF_REQ:
3055 err = l2cap_config_req(conn, cmd, cmd_len, data);
3056 break;
3057
3058 case L2CAP_CONF_RSP:
3059 err = l2cap_config_rsp(conn, cmd, data);
3060 break;
3061
3062 case L2CAP_DISCONN_REQ:
3063 err = l2cap_disconnect_req(conn, cmd, data);
3064 break;
3065
3066 case L2CAP_DISCONN_RSP:
3067 err = l2cap_disconnect_rsp(conn, cmd, data);
3068 break;
3069
3070 case L2CAP_ECHO_REQ:
3071 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3072 break;
3073
3074 case L2CAP_ECHO_RSP:
3075 break;
3076
3077 case L2CAP_INFO_REQ:
3078 err = l2cap_information_req(conn, cmd, data);
3079 break;
3080
3081 case L2CAP_INFO_RSP:
3082 err = l2cap_information_rsp(conn, cmd, data);
3083 break;
3084
3085 default:
3086 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3087 err = -EINVAL;
3088 break;
3089 }
3090
3091 return err;
3092}
3093
3094static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3095 struct l2cap_cmd_hdr *cmd, u8 *data)
3096{
3097 switch (cmd->code) {
3098 case L2CAP_COMMAND_REJ:
3099 return 0;
3100
3101 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003102 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003103
3104 case L2CAP_CONN_PARAM_UPDATE_RSP:
3105 return 0;
3106
3107 default:
3108 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3109 return -EINVAL;
3110 }
3111}
3112
3113static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3114 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003115{
3116 u8 *data = skb->data;
3117 int len = skb->len;
3118 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003119 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003120
3121 l2cap_raw_recv(conn, skb);
3122
3123 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003124 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3126 data += L2CAP_CMD_HDR_SIZE;
3127 len -= L2CAP_CMD_HDR_SIZE;
3128
Al Viro88219a02007-07-29 00:17:25 -07003129 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130
Al Viro88219a02007-07-29 00:17:25 -07003131 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 -07003132
Al Viro88219a02007-07-29 00:17:25 -07003133 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134 BT_DBG("corrupted command");
3135 break;
3136 }
3137
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003138 if (conn->hcon->type == LE_LINK)
3139 err = l2cap_le_sig_cmd(conn, &cmd, data);
3140 else
3141 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142
3143 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003144 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003145
3146 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147
3148 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003149 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3151 }
3152
Al Viro88219a02007-07-29 00:17:25 -07003153 data += cmd_len;
3154 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155 }
3156
3157 kfree_skb(skb);
3158}
3159
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003160static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003161{
3162 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003163 int hdr_size;
3164
3165 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3166 hdr_size = L2CAP_EXT_HDR_SIZE;
3167 else
3168 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003169
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003170 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003171 skb_trim(skb, skb->len - 2);
3172 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3173 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3174
3175 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003176 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003177 }
3178 return 0;
3179}
3180
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003181static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003182{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003183 u16 control = 0;
3184
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003185 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003186
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003187 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003188
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003189 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003190 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003191 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003192 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003193 }
3194
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003195 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003196 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003197
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003198 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003199
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003200 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003201 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003202 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003203 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003204 }
3205}
3206
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003207static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003208{
3209 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003210 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003211
3212 bt_cb(skb)->tx_seq = tx_seq;
3213 bt_cb(skb)->sar = sar;
3214
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003215 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003216 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003217 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003218 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003219 }
3220
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003221 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003222 if (tx_seq_offset < 0)
3223 tx_seq_offset += 64;
3224
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003225 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003226 if (bt_cb(next_skb)->tx_seq == tx_seq)
3227 return -EINVAL;
3228
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003229 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003230 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003231 if (next_tx_seq_offset < 0)
3232 next_tx_seq_offset += 64;
3233
3234 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003235 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003236 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003237 }
3238
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003239 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003240 break;
3241
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003242 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003243
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003244 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003245
3246 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003247}
3248
Mat Martineau84084a32011-07-22 14:54:00 -07003249static void append_skb_frag(struct sk_buff *skb,
3250 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003251{
Mat Martineau84084a32011-07-22 14:54:00 -07003252 /* skb->len reflects data in skb as well as all fragments
3253 * skb->data_len reflects only data in fragments
3254 */
3255 if (!skb_has_frag_list(skb))
3256 skb_shinfo(skb)->frag_list = new_frag;
3257
3258 new_frag->next = NULL;
3259
3260 (*last_frag)->next = new_frag;
3261 *last_frag = new_frag;
3262
3263 skb->len += new_frag->len;
3264 skb->data_len += new_frag->len;
3265 skb->truesize += new_frag->truesize;
3266}
3267
3268static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
3269{
3270 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003271
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003272 switch (__get_ctrl_sar(chan, control)) {
3273 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003274 if (chan->sdu)
3275 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003276
Mat Martineau84084a32011-07-22 14:54:00 -07003277 err = chan->ops->recv(chan->data, skb);
3278 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003279
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003280 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003281 if (chan->sdu)
3282 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003283
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003284 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003285 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003286
Mat Martineau84084a32011-07-22 14:54:00 -07003287 if (chan->sdu_len > chan->imtu) {
3288 err = -EMSGSIZE;
3289 break;
3290 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003291
Mat Martineau84084a32011-07-22 14:54:00 -07003292 if (skb->len >= chan->sdu_len)
3293 break;
3294
3295 chan->sdu = skb;
3296 chan->sdu_last_frag = skb;
3297
3298 skb = NULL;
3299 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003300 break;
3301
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003302 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003303 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003304 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003305
Mat Martineau84084a32011-07-22 14:54:00 -07003306 append_skb_frag(chan->sdu, skb,
3307 &chan->sdu_last_frag);
3308 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003309
Mat Martineau84084a32011-07-22 14:54:00 -07003310 if (chan->sdu->len >= chan->sdu_len)
3311 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003312
Mat Martineau84084a32011-07-22 14:54:00 -07003313 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003314 break;
3315
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003316 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003317 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003318 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003319
Mat Martineau84084a32011-07-22 14:54:00 -07003320 append_skb_frag(chan->sdu, skb,
3321 &chan->sdu_last_frag);
3322 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003323
Mat Martineau84084a32011-07-22 14:54:00 -07003324 if (chan->sdu->len != chan->sdu_len)
3325 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003326
Mat Martineau84084a32011-07-22 14:54:00 -07003327 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003328
Mat Martineau84084a32011-07-22 14:54:00 -07003329 if (!err) {
3330 /* Reassembly complete */
3331 chan->sdu = NULL;
3332 chan->sdu_last_frag = NULL;
3333 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003334 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003335 break;
3336 }
3337
Mat Martineau84084a32011-07-22 14:54:00 -07003338 if (err) {
3339 kfree_skb(skb);
3340 kfree_skb(chan->sdu);
3341 chan->sdu = NULL;
3342 chan->sdu_last_frag = NULL;
3343 chan->sdu_len = 0;
3344 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003345
Mat Martineau84084a32011-07-22 14:54:00 -07003346 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003347}
3348
Mat Martineau26f880d2011-07-07 09:39:01 -07003349static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003350{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003351 u16 control;
3352
Mat Martineau26f880d2011-07-07 09:39:01 -07003353 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003354
Mat Martineau26f880d2011-07-07 09:39:01 -07003355 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3356
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003357 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003358 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Mat Martineau26f880d2011-07-07 09:39:01 -07003359 l2cap_send_sframe(chan, control);
3360
3361 set_bit(CONN_RNR_SENT, &chan->conn_state);
3362
3363 __clear_ack_timer(chan);
3364}
3365
3366static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3367{
3368 u16 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003369
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003370 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003371 goto done;
3372
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003373 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003374 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003375 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003376 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003377 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003378
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003379 __clear_retrans_timer(chan);
3380 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003381
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003382 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003383
3384done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003385 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3386 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003387
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003388 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003389}
3390
Mat Martineaue3281402011-07-07 09:39:02 -07003391void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003392{
Mat Martineaue3281402011-07-07 09:39:02 -07003393 if (chan->mode == L2CAP_MODE_ERTM) {
3394 if (busy)
3395 l2cap_ertm_enter_local_busy(chan);
3396 else
3397 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003398 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003399}
3400
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003401static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003402{
3403 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003404 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003405
Mat Martineaue3281402011-07-07 09:39:02 -07003406 while ((skb = skb_peek(&chan->srej_q)) &&
3407 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3408 int err;
3409
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003410 if (bt_cb(skb)->tx_seq != tx_seq)
3411 break;
3412
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003413 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003414 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003415 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003416
3417 if (err < 0) {
3418 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3419 break;
3420 }
3421
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003422 chan->buffer_seq_srej =
3423 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003424 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003425 }
3426}
3427
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003428static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003429{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003430 struct srej_list *l, *tmp;
3431 u16 control;
3432
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003433 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003434 if (l->tx_seq == tx_seq) {
3435 list_del(&l->list);
3436 kfree(l);
3437 return;
3438 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003439 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003440 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003441 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003442 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003443 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003444 }
3445}
3446
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003447static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003448{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003449 struct srej_list *new;
3450 u16 control;
3451
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003452 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003453 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003454 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003455 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003456
3457 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003458 new->tx_seq = chan->expected_tx_seq;
3459 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003460 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003461 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003462 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003463}
3464
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003465static 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 -03003466{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003467 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003468 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003469 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003470 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003471 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003472 int err = 0;
3473
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003474 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3475 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003476
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003477 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003478 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003479 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003480 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003481 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003482 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003483 }
3484
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003485 chan->expected_ack_seq = req_seq;
3486 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003487
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003488 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003489 if (tx_seq_offset < 0)
3490 tx_seq_offset += 64;
3491
3492 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003493 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003494 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003495 goto drop;
3496 }
3497
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003498 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003499 goto drop;
3500
Mat Martineau02f1b642011-06-29 14:35:19 -07003501 if (tx_seq == chan->expected_tx_seq)
3502 goto expected;
3503
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003504 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003505 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003506
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003507 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003508 struct srej_list, list);
3509 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003510 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003511 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003512
3513 list_del(&first->list);
3514 kfree(first);
3515
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003516 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003517 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003518 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003519 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003520 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003521 }
3522 } else {
3523 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003524
3525 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003526 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003527 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003528
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003529 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003530 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003531 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003532 return 0;
3533 }
3534 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003535 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003536 }
3537 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003538 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003539 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003540 if (expected_tx_seq_offset < 0)
3541 expected_tx_seq_offset += 64;
3542
3543 /* duplicated tx_seq */
3544 if (tx_seq_offset < expected_tx_seq_offset)
3545 goto drop;
3546
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003547 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003548
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003549 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003550
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003551 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003552 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003553
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003554 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003555 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003556
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003557 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003558
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003559 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003560
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003561 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003562 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003563 return 0;
3564
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003565expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003566 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003567
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003568 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003569 bt_cb(skb)->tx_seq = tx_seq;
3570 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003571 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003572 return 0;
3573 }
3574
Mat Martineau84084a32011-07-22 14:54:00 -07003575 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Mat Martineaufadd1922011-07-07 09:39:03 -07003576 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Mat Martineaue3281402011-07-07 09:39:02 -07003577 if (err < 0) {
3578 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3579 return err;
3580 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003581
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003582 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003583 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003584 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003585 }
3586
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003587 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003588
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003589 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3590 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003591 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003592
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003593 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003594
3595drop:
3596 kfree_skb(skb);
3597 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003598}
3599
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003600static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003601{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003602 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan,
3603 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003604
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003605 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003606 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003607
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003608 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003609 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3610 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3611 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003612 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003613 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003614
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003615 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003616 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003617 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003618 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003619 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003620
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003621 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003622 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003623
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003624 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003625 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003626
3627 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003628 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003629 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003630 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003631
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003632 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3633 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003634 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003635 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003636 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003637 }
3638}
3639
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003640static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003641{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003642 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003643
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003644 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003645
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003646 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003647
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003648 chan->expected_ack_seq = tx_seq;
3649 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003650
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003651 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003652 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003653 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003654 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003655 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003656
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003657 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3658 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003659 }
3660}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003661static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003662{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003663 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003664
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003665 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003666
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003667 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003668
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003669 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003670 chan->expected_ack_seq = tx_seq;
3671 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003672
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003673 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003674 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003675
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003676 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003677
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003678 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003679 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003680 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003681 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003682 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003683 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003684 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003685 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003686 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003687 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003688 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003689 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003690 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003691 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003692 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003693 }
3694 }
3695}
3696
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003697static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003698{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003699 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003700
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003701 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003702
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003703 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003704 chan->expected_ack_seq = tx_seq;
3705 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003706
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003707 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003708 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003709
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003710 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003711 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003712 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003713 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003714 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003715 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003716
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003717 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003718 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003719 } else {
3720 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
3721 l2cap_send_sframe(chan, rx_control);
3722 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003723}
3724
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003725static 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 -03003726{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003727 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003728
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003729 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003730 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003731 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003732 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003733 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003734 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003735 }
3736
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003737 switch (__get_ctrl_super(chan, rx_control)) {
3738 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003739 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003740 break;
3741
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003742 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003743 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003744 break;
3745
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003746 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003747 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003748 break;
3749
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003750 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003751 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003752 break;
3753 }
3754
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003755 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003756 return 0;
3757}
3758
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003759static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3760{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003761 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003762 u16 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003763 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003764 int len, next_tx_seq_offset, req_seq_offset;
3765
3766 control = get_unaligned_le16(skb->data);
3767 skb_pull(skb, 2);
3768 len = skb->len;
3769
3770 /*
3771 * We can just drop the corrupted I-frame here.
3772 * Receiver will miss it and start proper recovery
3773 * procedures and ask retransmission.
3774 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003775 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003776 goto drop;
3777
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03003778 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003779 len -= 2;
3780
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003781 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003782 len -= 2;
3783
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003784 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003785 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003786 goto drop;
3787 }
3788
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003789 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003790 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003791 if (req_seq_offset < 0)
3792 req_seq_offset += 64;
3793
3794 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003795 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003796 if (next_tx_seq_offset < 0)
3797 next_tx_seq_offset += 64;
3798
3799 /* check for invalid req-seq */
3800 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003801 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003802 goto drop;
3803 }
3804
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03003805 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003806 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003807 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003808 goto drop;
3809 }
3810
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003811 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003812 } else {
3813 if (len != 0) {
3814 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003815 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003816 goto drop;
3817 }
3818
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003819 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003820 }
3821
3822 return 0;
3823
3824drop:
3825 kfree_skb(skb);
3826 return 0;
3827}
3828
Linus Torvalds1da177e2005-04-16 15:20:36 -07003829static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3830{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003831 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003832 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003833 u16 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003834 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003835 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003837 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003838 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839 BT_DBG("unknown cid 0x%4.4x", cid);
3840 goto drop;
3841 }
3842
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003843 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003844
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003845 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03003847 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848 goto drop;
3849
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003850 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003851 case L2CAP_MODE_BASIC:
3852 /* If socket recv buffers overflows we drop data here
3853 * which is *bad* because L2CAP has to be reliable.
3854 * But we don't have any other choice. L2CAP doesn't
3855 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003857 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003858 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003860 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003861 goto done;
3862 break;
3863
3864 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003865 if (!sock_owned_by_user(sk)) {
3866 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003867 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003868 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003869 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003870 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003871
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003872 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003873
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003874 case L2CAP_MODE_STREAMING:
3875 control = get_unaligned_le16(skb->data);
3876 skb_pull(skb, 2);
3877 len = skb->len;
3878
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003879 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003880 goto drop;
3881
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003882 if (__is_sar_start(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003883 len -= 2;
3884
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003885 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003886 len -= 2;
3887
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03003888 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003889 goto drop;
3890
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003891 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003892
Mat Martineau84084a32011-07-22 14:54:00 -07003893 if (chan->expected_tx_seq != tx_seq) {
3894 /* Frame(s) missing - must discard partial SDU */
3895 kfree_skb(chan->sdu);
3896 chan->sdu = NULL;
3897 chan->sdu_last_frag = NULL;
3898 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003899
Mat Martineau84084a32011-07-22 14:54:00 -07003900 /* TODO: Notify userland of missing data */
3901 }
3902
3903 chan->expected_tx_seq = (tx_seq + 1) % 64;
3904
3905 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
3906 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003907
3908 goto done;
3909
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003910 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003911 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003912 break;
3913 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914
3915drop:
3916 kfree_skb(skb);
3917
3918done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003919 if (sk)
3920 bh_unlock_sock(sk);
3921
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922 return 0;
3923}
3924
Al Viro8e036fc2007-07-29 00:16:36 -07003925static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003927 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003928 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003930 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3931 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932 goto drop;
3933
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003934 sk = chan->sk;
3935
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003936 bh_lock_sock(sk);
3937
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938 BT_DBG("sk %p, len %d", sk, skb->len);
3939
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03003940 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941 goto drop;
3942
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003943 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944 goto drop;
3945
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003946 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003947 goto done;
3948
3949drop:
3950 kfree_skb(skb);
3951
3952done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003953 if (sk)
3954 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003955 return 0;
3956}
3957
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003958static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3959{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003960 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003961 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003962
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003963 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3964 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003965 goto drop;
3966
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003967 sk = chan->sk;
3968
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003969 bh_lock_sock(sk);
3970
3971 BT_DBG("sk %p, len %d", sk, skb->len);
3972
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03003973 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003974 goto drop;
3975
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003976 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003977 goto drop;
3978
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003979 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003980 goto done;
3981
3982drop:
3983 kfree_skb(skb);
3984
3985done:
3986 if (sk)
3987 bh_unlock_sock(sk);
3988 return 0;
3989}
3990
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3992{
3993 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003994 u16 cid, len;
3995 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996
3997 skb_pull(skb, L2CAP_HDR_SIZE);
3998 cid = __le16_to_cpu(lh->cid);
3999 len = __le16_to_cpu(lh->len);
4000
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004001 if (len != skb->len) {
4002 kfree_skb(skb);
4003 return;
4004 }
4005
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4007
4008 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004009 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004010 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011 l2cap_sig_channel(conn, skb);
4012 break;
4013
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004014 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004015 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016 skb_pull(skb, 2);
4017 l2cap_conless_channel(conn, psm, skb);
4018 break;
4019
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004020 case L2CAP_CID_LE_DATA:
4021 l2cap_att_channel(conn, cid, skb);
4022 break;
4023
Anderson Brigliab501d6a2011-06-07 18:46:31 -03004024 case L2CAP_CID_SMP:
4025 if (smp_sig_channel(conn, skb))
4026 l2cap_conn_del(conn->hcon, EACCES);
4027 break;
4028
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029 default:
4030 l2cap_data_channel(conn, cid, skb);
4031 break;
4032 }
4033}
4034
4035/* ---- L2CAP interface with lower layer (HCI) ---- */
4036
4037static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4038{
4039 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004040 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041
4042 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004043 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044
4045 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4046
4047 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004048 read_lock(&chan_list_lock);
4049 list_for_each_entry(c, &chan_list, global_l) {
4050 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004051
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004052 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053 continue;
4054
4055 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004056 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004057 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004058 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004059 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004060 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4061 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004062 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004063 lm2 |= HCI_LM_MASTER;
4064 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004066 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067
4068 return exact ? lm1 : lm2;
4069}
4070
4071static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4072{
Marcel Holtmann01394182006-07-03 10:02:46 +02004073 struct l2cap_conn *conn;
4074
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4076
Ville Tervoacd7d372011-02-10 22:38:49 -03004077 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004078 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079
4080 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081 conn = l2cap_conn_add(hcon, status);
4082 if (conn)
4083 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004084 } else
Joe Perchese1750722011-06-29 18:18:29 -07004085 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086
4087 return 0;
4088}
4089
Marcel Holtmann2950f212009-02-12 14:02:50 +01004090static int l2cap_disconn_ind(struct hci_conn *hcon)
4091{
4092 struct l2cap_conn *conn = hcon->l2cap_data;
4093
4094 BT_DBG("hcon %p", hcon);
4095
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03004096 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004097 return 0x13;
4098
4099 return conn->disc_reason;
4100}
4101
4102static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103{
4104 BT_DBG("hcon %p reason %d", hcon, reason);
4105
Ville Tervoacd7d372011-02-10 22:38:49 -03004106 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004107 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004108
Joe Perchese1750722011-06-29 18:18:29 -07004109 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004110
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111 return 0;
4112}
4113
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004114static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004115{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004116 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004117 return;
4118
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004119 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004120 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004121 __clear_chan_timer(chan);
4122 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004123 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004124 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004125 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004126 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004127 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004128 }
4129}
4130
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004131static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004133 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004134 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135
Marcel Holtmann01394182006-07-03 10:02:46 +02004136 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004138
Linus Torvalds1da177e2005-04-16 15:20:36 -07004139 BT_DBG("conn %p", conn);
4140
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004141 if (hcon->type == LE_LINK) {
4142 smp_distribute_keys(conn, 0);
4143 del_timer(&conn->security_timer);
4144 }
4145
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004146 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004148 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004149 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004150
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151 bh_lock_sock(sk);
4152
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004153 BT_DBG("chan->scid %d", chan->scid);
4154
4155 if (chan->scid == L2CAP_CID_LE_DATA) {
4156 if (!status && encrypt) {
4157 chan->sec_level = hcon->sec_level;
4158 l2cap_chan_ready(sk);
4159 }
4160
4161 bh_unlock_sock(sk);
4162 continue;
4163 }
4164
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004165 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004166 bh_unlock_sock(sk);
4167 continue;
4168 }
4169
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004170 if (!status && (chan->state == BT_CONNECTED ||
4171 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004172 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004173 bh_unlock_sock(sk);
4174 continue;
4175 }
4176
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004177 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004178 if (!status) {
4179 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004180 req.scid = cpu_to_le16(chan->scid);
4181 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004182
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004183 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004184 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004185
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004186 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004187 L2CAP_CONN_REQ, sizeof(req), &req);
4188 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004189 __clear_chan_timer(chan);
4190 __set_chan_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004191 }
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004192 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004193 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004194 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004195
4196 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004197 if (bt_sk(sk)->defer_setup) {
4198 struct sock *parent = bt_sk(sk)->parent;
4199 res = L2CAP_CR_PEND;
4200 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004201 if (parent)
4202 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004203 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004204 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004205 res = L2CAP_CR_SUCCESS;
4206 stat = L2CAP_CS_NO_INFO;
4207 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004208 } else {
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004209 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004210 __set_chan_timer(chan, HZ / 10);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004211 res = L2CAP_CR_SEC_BLOCK;
4212 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004213 }
4214
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004215 rsp.scid = cpu_to_le16(chan->dcid);
4216 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004217 rsp.result = cpu_to_le16(res);
4218 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004219 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4220 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221 }
4222
Linus Torvalds1da177e2005-04-16 15:20:36 -07004223 bh_unlock_sock(sk);
4224 }
4225
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004226 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004227
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228 return 0;
4229}
4230
4231static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4232{
4233 struct l2cap_conn *conn = hcon->l2cap_data;
4234
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004235 if (!conn)
4236 conn = l2cap_conn_add(hcon, 0);
4237
4238 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004239 goto drop;
4240
4241 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4242
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004243 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004245 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004246 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247 int len;
4248
4249 if (conn->rx_len) {
4250 BT_ERR("Unexpected start frame (len %d)", skb->len);
4251 kfree_skb(conn->rx_skb);
4252 conn->rx_skb = NULL;
4253 conn->rx_len = 0;
4254 l2cap_conn_unreliable(conn, ECOMM);
4255 }
4256
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004257 /* Start fragment always begin with Basic L2CAP header */
4258 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004259 BT_ERR("Frame is too short (len %d)", skb->len);
4260 l2cap_conn_unreliable(conn, ECOMM);
4261 goto drop;
4262 }
4263
4264 hdr = (struct l2cap_hdr *) skb->data;
4265 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004266 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267
4268 if (len == skb->len) {
4269 /* Complete frame received */
4270 l2cap_recv_frame(conn, skb);
4271 return 0;
4272 }
4273
4274 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4275
4276 if (skb->len > len) {
4277 BT_ERR("Frame is too long (len %d, expected len %d)",
4278 skb->len, len);
4279 l2cap_conn_unreliable(conn, ECOMM);
4280 goto drop;
4281 }
4282
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004283 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004284
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004285 if (chan && chan->sk) {
4286 struct sock *sk = chan->sk;
4287
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004288 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004289 BT_ERR("Frame exceeding recv MTU (len %d, "
4290 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004291 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004292 bh_unlock_sock(sk);
4293 l2cap_conn_unreliable(conn, ECOMM);
4294 goto drop;
4295 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004296 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004297 }
4298
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004300 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4301 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004302 goto drop;
4303
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004304 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004305 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306 conn->rx_len = len - skb->len;
4307 } else {
4308 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4309
4310 if (!conn->rx_len) {
4311 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4312 l2cap_conn_unreliable(conn, ECOMM);
4313 goto drop;
4314 }
4315
4316 if (skb->len > conn->rx_len) {
4317 BT_ERR("Fragment is too long (len %d, expected %d)",
4318 skb->len, conn->rx_len);
4319 kfree_skb(conn->rx_skb);
4320 conn->rx_skb = NULL;
4321 conn->rx_len = 0;
4322 l2cap_conn_unreliable(conn, ECOMM);
4323 goto drop;
4324 }
4325
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004326 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004327 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004328 conn->rx_len -= skb->len;
4329
4330 if (!conn->rx_len) {
4331 /* Complete frame received */
4332 l2cap_recv_frame(conn, conn->rx_skb);
4333 conn->rx_skb = NULL;
4334 }
4335 }
4336
4337drop:
4338 kfree_skb(skb);
4339 return 0;
4340}
4341
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004342static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004344 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004346 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004348 list_for_each_entry(c, &chan_list, global_l) {
4349 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004351 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 +01004352 batostr(&bt_sk(sk)->src),
4353 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc500e2011-06-03 00:19:47 -03004354 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004355 c->scid, c->dcid, c->imtu, c->omtu,
4356 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004357}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004358
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004359 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004360
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004361 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004362}
4363
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004364static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4365{
4366 return single_open(file, l2cap_debugfs_show, inode->i_private);
4367}
4368
4369static const struct file_operations l2cap_debugfs_fops = {
4370 .open = l2cap_debugfs_open,
4371 .read = seq_read,
4372 .llseek = seq_lseek,
4373 .release = single_release,
4374};
4375
4376static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377
Linus Torvalds1da177e2005-04-16 15:20:36 -07004378static struct hci_proto l2cap_hci_proto = {
4379 .name = "L2CAP",
4380 .id = HCI_PROTO_L2CAP,
4381 .connect_ind = l2cap_connect_ind,
4382 .connect_cfm = l2cap_connect_cfm,
4383 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004384 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004385 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004386 .recv_acldata = l2cap_recv_acldata
4387};
4388
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004389int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004390{
4391 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004392
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004393 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394 if (err < 0)
4395 return err;
4396
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397 err = hci_register_proto(&l2cap_hci_proto);
4398 if (err < 0) {
4399 BT_ERR("L2CAP protocol registration failed");
4400 bt_sock_unregister(BTPROTO_L2CAP);
4401 goto error;
4402 }
4403
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004404 if (bt_debugfs) {
4405 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4406 bt_debugfs, NULL, &l2cap_debugfs_fops);
4407 if (!l2cap_debugfs)
4408 BT_ERR("Failed to create L2CAP debug file");
4409 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410
Linus Torvalds1da177e2005-04-16 15:20:36 -07004411 return 0;
4412
4413error:
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004414 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415 return err;
4416}
4417
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004418void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004419{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004420 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4423 BT_ERR("L2CAP protocol unregistration failed");
4424
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004425 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004426}
4427
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004428module_param(disable_ertm, bool, 0644);
4429MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03004430
4431module_param(enable_hs, bool, 0644);
4432MODULE_PARM_DESC(enable_hs, "Enable High Speed");