blob: 410c9cda057c6d6b49f14ec54acdb1aed0b4b122 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
7 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation;
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
16 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090017 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090022 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
23 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 SOFTWARE IS DISCLAIMED.
25*/
26
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020027/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30
31#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080032#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
34#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/poll.h>
38#include <linux/fcntl.h>
39#include <linux/init.h>
40#include <linux/interrupt.h>
41#include <linux/socket.h>
42#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080044#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010045#include <linux/debugfs.h>
46#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030047#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030048#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/sock.h>
50
51#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
Anderson Brigliab501d6a2011-06-07 18:46:31 -030057#include <net/bluetooth/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020059int disable_ertm;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +030060int enable_hs;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020061
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070062static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010063static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Johannes Bergb5ad8b72011-06-01 08:54:45 +020065static LIST_HEAD(chan_list);
66static DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Linus Torvalds1da177e2005-04-16 15:20:36 -070068static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
69 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030070static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
71 void *data);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030072static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030073static void l2cap_send_disconn_req(struct l2cap_conn *conn,
74 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030076static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
77
Marcel Holtmann01394182006-07-03 10:02:46 +020078/* ---- L2CAP channels ---- */
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -030079
80static inline void chan_hold(struct l2cap_chan *c)
81{
82 atomic_inc(&c->refcnt);
83}
84
85static inline void chan_put(struct l2cap_chan *c)
86{
87 if (atomic_dec_and_test(&c->refcnt))
88 kfree(c);
89}
90
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030091static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020092{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030093 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030094
95 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030096 if (c->dcid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030097 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020098 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030099 return NULL;
100
Marcel Holtmann01394182006-07-03 10:02:46 +0200101}
102
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300103static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200104{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300105 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300106
107 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300108 if (c->scid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300109 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200110 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300111 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200112}
113
114/* Find channel with given SCID.
115 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300116static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200117{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300118 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300119
120 read_lock(&conn->chan_lock);
121 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300122 if (c)
123 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300124 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300125 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200126}
127
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300128static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200129{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300130 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300131
132 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300133 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300134 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200135 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300136 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200137}
138
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300139static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200140{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300141 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300142
143 read_lock(&conn->chan_lock);
144 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300145 if (c)
146 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300147 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300148 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200149}
150
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300151static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300152{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300153 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300154
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300155 list_for_each_entry(c, &chan_list, global_l) {
156 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300157 goto found;
158 }
159
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300160 c = NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300161found:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300162 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300163}
164
165int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
166{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300167 int err;
168
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300169 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300170
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300171 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300172 err = -EADDRINUSE;
173 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300174 }
175
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300176 if (psm) {
177 chan->psm = psm;
178 chan->sport = psm;
179 err = 0;
180 } else {
181 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300182
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300183 err = -EINVAL;
184 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300185 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300186 chan->psm = cpu_to_le16(p);
187 chan->sport = cpu_to_le16(p);
188 err = 0;
189 break;
190 }
191 }
192
193done:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300194 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300195 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300196}
197
198int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
199{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300200 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300201
202 chan->scid = scid;
203
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300204 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300205
206 return 0;
207}
208
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300209static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200210{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300211 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200212
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300213 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300214 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200215 return cid;
216 }
217
218 return 0;
219}
220
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300221static void l2cap_set_timer(struct l2cap_chan *chan, struct timer_list *timer, long timeout)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300222{
Mat Martineau774e5652011-06-29 14:35:20 -0700223 BT_DBG("chan %p state %d timeout %ld", chan->sk, chan->state, timeout);
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300224
Mat Martineau942ecc92011-06-29 14:35:21 -0700225 if (!mod_timer(timer, jiffies + msecs_to_jiffies(timeout)))
Mat Martineau774e5652011-06-29 14:35:20 -0700226 chan_hold(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300227}
228
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300229static void l2cap_clear_timer(struct l2cap_chan *chan, struct timer_list *timer)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300230{
Mat Martineau774e5652011-06-29 14:35:20 -0700231 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300232
Mat Martineau774e5652011-06-29 14:35:20 -0700233 if (timer_pending(timer) && del_timer(timer))
234 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300235}
236
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300237static void l2cap_state_change(struct l2cap_chan *chan, int state)
238{
239 chan->state = state;
240 chan->ops->state_change(chan->data, state);
241}
242
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300243static void l2cap_chan_timeout(unsigned long arg)
244{
245 struct l2cap_chan *chan = (struct l2cap_chan *) arg;
246 struct sock *sk = chan->sk;
247 int reason;
248
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300249 BT_DBG("chan %p state %d", chan, chan->state);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300250
251 bh_lock_sock(sk);
252
253 if (sock_owned_by_user(sk)) {
254 /* sk is owned by user. Try again later */
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -0300255 __set_chan_timer(chan, HZ / 5);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300256 bh_unlock_sock(sk);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300257 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300258 return;
259 }
260
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300261 if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300262 reason = ECONNREFUSED;
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300263 else if (chan->state == BT_CONNECT &&
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300264 chan->sec_level != BT_SECURITY_SDP)
265 reason = ECONNREFUSED;
266 else
267 reason = ETIMEDOUT;
268
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300269 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300270
271 bh_unlock_sock(sk);
272
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -0300273 chan->ops->close(chan->data);
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300274 chan_put(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300275}
276
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300277struct l2cap_chan *l2cap_chan_create(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200278{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300279 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200280
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300281 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
282 if (!chan)
283 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200284
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300285 chan->sk = sk;
286
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300287 write_lock_bh(&chan_list_lock);
288 list_add(&chan->global_l, &chan_list);
289 write_unlock_bh(&chan_list_lock);
290
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300291 setup_timer(&chan->chan_timer, l2cap_chan_timeout, (unsigned long) chan);
292
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -0300293 chan->state = BT_OPEN;
294
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300295 atomic_set(&chan->refcnt, 1);
296
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300297 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200298}
299
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300300void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300301{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300302 write_lock_bh(&chan_list_lock);
303 list_del(&chan->global_l);
304 write_unlock_bh(&chan_list_lock);
305
Gustavo F. Padovan71ba0e52011-05-17 14:34:52 -0300306 chan_put(chan);
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300307}
308
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300309static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200310{
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300311 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300312 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200313
Marcel Holtmann2950f212009-02-12 14:02:50 +0100314 conn->disc_reason = 0x13;
315
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300316 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200317
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300318 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
Ville Tervob62f3282011-02-10 22:38:50 -0300319 if (conn->hcon->type == LE_LINK) {
320 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300321 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300322 chan->scid = L2CAP_CID_LE_DATA;
323 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300324 } else {
325 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300326 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300327 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300328 }
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300329 } else if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200330 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300331 chan->scid = L2CAP_CID_CONN_LESS;
332 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300333 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200334 } else {
335 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300336 chan->scid = L2CAP_CID_SIGNALING;
337 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300338 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200339 }
340
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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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. Padovan89bc5002011-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
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001873static void l2cap_ack_timeout(unsigned long arg)
1874{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001875 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001876
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001877 bh_lock_sock(chan->sk);
1878 l2cap_send_ack(chan);
1879 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001880}
1881
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001882static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001883{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001884 struct sock *sk = chan->sk;
1885
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001886 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001887 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001888 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001889 chan->num_acked = 0;
1890 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001891
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001892 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1893 (unsigned long) chan);
1894 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1895 (unsigned long) chan);
1896 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001897
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001898 skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001899
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001900 INIT_LIST_HEAD(&chan->srej_l);
1901
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001902
1903 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001904}
1905
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001906static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1907{
1908 switch (mode) {
1909 case L2CAP_MODE_STREAMING:
1910 case L2CAP_MODE_ERTM:
1911 if (l2cap_mode_supported(mode, remote_feat_mask))
1912 return mode;
1913 /* fall through */
1914 default:
1915 return L2CAP_MODE_BASIC;
1916 }
1917}
1918
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001919static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
1920{
1921 return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
1922}
1923
1924static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
1925{
1926 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
1927 __l2cap_ews_supported(chan))
1928 /* use extended control field */
1929 set_bit(FLAG_EXT_CTRL, &chan->flags);
1930 else
1931 chan->tx_win = min_t(u16, chan->tx_win,
1932 L2CAP_DEFAULT_TX_WINDOW);
1933}
1934
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001935static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001938 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 void *ptr = req->data;
1940
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001941 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001943 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001944 goto done;
1945
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001946 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001947 case L2CAP_MODE_STREAMING:
1948 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03001949 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001950 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001951
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001952 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001953 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001954 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001955 break;
1956 }
1957
1958done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001959 if (chan->imtu != L2CAP_DEFAULT_MTU)
1960 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001961
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001962 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001963 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001964 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1965 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001966 break;
1967
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001968 rfc.mode = L2CAP_MODE_BASIC;
1969 rfc.txwin_size = 0;
1970 rfc.max_transmit = 0;
1971 rfc.retrans_timeout = 0;
1972 rfc.monitor_timeout = 0;
1973 rfc.max_pdu_size = 0;
1974
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001975 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1976 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001977 break;
1978
1979 case L2CAP_MODE_ERTM:
1980 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001981 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001982 rfc.retrans_timeout = 0;
1983 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001984 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001985 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1986 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001987
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03001988 l2cap_txwin_setup(chan);
1989
1990 rfc.txwin_size = min_t(u16, chan->tx_win,
1991 L2CAP_DEFAULT_TX_WINDOW);
1992
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001993 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1994 (unsigned long) &rfc);
1995
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001996 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001997 break;
1998
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001999 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002000 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002001 chan->fcs = L2CAP_FCS_NONE;
2002 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002003 }
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002004
2005 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2006 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
2007 chan->tx_win);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002008 break;
2009
2010 case L2CAP_MODE_STREAMING:
2011 rfc.mode = L2CAP_MODE_STREAMING;
2012 rfc.txwin_size = 0;
2013 rfc.max_transmit = 0;
2014 rfc.retrans_timeout = 0;
2015 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002016 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002017 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
2018 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002019
Gustavo F. Padovan63406502010-08-03 23:49:29 -03002020 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
2021 (unsigned long) &rfc);
2022
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002023 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002024 break;
2025
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002026 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002027 test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002028 chan->fcs = L2CAP_FCS_NONE;
2029 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002030 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07002031 break;
2032 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002034 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002035 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036
2037 return ptr - data;
2038}
2039
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002040static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002042 struct l2cap_conf_rsp *rsp = data;
2043 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002044 void *req = chan->conf_req;
2045 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002046 int type, hint, olen;
2047 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002048 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02002049 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002050 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002052 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002053
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002054 while (len >= L2CAP_CONF_OPT_SIZE) {
2055 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002057 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002058 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002059
2060 switch (type) {
2061 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002062 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002063 break;
2064
2065 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002066 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002067 break;
2068
2069 case L2CAP_CONF_QOS:
2070 break;
2071
Marcel Holtmann6464f352007-10-20 13:39:51 +02002072 case L2CAP_CONF_RFC:
2073 if (olen == sizeof(rfc))
2074 memcpy(&rfc, (void *) val, olen);
2075 break;
2076
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002077 case L2CAP_CONF_FCS:
2078 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002079 set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002080
2081 break;
2082
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002083 case L2CAP_CONF_EWS:
2084 if (!enable_hs)
2085 return -ECONNREFUSED;
2086
2087 set_bit(FLAG_EXT_CTRL, &chan->flags);
2088 set_bit(CONF_EWS_RECV, &chan->conf_state);
2089 chan->remote_tx_win = val;
2090 break;
2091
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002092 default:
2093 if (hint)
2094 break;
2095
2096 result = L2CAP_CONF_UNKNOWN;
2097 *((u8 *) ptr++) = type;
2098 break;
2099 }
2100 }
2101
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002102 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002103 goto done;
2104
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002105 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002106 case L2CAP_MODE_STREAMING:
2107 case L2CAP_MODE_ERTM:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002108 if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002109 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002110 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002111 break;
2112 }
2113
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002114 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002115 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002116
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002117 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002118 }
2119
2120done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002121 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002122 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002123 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002124
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002125 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002126 return -ECONNREFUSED;
2127
2128 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2129 sizeof(rfc), (unsigned long) &rfc);
2130 }
2131
2132
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002133 if (result == L2CAP_CONF_SUCCESS) {
2134 /* Configure output options and let the other side know
2135 * which ones we don't like. */
2136
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002137 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2138 result = L2CAP_CONF_UNACCEPT;
2139 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002140 chan->omtu = mtu;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002141 set_bit(CONF_MTU_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002142 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002143 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002144
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002145 switch (rfc.mode) {
2146 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002147 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002148 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002149 break;
2150
2151 case L2CAP_MODE_ERTM:
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002152 if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
2153 chan->remote_tx_win = rfc.txwin_size;
2154 else
2155 rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
2156
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002157 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002158
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002159 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2160 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002161
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002162 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002163
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002164 rfc.retrans_timeout =
2165 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2166 rfc.monitor_timeout =
2167 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002168
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002169 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002170
2171 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2172 sizeof(rfc), (unsigned long) &rfc);
2173
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002174 break;
2175
2176 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002177 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2178 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002179
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002180 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002181
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002182 set_bit(CONF_MODE_DONE, &chan->conf_state);
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002183
2184 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2185 sizeof(rfc), (unsigned long) &rfc);
2186
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002187 break;
2188
2189 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002190 result = L2CAP_CONF_UNACCEPT;
2191
2192 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002193 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002194 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002195
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002196 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002197 set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002198 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002199 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002200 rsp->result = cpu_to_le16(result);
2201 rsp->flags = cpu_to_le16(0x0000);
2202
2203 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204}
2205
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002206static 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 -03002207{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002208 struct l2cap_conf_req *req = data;
2209 void *ptr = req->data;
2210 int type, olen;
2211 unsigned long val;
2212 struct l2cap_conf_rfc rfc;
2213
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002214 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002215
2216 while (len >= L2CAP_CONF_OPT_SIZE) {
2217 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2218
2219 switch (type) {
2220 case L2CAP_CONF_MTU:
2221 if (val < L2CAP_DEFAULT_MIN_MTU) {
2222 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002223 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002224 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002225 chan->imtu = val;
2226 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002227 break;
2228
2229 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002230 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002231 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002232 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002233 break;
2234
2235 case L2CAP_CONF_RFC:
2236 if (olen == sizeof(rfc))
2237 memcpy(&rfc, (void *)val, olen);
2238
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002239 if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002240 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002241 return -ECONNREFUSED;
2242
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002243 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002244
2245 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2246 sizeof(rfc), (unsigned long) &rfc);
2247 break;
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002248
2249 case L2CAP_CONF_EWS:
2250 chan->tx_win = min_t(u16, val,
2251 L2CAP_DEFAULT_EXT_WINDOW);
2252 l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS,
2253 2, chan->tx_win);
2254 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002255 }
2256 }
2257
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002258 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002259 return -ECONNREFUSED;
2260
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002261 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002262
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002263 if (*result == L2CAP_CONF_SUCCESS) {
2264 switch (rfc.mode) {
2265 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002266 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2267 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2268 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002269 break;
2270 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002271 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002272 }
2273 }
2274
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002275 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002276 req->flags = cpu_to_le16(0x0000);
2277
2278 return ptr - data;
2279}
2280
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002281static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282{
2283 struct l2cap_conf_rsp *rsp = data;
2284 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002286 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002288 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002289 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002290 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291
2292 return ptr - data;
2293}
2294
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002295void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002296{
2297 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002298 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002299 u8 buf[128];
2300
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002301 rsp.scid = cpu_to_le16(chan->dcid);
2302 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002303 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2304 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2305 l2cap_send_cmd(conn, chan->ident,
2306 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2307
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002308 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002309 return;
2310
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002311 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2312 l2cap_build_conf_req(chan, buf), buf);
2313 chan->num_conf_req++;
2314}
2315
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002316static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002317{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002318 int type, olen;
2319 unsigned long val;
2320 struct l2cap_conf_rfc rfc;
2321
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002322 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002323
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002324 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002325 return;
2326
2327 while (len >= L2CAP_CONF_OPT_SIZE) {
2328 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2329
2330 switch (type) {
2331 case L2CAP_CONF_RFC:
2332 if (olen == sizeof(rfc))
2333 memcpy(&rfc, (void *)val, olen);
2334 goto done;
2335 }
2336 }
2337
2338done:
2339 switch (rfc.mode) {
2340 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002341 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2342 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2343 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002344 break;
2345 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002346 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002347 }
2348}
2349
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002350static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2351{
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002352 struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002353
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002354 if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002355 return 0;
2356
2357 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2358 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002359 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002360
2361 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002362 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002363
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002364 l2cap_conn_start(conn);
2365 }
2366
2367 return 0;
2368}
2369
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2371{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2373 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002374 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002375 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002376 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377
2378 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002379 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380
2381 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2382
2383 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002384 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2385 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386 result = L2CAP_CR_BAD_PSM;
2387 goto sendresp;
2388 }
2389
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002390 parent = pchan->sk;
2391
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002392 bh_lock_sock(parent);
2393
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002394 /* Check if the ACL is secure enough (if not SDP) */
2395 if (psm != cpu_to_le16(0x0001) &&
2396 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002397 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002398 result = L2CAP_CR_SEC_BLOCK;
2399 goto response;
2400 }
2401
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 result = L2CAP_CR_NO_MEM;
2403
2404 /* Check for backlog size */
2405 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002406 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407 goto response;
2408 }
2409
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002410 chan = pchan->ops->new_connection(pchan->data);
2411 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 goto response;
2413
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002414 sk = chan->sk;
2415
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002416 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417
2418 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002419 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2420 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 sock_set_flag(sk, SOCK_ZAPPED);
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002422 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 goto response;
2424 }
2425
2426 hci_conn_hold(conn->hcon);
2427
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 bacpy(&bt_sk(sk)->src, conn->src);
2429 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002430 chan->psm = psm;
2431 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002433 bt_accept_enqueue(parent, sk);
2434
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002435 __l2cap_chan_add(conn, chan);
2436
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002437 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002439 __set_chan_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002441 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442
Marcel Holtmann984947d2009-02-06 23:35:19 +01002443 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002444 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002445 if (bt_sk(sk)->defer_setup) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002446 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002447 result = L2CAP_CR_PEND;
2448 status = L2CAP_CS_AUTHOR_PEND;
2449 parent->sk_data_ready(parent, 0);
2450 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002451 l2cap_state_change(chan, BT_CONFIG);
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002452 result = L2CAP_CR_SUCCESS;
2453 status = L2CAP_CS_NO_INFO;
2454 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002455 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002456 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002457 result = L2CAP_CR_PEND;
2458 status = L2CAP_CS_AUTHEN_PEND;
2459 }
2460 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002461 l2cap_state_change(chan, BT_CONNECT2);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002462 result = L2CAP_CR_PEND;
2463 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 }
2465
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002466 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467
2468response:
2469 bh_unlock_sock(parent);
2470
2471sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002472 rsp.scid = cpu_to_le16(scid);
2473 rsp.dcid = cpu_to_le16(dcid);
2474 rsp.result = cpu_to_le16(result);
2475 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002477
2478 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2479 struct l2cap_info_req info;
2480 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2481
2482 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2483 conn->info_ident = l2cap_get_ident(conn);
2484
2485 mod_timer(&conn->info_timer, jiffies +
2486 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2487
2488 l2cap_send_cmd(conn, conn->info_ident,
2489 L2CAP_INFO_REQ, sizeof(info), &info);
2490 }
2491
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002492 if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002493 result == L2CAP_CR_SUCCESS) {
2494 u8 buf[128];
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002495 set_bit(CONF_REQ_SENT, &chan->conf_state);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002496 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002497 l2cap_build_conf_req(chan, buf), buf);
2498 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002499 }
2500
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501 return 0;
2502}
2503
2504static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2505{
2506 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2507 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002508 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509 struct sock *sk;
2510 u8 req[128];
2511
2512 scid = __le16_to_cpu(rsp->scid);
2513 dcid = __le16_to_cpu(rsp->dcid);
2514 result = __le16_to_cpu(rsp->result);
2515 status = __le16_to_cpu(rsp->status);
2516
2517 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2518
2519 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002520 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002521 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002522 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002524 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002525 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002526 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527 }
2528
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002529 sk = chan->sk;
2530
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531 switch (result) {
2532 case L2CAP_CR_SUCCESS:
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002533 l2cap_state_change(chan, BT_CONFIG);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002534 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002535 chan->dcid = dcid;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002536 clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002537
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002538 if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002539 break;
2540
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541 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, req), req);
2543 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544 break;
2545
2546 case L2CAP_CR_PEND:
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002547 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548 break;
2549
2550 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002551 /* don't delete l2cap channel if sk is owned by user */
2552 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002553 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002554 __clear_chan_timer(chan);
2555 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002556 break;
2557 }
2558
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002559 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 break;
2561 }
2562
2563 bh_unlock_sock(sk);
2564 return 0;
2565}
2566
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002567static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002568{
2569 /* FCS is enabled only in ERTM or streaming mode, if one or both
2570 * sides request it.
2571 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002572 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002573 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002574 else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002575 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002576}
2577
Al Viro88219a02007-07-29 00:17:25 -07002578static 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 -07002579{
2580 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2581 u16 dcid, flags;
2582 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002583 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002585 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586
2587 dcid = __le16_to_cpu(req->dcid);
2588 flags = __le16_to_cpu(req->flags);
2589
2590 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2591
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002592 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002593 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 return -ENOENT;
2595
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002596 sk = chan->sk;
2597
David S. Miller033b1142011-07-21 13:38:42 -07002598 if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002599 struct l2cap_cmd_rej_cid rej;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002600
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03002601 rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2602 rej.scid = cpu_to_le16(chan->scid);
2603 rej.dcid = cpu_to_le16(chan->dcid);
2604
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002605 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2606 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002607 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002608 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002609
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002610 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002611 len = cmd_len - sizeof(*req);
Dan Rosenberg7ac28812011-06-24 08:38:05 -04002612 if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002613 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002614 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002615 L2CAP_CONF_REJECT, flags), rsp);
2616 goto unlock;
2617 }
2618
2619 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002620 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2621 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622
2623 if (flags & 0x0001) {
2624 /* Incomplete config. Send empty response. */
2625 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002626 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002627 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628 goto unlock;
2629 }
2630
2631 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002632 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002633 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002634 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002636 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002638 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002639 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002640
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002641 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002642 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002643
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002644 if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002645 goto unlock;
2646
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002647 if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002648 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002649
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002650 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002651
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002652 chan->next_tx_seq = 0;
2653 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002654 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002655 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002656 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002657
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002659 goto unlock;
2660 }
2661
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002662 if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002663 u8 buf[64];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002665 l2cap_build_conf_req(chan, buf), buf);
2666 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667 }
2668
2669unlock:
2670 bh_unlock_sock(sk);
2671 return 0;
2672}
2673
2674static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2675{
2676 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2677 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002678 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002680 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681
2682 scid = __le16_to_cpu(rsp->scid);
2683 flags = __le16_to_cpu(rsp->flags);
2684 result = __le16_to_cpu(rsp->result);
2685
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002686 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2687 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002689 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002690 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691 return 0;
2692
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002693 sk = chan->sk;
2694
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695 switch (result) {
2696 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002697 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698 break;
2699
2700 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002701 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002702 char req[64];
2703
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002704 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002705 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002706 goto done;
2707 }
2708
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002709 /* throw out any old stored conf requests */
2710 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002711 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2712 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002713 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002714 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002715 goto done;
2716 }
2717
2718 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2719 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002720 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002721 if (result != L2CAP_CONF_SUCCESS)
2722 goto done;
2723 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 }
2725
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002726 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002727 sk->sk_err = ECONNRESET;
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002728 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002729 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 goto done;
2731 }
2732
2733 if (flags & 0x01)
2734 goto done;
2735
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002736 set_bit(CONF_INPUT_DONE, &chan->conf_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03002738 if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002739 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002740
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002741 l2cap_state_change(chan, BT_CONNECTED);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002742 chan->next_tx_seq = 0;
2743 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002744 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002745 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002746 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002747
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 l2cap_chan_ready(sk);
2749 }
2750
2751done:
2752 bh_unlock_sock(sk);
2753 return 0;
2754}
2755
2756static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2757{
2758 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2759 struct l2cap_disconn_rsp rsp;
2760 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002761 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 struct sock *sk;
2763
2764 scid = __le16_to_cpu(req->scid);
2765 dcid = __le16_to_cpu(req->dcid);
2766
2767 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2768
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002769 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002770 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 return 0;
2772
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002773 sk = chan->sk;
2774
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002775 rsp.dcid = cpu_to_le16(chan->scid);
2776 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2778
2779 sk->sk_shutdown = SHUTDOWN_MASK;
2780
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002781 /* don't delete l2cap channel if sk is owned by user */
2782 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002783 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002784 __clear_chan_timer(chan);
2785 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002786 bh_unlock_sock(sk);
2787 return 0;
2788 }
2789
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002790 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 bh_unlock_sock(sk);
2792
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002793 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794 return 0;
2795}
2796
2797static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2798{
2799 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2800 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002801 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802 struct sock *sk;
2803
2804 scid = __le16_to_cpu(rsp->scid);
2805 dcid = __le16_to_cpu(rsp->dcid);
2806
2807 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2808
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002809 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002810 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811 return 0;
2812
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002813 sk = chan->sk;
2814
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002815 /* don't delete l2cap channel if sk is owned by user */
2816 if (sock_owned_by_user(sk)) {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03002817 l2cap_state_change(chan,BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03002818 __clear_chan_timer(chan);
2819 __set_chan_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002820 bh_unlock_sock(sk);
2821 return 0;
2822 }
2823
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002824 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825 bh_unlock_sock(sk);
2826
Gustavo F. Padovanba3bd0e2011-05-16 18:23:24 -03002827 chan->ops->close(chan->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828 return 0;
2829}
2830
2831static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2832{
2833 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834 u16 type;
2835
2836 type = __le16_to_cpu(req->type);
2837
2838 BT_DBG("type 0x%4.4x", type);
2839
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002840 if (type == L2CAP_IT_FEAT_MASK) {
2841 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002842 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002843 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2844 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2845 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002846 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002847 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2848 | L2CAP_FEAT_FCS;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03002849 if (enable_hs)
Andrei Emeltchenko6327eb92011-10-11 13:37:42 +03002850 feat_mask |= L2CAP_FEAT_EXT_FLOW
2851 | L2CAP_FEAT_EXT_WINDOW;
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03002852
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002853 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002854 l2cap_send_cmd(conn, cmd->ident,
2855 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002856 } else if (type == L2CAP_IT_FIXED_CHAN) {
2857 u8 buf[12];
2858 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2859 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2860 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2861 memcpy(buf + 4, l2cap_fixed_chan, 8);
2862 l2cap_send_cmd(conn, cmd->ident,
2863 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002864 } else {
2865 struct l2cap_info_rsp rsp;
2866 rsp.type = cpu_to_le16(type);
2867 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2868 l2cap_send_cmd(conn, cmd->ident,
2869 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2870 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871
2872 return 0;
2873}
2874
2875static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2876{
2877 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2878 u16 type, result;
2879
2880 type = __le16_to_cpu(rsp->type);
2881 result = __le16_to_cpu(rsp->result);
2882
2883 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2884
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002885 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2886 if (cmd->ident != conn->info_ident ||
2887 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2888 return 0;
2889
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002890 del_timer(&conn->info_timer);
2891
Ville Tervoadb08ed2010-08-04 09:43:33 +03002892 if (result != L2CAP_IR_SUCCESS) {
2893 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2894 conn->info_ident = 0;
2895
2896 l2cap_conn_start(conn);
2897
2898 return 0;
2899 }
2900
Marcel Holtmann984947d2009-02-06 23:35:19 +01002901 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002902 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002903
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002904 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002905 struct l2cap_info_req req;
2906 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2907
2908 conn->info_ident = l2cap_get_ident(conn);
2909
2910 l2cap_send_cmd(conn, conn->info_ident,
2911 L2CAP_INFO_REQ, sizeof(req), &req);
2912 } else {
2913 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2914 conn->info_ident = 0;
2915
2916 l2cap_conn_start(conn);
2917 }
2918 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002919 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002920 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002921
2922 l2cap_conn_start(conn);
2923 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002924
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925 return 0;
2926}
2927
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002928static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002929 u16 to_multiplier)
2930{
2931 u16 max_latency;
2932
2933 if (min > max || min < 6 || max > 3200)
2934 return -EINVAL;
2935
2936 if (to_multiplier < 10 || to_multiplier > 3200)
2937 return -EINVAL;
2938
2939 if (max >= to_multiplier * 8)
2940 return -EINVAL;
2941
2942 max_latency = (to_multiplier * 8 / max) - 1;
2943 if (latency > 499 || latency > max_latency)
2944 return -EINVAL;
2945
2946 return 0;
2947}
2948
2949static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2950 struct l2cap_cmd_hdr *cmd, u8 *data)
2951{
2952 struct hci_conn *hcon = conn->hcon;
2953 struct l2cap_conn_param_update_req *req;
2954 struct l2cap_conn_param_update_rsp rsp;
2955 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002956 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002957
2958 if (!(hcon->link_mode & HCI_LM_MASTER))
2959 return -EINVAL;
2960
2961 cmd_len = __le16_to_cpu(cmd->len);
2962 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2963 return -EPROTO;
2964
2965 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002966 min = __le16_to_cpu(req->min);
2967 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002968 latency = __le16_to_cpu(req->latency);
2969 to_multiplier = __le16_to_cpu(req->to_multiplier);
2970
2971 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2972 min, max, latency, to_multiplier);
2973
2974 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002975
2976 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2977 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002978 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2979 else
2980 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2981
2982 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2983 sizeof(rsp), &rsp);
2984
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002985 if (!err)
2986 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2987
Claudio Takahaside731152011-02-11 19:28:55 -02002988 return 0;
2989}
2990
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002991static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2992 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2993{
2994 int err = 0;
2995
2996 switch (cmd->code) {
2997 case L2CAP_COMMAND_REJ:
2998 l2cap_command_rej(conn, cmd, data);
2999 break;
3000
3001 case L2CAP_CONN_REQ:
3002 err = l2cap_connect_req(conn, cmd, data);
3003 break;
3004
3005 case L2CAP_CONN_RSP:
3006 err = l2cap_connect_rsp(conn, cmd, data);
3007 break;
3008
3009 case L2CAP_CONF_REQ:
3010 err = l2cap_config_req(conn, cmd, cmd_len, data);
3011 break;
3012
3013 case L2CAP_CONF_RSP:
3014 err = l2cap_config_rsp(conn, cmd, data);
3015 break;
3016
3017 case L2CAP_DISCONN_REQ:
3018 err = l2cap_disconnect_req(conn, cmd, data);
3019 break;
3020
3021 case L2CAP_DISCONN_RSP:
3022 err = l2cap_disconnect_rsp(conn, cmd, data);
3023 break;
3024
3025 case L2CAP_ECHO_REQ:
3026 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
3027 break;
3028
3029 case L2CAP_ECHO_RSP:
3030 break;
3031
3032 case L2CAP_INFO_REQ:
3033 err = l2cap_information_req(conn, cmd, data);
3034 break;
3035
3036 case L2CAP_INFO_RSP:
3037 err = l2cap_information_rsp(conn, cmd, data);
3038 break;
3039
3040 default:
3041 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
3042 err = -EINVAL;
3043 break;
3044 }
3045
3046 return err;
3047}
3048
3049static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
3050 struct l2cap_cmd_hdr *cmd, u8 *data)
3051{
3052 switch (cmd->code) {
3053 case L2CAP_COMMAND_REJ:
3054 return 0;
3055
3056 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02003057 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003058
3059 case L2CAP_CONN_PARAM_UPDATE_RSP:
3060 return 0;
3061
3062 default:
3063 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
3064 return -EINVAL;
3065 }
3066}
3067
3068static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3069 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070{
3071 u8 *data = skb->data;
3072 int len = skb->len;
3073 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003074 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075
3076 l2cap_raw_recv(conn, skb);
3077
3078 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003079 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3081 data += L2CAP_CMD_HDR_SIZE;
3082 len -= L2CAP_CMD_HDR_SIZE;
3083
Al Viro88219a02007-07-29 00:17:25 -07003084 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085
Al Viro88219a02007-07-29 00:17:25 -07003086 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 -07003087
Al Viro88219a02007-07-29 00:17:25 -07003088 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003089 BT_DBG("corrupted command");
3090 break;
3091 }
3092
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003093 if (conn->hcon->type == LE_LINK)
3094 err = l2cap_le_sig_cmd(conn, &cmd, data);
3095 else
3096 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097
3098 if (err) {
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003099 struct l2cap_cmd_rej_unk rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003100
3101 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102
3103 /* FIXME: Map err to a valid reason */
Ilia Kolomisnkye2fd3182011-07-10 08:47:44 +03003104 rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3106 }
3107
Al Viro88219a02007-07-29 00:17:25 -07003108 data += cmd_len;
3109 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110 }
3111
3112 kfree_skb(skb);
3113}
3114
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003115static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003116{
3117 u16 our_fcs, rcv_fcs;
Andrei Emeltchenkoe4ca6d92011-10-11 13:37:52 +03003118 int hdr_size;
3119
3120 if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3121 hdr_size = L2CAP_EXT_HDR_SIZE;
3122 else
3123 hdr_size = L2CAP_ENH_HDR_SIZE;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003124
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003125 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003126 skb_trim(skb, skb->len - 2);
3127 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3128 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3129
3130 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003131 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003132 }
3133 return 0;
3134}
3135
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003136static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003137{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003138 u16 control = 0;
3139
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003140 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003141
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003142 control |= __set_reqseq(chan, chan->buffer_seq);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003143
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003144 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003145 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003146 l2cap_send_sframe(chan, control);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003147 set_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003148 }
3149
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003150 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003151 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003152
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003153 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003154
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003155 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003156 chan->frames_sent == 0) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003157 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003158 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003159 }
3160}
3161
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003162static 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 -03003163{
3164 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003165 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003166
3167 bt_cb(skb)->tx_seq = tx_seq;
3168 bt_cb(skb)->sar = sar;
3169
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003170 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003171 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003172 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003173 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003174 }
3175
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003176 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003177 if (tx_seq_offset < 0)
3178 tx_seq_offset += 64;
3179
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003180 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003181 if (bt_cb(next_skb)->tx_seq == tx_seq)
3182 return -EINVAL;
3183
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003184 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003185 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003186 if (next_tx_seq_offset < 0)
3187 next_tx_seq_offset += 64;
3188
3189 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003190 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003191 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003192 }
3193
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003194 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003195 break;
3196
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003197 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003198
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003199 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003200
3201 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003202}
3203
Mat Martineau84084a32011-07-22 14:54:00 -07003204static void append_skb_frag(struct sk_buff *skb,
3205 struct sk_buff *new_frag, struct sk_buff **last_frag)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003206{
Mat Martineau84084a32011-07-22 14:54:00 -07003207 /* skb->len reflects data in skb as well as all fragments
3208 * skb->data_len reflects only data in fragments
3209 */
3210 if (!skb_has_frag_list(skb))
3211 skb_shinfo(skb)->frag_list = new_frag;
3212
3213 new_frag->next = NULL;
3214
3215 (*last_frag)->next = new_frag;
3216 *last_frag = new_frag;
3217
3218 skb->len += new_frag->len;
3219 skb->data_len += new_frag->len;
3220 skb->truesize += new_frag->truesize;
3221}
3222
3223static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
3224{
3225 int err = -EINVAL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003226
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003227 switch (__get_ctrl_sar(chan, control)) {
3228 case L2CAP_SAR_UNSEGMENTED:
Mat Martineau84084a32011-07-22 14:54:00 -07003229 if (chan->sdu)
3230 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003231
Mat Martineau84084a32011-07-22 14:54:00 -07003232 err = chan->ops->recv(chan->data, skb);
3233 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003234
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003235 case L2CAP_SAR_START:
Mat Martineau84084a32011-07-22 14:54:00 -07003236 if (chan->sdu)
3237 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003238
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003239 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003240 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003241
Mat Martineau84084a32011-07-22 14:54:00 -07003242 if (chan->sdu_len > chan->imtu) {
3243 err = -EMSGSIZE;
3244 break;
3245 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003246
Mat Martineau84084a32011-07-22 14:54:00 -07003247 if (skb->len >= chan->sdu_len)
3248 break;
3249
3250 chan->sdu = skb;
3251 chan->sdu_last_frag = skb;
3252
3253 skb = NULL;
3254 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003255 break;
3256
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003257 case L2CAP_SAR_CONTINUE:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003258 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003259 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003260
Mat Martineau84084a32011-07-22 14:54:00 -07003261 append_skb_frag(chan->sdu, skb,
3262 &chan->sdu_last_frag);
3263 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003264
Mat Martineau84084a32011-07-22 14:54:00 -07003265 if (chan->sdu->len >= chan->sdu_len)
3266 break;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003267
Mat Martineau84084a32011-07-22 14:54:00 -07003268 err = 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003269 break;
3270
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003271 case L2CAP_SAR_END:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003272 if (!chan->sdu)
Mat Martineau84084a32011-07-22 14:54:00 -07003273 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003274
Mat Martineau84084a32011-07-22 14:54:00 -07003275 append_skb_frag(chan->sdu, skb,
3276 &chan->sdu_last_frag);
3277 skb = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003278
Mat Martineau84084a32011-07-22 14:54:00 -07003279 if (chan->sdu->len != chan->sdu_len)
3280 break;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003281
Mat Martineau84084a32011-07-22 14:54:00 -07003282 err = chan->ops->recv(chan->data, chan->sdu);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003283
Mat Martineau84084a32011-07-22 14:54:00 -07003284 if (!err) {
3285 /* Reassembly complete */
3286 chan->sdu = NULL;
3287 chan->sdu_last_frag = NULL;
3288 chan->sdu_len = 0;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003289 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003290 break;
3291 }
3292
Mat Martineau84084a32011-07-22 14:54:00 -07003293 if (err) {
3294 kfree_skb(skb);
3295 kfree_skb(chan->sdu);
3296 chan->sdu = NULL;
3297 chan->sdu_last_frag = NULL;
3298 chan->sdu_len = 0;
3299 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003300
Mat Martineau84084a32011-07-22 14:54:00 -07003301 return err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003302}
3303
Mat Martineau26f880d2011-07-07 09:39:01 -07003304static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003305{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003306 u16 control;
3307
Mat Martineau26f880d2011-07-07 09:39:01 -07003308 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003309
Mat Martineau26f880d2011-07-07 09:39:01 -07003310 set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3311
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003312 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003313 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
Mat Martineau26f880d2011-07-07 09:39:01 -07003314 l2cap_send_sframe(chan, control);
3315
3316 set_bit(CONN_RNR_SENT, &chan->conn_state);
3317
3318 __clear_ack_timer(chan);
3319}
3320
3321static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
3322{
3323 u16 control;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003324
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003325 if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003326 goto done;
3327
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003328 control = __set_reqseq(chan, chan->buffer_seq);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003329 control |= __set_ctrl_poll(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003330 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003331 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003332 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003333
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003334 __clear_retrans_timer(chan);
3335 __set_monitor_timer(chan);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003336
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003337 set_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003338
3339done:
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003340 clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3341 clear_bit(CONN_RNR_SENT, &chan->conn_state);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003342
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003343 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003344}
3345
Mat Martineaue3281402011-07-07 09:39:02 -07003346void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003347{
Mat Martineaue3281402011-07-07 09:39:02 -07003348 if (chan->mode == L2CAP_MODE_ERTM) {
3349 if (busy)
3350 l2cap_ertm_enter_local_busy(chan);
3351 else
3352 l2cap_ertm_exit_local_busy(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003353 }
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003354}
3355
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003356static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003357{
3358 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003359 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003360
Mat Martineaue3281402011-07-07 09:39:02 -07003361 while ((skb = skb_peek(&chan->srej_q)) &&
3362 !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3363 int err;
3364
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003365 if (bt_cb(skb)->tx_seq != tx_seq)
3366 break;
3367
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003368 skb = skb_dequeue(&chan->srej_q);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003369 control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
Mat Martineau84084a32011-07-22 14:54:00 -07003370 err = l2cap_reassemble_sdu(chan, skb, control);
Mat Martineaue3281402011-07-07 09:39:02 -07003371
3372 if (err < 0) {
3373 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3374 break;
3375 }
3376
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003377 chan->buffer_seq_srej =
3378 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003379 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003380 }
3381}
3382
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003383static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003384{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003385 struct srej_list *l, *tmp;
3386 u16 control;
3387
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003388 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003389 if (l->tx_seq == tx_seq) {
3390 list_del(&l->list);
3391 kfree(l);
3392 return;
3393 }
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003394 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003395 control |= __set_reqseq(chan, l->tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003396 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003397 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003398 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003399 }
3400}
3401
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003402static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003403{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003404 struct srej_list *new;
3405 u16 control;
3406
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003407 while (tx_seq != chan->expected_tx_seq) {
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003408 control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003409 control |= __set_reqseq(chan, chan->expected_tx_seq);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003410 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003411
3412 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003413 new->tx_seq = chan->expected_tx_seq;
3414 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003415 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003416 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003417 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003418}
3419
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003420static 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 -03003421{
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003422 u16 tx_seq = __get_txseq(chan, rx_control);
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003423 u16 req_seq = __get_reqseq(chan, rx_control);
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003424 u8 sar = __get_ctrl_sar(chan, rx_control);
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003425 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003426 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003427 int err = 0;
3428
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003429 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3430 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003431
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003432 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003433 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003434 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003435 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003436 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003437 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003438 }
3439
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003440 chan->expected_ack_seq = req_seq;
3441 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003442
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003443 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003444 if (tx_seq_offset < 0)
3445 tx_seq_offset += 64;
3446
3447 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003448 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003449 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003450 goto drop;
3451 }
3452
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003453 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003454 goto drop;
3455
Mat Martineau02f1b642011-06-29 14:35:19 -07003456 if (tx_seq == chan->expected_tx_seq)
3457 goto expected;
3458
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003459 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003460 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003461
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003462 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003463 struct srej_list, list);
3464 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003465 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003466 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003467
3468 list_del(&first->list);
3469 kfree(first);
3470
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003471 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003472 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003473 clear_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003474 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003475 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003476 }
3477 } else {
3478 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003479
3480 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003481 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003482 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003483
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003484 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003485 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003486 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003487 return 0;
3488 }
3489 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003490 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003491 }
3492 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003493 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003494 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003495 if (expected_tx_seq_offset < 0)
3496 expected_tx_seq_offset += 64;
3497
3498 /* duplicated tx_seq */
3499 if (tx_seq_offset < expected_tx_seq_offset)
3500 goto drop;
3501
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003502 set_bit(CONN_SREJ_SENT, &chan->conn_state);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003503
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003504 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003505
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003506 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003507 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003508
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003509 __skb_queue_head_init(&chan->srej_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003510 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003511
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003512 set_bit(CONN_SEND_PBIT, &chan->conn_state);
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003513
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003514 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003515
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003516 __clear_ack_timer(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003517 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003518 return 0;
3519
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003520expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003521 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003522
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003523 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003524 bt_cb(skb)->tx_seq = tx_seq;
3525 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003526 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003527 return 0;
3528 }
3529
Mat Martineau84084a32011-07-22 14:54:00 -07003530 err = l2cap_reassemble_sdu(chan, skb, rx_control);
Mat Martineaufadd1922011-07-07 09:39:03 -07003531 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Mat Martineaue3281402011-07-07 09:39:02 -07003532 if (err < 0) {
3533 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3534 return err;
3535 }
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003536
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003537 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003538 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003539 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003540 }
3541
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003542 __set_ack_timer(chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003543
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003544 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3545 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003546 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003547
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003548 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003549
3550drop:
3551 kfree_skb(skb);
3552 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003553}
3554
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003555static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003556{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003557 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan,
3558 __get_reqseq(chan, rx_control), rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003559
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003560 chan->expected_ack_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003561 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003562
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003563 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003564 set_bit(CONN_SEND_FBIT, &chan->conn_state);
3565 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3566 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003567 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003568 __set_retrans_timer(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003569
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003570 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003571 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003572 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003573 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003574 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003575
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003576 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003577 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003578
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003579 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003580 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003581
3582 } else {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003583 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003584 (chan->unacked_frames > 0))
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003585 __set_retrans_timer(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003586
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003587 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
3588 if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003589 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003590 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003591 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003592 }
3593}
3594
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003595static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003596{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003597 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003598
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003599 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003600
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003601 clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003602
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003603 chan->expected_ack_seq = tx_seq;
3604 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003605
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003606 if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003607 if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003608 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003609 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003610 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003611
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003612 if (test_bit(CONN_WAIT_F, &chan->conn_state))
3613 set_bit(CONN_REJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003614 }
3615}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003616static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003617{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003618 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003619
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003620 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003621
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
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003624 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003625 chan->expected_ack_seq = tx_seq;
3626 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003627
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003628 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003629 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003630
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003631 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003632
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003633 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003634 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003635 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003636 }
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003637 } else if (__is_ctrl_final(chan, rx_control)) {
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003638 if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003639 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003640 clear_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003641 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003642 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003643 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003644 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003645 if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003646 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003647 set_bit(CONN_SREJ_ACT, &chan->conn_state);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003648 }
3649 }
3650}
3651
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003652static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003653{
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003654 u16 tx_seq = __get_reqseq(chan, rx_control);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003655
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003656 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003657
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003658 set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003659 chan->expected_ack_seq = tx_seq;
3660 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003661
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003662 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003663 set_bit(CONN_SEND_FBIT, &chan->conn_state);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003664
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003665 if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003666 __clear_retrans_timer(chan);
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003667 if (__is_ctrl_poll(chan, rx_control))
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003668 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003669 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003670 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003671
Andrei Emeltchenkoe3781732011-10-11 13:37:50 +03003672 if (__is_ctrl_poll(chan, rx_control)) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003673 l2cap_send_srejtail(chan);
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003674 } else {
3675 rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
3676 l2cap_send_sframe(chan, rx_control);
3677 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003678}
3679
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003680static 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 -03003681{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003682 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003683
Andrei Emeltchenko03f67152011-10-11 13:37:49 +03003684 if (__is_ctrl_final(chan, rx_control) &&
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003685 test_bit(CONN_WAIT_F, &chan->conn_state)) {
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003686 __clear_monitor_timer(chan);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003687 if (chan->unacked_frames > 0)
Gustavo F. Padovan1a09bcb2011-05-17 15:13:19 -03003688 __set_retrans_timer(chan);
Gustavo F. Padovane2ab4352011-06-10 21:28:49 -03003689 clear_bit(CONN_WAIT_F, &chan->conn_state);
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003690 }
3691
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003692 switch (__get_ctrl_super(chan, rx_control)) {
3693 case L2CAP_SUPER_RR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003694 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003695 break;
3696
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003697 case L2CAP_SUPER_REJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003698 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003699 break;
3700
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003701 case L2CAP_SUPER_SREJ:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003702 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003703 break;
3704
Andrei Emeltchenkoab784b72011-10-11 13:37:44 +03003705 case L2CAP_SUPER_RNR:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003706 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003707 break;
3708 }
3709
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003710 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003711 return 0;
3712}
3713
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003714static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3715{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003716 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003717 u16 control;
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003718 u16 req_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003719 int len, next_tx_seq_offset, req_seq_offset;
3720
3721 control = get_unaligned_le16(skb->data);
3722 skb_pull(skb, 2);
3723 len = skb->len;
3724
3725 /*
3726 * We can just drop the corrupted I-frame here.
3727 * Receiver will miss it and start proper recovery
3728 * procedures and ask retransmission.
3729 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003730 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003731 goto drop;
3732
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03003733 if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003734 len -= 2;
3735
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003736 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003737 len -= 2;
3738
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003739 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003740 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003741 goto drop;
3742 }
3743
Andrei Emeltchenko0b209fa2011-10-11 13:37:46 +03003744 req_seq = __get_reqseq(chan, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003745 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003746 if (req_seq_offset < 0)
3747 req_seq_offset += 64;
3748
3749 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003750 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003751 if (next_tx_seq_offset < 0)
3752 next_tx_seq_offset += 64;
3753
3754 /* check for invalid req-seq */
3755 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003756 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003757 goto drop;
3758 }
3759
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03003760 if (!__is_sframe(chan, control)) {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003761 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003762 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003763 goto drop;
3764 }
3765
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003766 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003767 } else {
3768 if (len != 0) {
3769 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003770 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003771 goto drop;
3772 }
3773
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003774 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003775 }
3776
3777 return 0;
3778
3779drop:
3780 kfree_skb(skb);
3781 return 0;
3782}
3783
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3785{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003786 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003787 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003788 u16 control;
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003789 u16 tx_seq;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003790 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003792 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003793 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794 BT_DBG("unknown cid 0x%4.4x", cid);
3795 goto drop;
3796 }
3797
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003798 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003799
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003800 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003802 if (chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003803 goto drop;
3804
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003805 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003806 case L2CAP_MODE_BASIC:
3807 /* If socket recv buffers overflows we drop data here
3808 * which is *bad* because L2CAP has to be reliable.
3809 * But we don't have any other choice. L2CAP doesn't
3810 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003811
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003812 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003813 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003815 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003816 goto done;
3817 break;
3818
3819 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003820 if (!sock_owned_by_user(sk)) {
3821 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003822 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003823 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003824 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003825 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003826
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003827 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003828
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003829 case L2CAP_MODE_STREAMING:
3830 control = get_unaligned_le16(skb->data);
3831 skb_pull(skb, 2);
3832 len = skb->len;
3833
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003834 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003835 goto drop;
3836
Andrei Emeltchenko7e0ef6e2011-10-11 13:37:45 +03003837 if (__is_sar_start(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003838 len -= 2;
3839
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003840 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003841 len -= 2;
3842
Andrei Emeltchenko793c2f12011-10-11 13:37:48 +03003843 if (len > chan->mps || len < 0 || __is_sframe(chan, control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003844 goto drop;
3845
Andrei Emeltchenkofb45de72011-10-11 13:37:47 +03003846 tx_seq = __get_txseq(chan, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003847
Mat Martineau84084a32011-07-22 14:54:00 -07003848 if (chan->expected_tx_seq != tx_seq) {
3849 /* Frame(s) missing - must discard partial SDU */
3850 kfree_skb(chan->sdu);
3851 chan->sdu = NULL;
3852 chan->sdu_last_frag = NULL;
3853 chan->sdu_len = 0;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003854
Mat Martineau84084a32011-07-22 14:54:00 -07003855 /* TODO: Notify userland of missing data */
3856 }
3857
3858 chan->expected_tx_seq = (tx_seq + 1) % 64;
3859
3860 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
3861 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003862
3863 goto done;
3864
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003865 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003866 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003867 break;
3868 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869
3870drop:
3871 kfree_skb(skb);
3872
3873done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003874 if (sk)
3875 bh_unlock_sock(sk);
3876
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877 return 0;
3878}
3879
Al Viro8e036fc2007-07-29 00:16:36 -07003880static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003882 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003883 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003884
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003885 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3886 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887 goto drop;
3888
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003889 sk = chan->sk;
3890
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003891 bh_lock_sock(sk);
3892
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893 BT_DBG("sk %p, len %d", sk, skb->len);
3894
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003895 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896 goto drop;
3897
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003898 if (chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899 goto drop;
3900
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003901 if (!chan->ops->recv(chan->data, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902 goto done;
3903
3904drop:
3905 kfree_skb(skb);
3906
3907done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003908 if (sk)
3909 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910 return 0;
3911}
3912
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003913static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3914{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003915 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003916 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003917
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003918 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3919 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003920 goto drop;
3921
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003922 sk = chan->sk;
3923
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003924 bh_lock_sock(sk);
3925
3926 BT_DBG("sk %p, len %d", sk, skb->len);
3927
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03003928 if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003929 goto drop;
3930
Vinicius Costa Gomese13e21d2011-06-17 22:46:27 -03003931 if (chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003932 goto drop;
3933
Gustavo F. Padovan23070492011-05-16 17:57:22 -03003934 if (!chan->ops->recv(chan->data, skb))
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003935 goto done;
3936
3937drop:
3938 kfree_skb(skb);
3939
3940done:
3941 if (sk)
3942 bh_unlock_sock(sk);
3943 return 0;
3944}
3945
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3947{
3948 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003949 u16 cid, len;
3950 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951
3952 skb_pull(skb, L2CAP_HDR_SIZE);
3953 cid = __le16_to_cpu(lh->cid);
3954 len = __le16_to_cpu(lh->len);
3955
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003956 if (len != skb->len) {
3957 kfree_skb(skb);
3958 return;
3959 }
3960
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3962
3963 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003964 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003965 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966 l2cap_sig_channel(conn, skb);
3967 break;
3968
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003969 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003970 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003971 skb_pull(skb, 2);
3972 l2cap_conless_channel(conn, psm, skb);
3973 break;
3974
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003975 case L2CAP_CID_LE_DATA:
3976 l2cap_att_channel(conn, cid, skb);
3977 break;
3978
Anderson Brigliab501d6a2011-06-07 18:46:31 -03003979 case L2CAP_CID_SMP:
3980 if (smp_sig_channel(conn, skb))
3981 l2cap_conn_del(conn->hcon, EACCES);
3982 break;
3983
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984 default:
3985 l2cap_data_channel(conn, cid, skb);
3986 break;
3987 }
3988}
3989
3990/* ---- L2CAP interface with lower layer (HCI) ---- */
3991
3992static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3993{
3994 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003995 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996
3997 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003998 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999
4000 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4001
4002 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004003 read_lock(&chan_list_lock);
4004 list_for_each_entry(c, &chan_list, global_l) {
4005 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004006
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004007 if (c->state != BT_LISTEN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008 continue;
4009
4010 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004011 lm1 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004012 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004013 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004015 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4016 lm2 |= HCI_LM_ACCEPT;
Andrei Emeltchenko43bd0f32011-10-11 14:04:34 +03004017 if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004018 lm2 |= HCI_LM_MASTER;
4019 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004021 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022
4023 return exact ? lm1 : lm2;
4024}
4025
4026static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4027{
Marcel Holtmann01394182006-07-03 10:02:46 +02004028 struct l2cap_conn *conn;
4029
Linus Torvalds1da177e2005-04-16 15:20:36 -07004030 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4031
Ville Tervoacd7d372011-02-10 22:38:49 -03004032 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004033 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034
4035 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036 conn = l2cap_conn_add(hcon, status);
4037 if (conn)
4038 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004039 } else
Joe Perchese1750722011-06-29 18:18:29 -07004040 l2cap_conn_del(hcon, bt_to_errno(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041
4042 return 0;
4043}
4044
Marcel Holtmann2950f212009-02-12 14:02:50 +01004045static int l2cap_disconn_ind(struct hci_conn *hcon)
4046{
4047 struct l2cap_conn *conn = hcon->l2cap_data;
4048
4049 BT_DBG("hcon %p", hcon);
4050
Gustavo F. Padovanb5694502011-06-08 19:09:13 -03004051 if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
Marcel Holtmann2950f212009-02-12 14:02:50 +01004052 return 0x13;
4053
4054 return conn->disc_reason;
4055}
4056
4057static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058{
4059 BT_DBG("hcon %p reason %d", hcon, reason);
4060
Ville Tervoacd7d372011-02-10 22:38:49 -03004061 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004062 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063
Joe Perchese1750722011-06-29 18:18:29 -07004064 l2cap_conn_del(hcon, bt_to_errno(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004065
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066 return 0;
4067}
4068
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004069static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004070{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004071 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004072 return;
4073
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004074 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004075 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004076 __clear_chan_timer(chan);
4077 __set_chan_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004078 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004079 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004080 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004081 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004082 __clear_chan_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004083 }
4084}
4085
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004086static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004088 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004089 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090
Marcel Holtmann01394182006-07-03 10:02:46 +02004091 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004093
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094 BT_DBG("conn %p", conn);
4095
Vinicius Costa Gomes160dc6a2011-08-19 21:06:55 -03004096 if (hcon->type == LE_LINK) {
4097 smp_distribute_keys(conn, 0);
4098 del_timer(&conn->security_timer);
4099 }
4100
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004101 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004103 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004104 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004105
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106 bh_lock_sock(sk);
4107
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -03004108 BT_DBG("chan->scid %d", chan->scid);
4109
4110 if (chan->scid == L2CAP_CID_LE_DATA) {
4111 if (!status && encrypt) {
4112 chan->sec_level = hcon->sec_level;
4113 l2cap_chan_ready(sk);
4114 }
4115
4116 bh_unlock_sock(sk);
4117 continue;
4118 }
4119
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004120 if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004121 bh_unlock_sock(sk);
4122 continue;
4123 }
4124
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004125 if (!status && (chan->state == BT_CONNECTED ||
4126 chan->state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004127 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004128 bh_unlock_sock(sk);
4129 continue;
4130 }
4131
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004132 if (chan->state == BT_CONNECT) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004133 if (!status) {
4134 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004135 req.scid = cpu_to_le16(chan->scid);
4136 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004137
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004138 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanc1360a12011-06-10 17:02:12 -03004139 set_bit(CONF_CONNECT_PEND, &chan->conf_state);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004140
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004141 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004142 L2CAP_CONN_REQ, sizeof(req), &req);
4143 } else {
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004144 __clear_chan_timer(chan);
4145 __set_chan_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004146 }
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004147 } else if (chan->state == BT_CONNECT2) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004148 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004149 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004150
4151 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004152 if (bt_sk(sk)->defer_setup) {
4153 struct sock *parent = bt_sk(sk)->parent;
4154 res = L2CAP_CR_PEND;
4155 stat = L2CAP_CS_AUTHOR_PEND;
Ilia Kolomisnky05e9a2f2011-07-15 18:30:21 +00004156 if (parent)
4157 parent->sk_data_ready(parent, 0);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004158 } else {
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004159 l2cap_state_change(chan, BT_CONFIG);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004160 res = L2CAP_CR_SUCCESS;
4161 stat = L2CAP_CS_NO_INFO;
4162 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004163 } else {
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004164 l2cap_state_change(chan, BT_DISCONN);
Gustavo F. Padovanc9b66672011-05-17 14:59:01 -03004165 __set_chan_timer(chan, HZ / 10);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004166 res = L2CAP_CR_SEC_BLOCK;
4167 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004168 }
4169
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004170 rsp.scid = cpu_to_le16(chan->dcid);
4171 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004172 rsp.result = cpu_to_le16(res);
4173 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004174 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4175 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176 }
4177
Linus Torvalds1da177e2005-04-16 15:20:36 -07004178 bh_unlock_sock(sk);
4179 }
4180
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004181 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004182
Linus Torvalds1da177e2005-04-16 15:20:36 -07004183 return 0;
4184}
4185
4186static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4187{
4188 struct l2cap_conn *conn = hcon->l2cap_data;
4189
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004190 if (!conn)
4191 conn = l2cap_conn_add(hcon, 0);
4192
4193 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004194 goto drop;
4195
4196 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4197
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004198 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004200 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004201 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202 int len;
4203
4204 if (conn->rx_len) {
4205 BT_ERR("Unexpected start frame (len %d)", skb->len);
4206 kfree_skb(conn->rx_skb);
4207 conn->rx_skb = NULL;
4208 conn->rx_len = 0;
4209 l2cap_conn_unreliable(conn, ECOMM);
4210 }
4211
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004212 /* Start fragment always begin with Basic L2CAP header */
4213 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214 BT_ERR("Frame is too short (len %d)", skb->len);
4215 l2cap_conn_unreliable(conn, ECOMM);
4216 goto drop;
4217 }
4218
4219 hdr = (struct l2cap_hdr *) skb->data;
4220 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004221 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222
4223 if (len == skb->len) {
4224 /* Complete frame received */
4225 l2cap_recv_frame(conn, skb);
4226 return 0;
4227 }
4228
4229 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4230
4231 if (skb->len > len) {
4232 BT_ERR("Frame is too long (len %d, expected len %d)",
4233 skb->len, len);
4234 l2cap_conn_unreliable(conn, ECOMM);
4235 goto drop;
4236 }
4237
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004238 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004239
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004240 if (chan && chan->sk) {
4241 struct sock *sk = chan->sk;
4242
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004243 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004244 BT_ERR("Frame exceeding recv MTU (len %d, "
4245 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004246 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004247 bh_unlock_sock(sk);
4248 l2cap_conn_unreliable(conn, ECOMM);
4249 goto drop;
4250 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004251 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004252 }
4253
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004255 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4256 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257 goto drop;
4258
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004259 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004260 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004261 conn->rx_len = len - skb->len;
4262 } else {
4263 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4264
4265 if (!conn->rx_len) {
4266 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4267 l2cap_conn_unreliable(conn, ECOMM);
4268 goto drop;
4269 }
4270
4271 if (skb->len > conn->rx_len) {
4272 BT_ERR("Fragment is too long (len %d, expected %d)",
4273 skb->len, conn->rx_len);
4274 kfree_skb(conn->rx_skb);
4275 conn->rx_skb = NULL;
4276 conn->rx_len = 0;
4277 l2cap_conn_unreliable(conn, ECOMM);
4278 goto drop;
4279 }
4280
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004281 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004282 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283 conn->rx_len -= skb->len;
4284
4285 if (!conn->rx_len) {
4286 /* Complete frame received */
4287 l2cap_recv_frame(conn, conn->rx_skb);
4288 conn->rx_skb = NULL;
4289 }
4290 }
4291
4292drop:
4293 kfree_skb(skb);
4294 return 0;
4295}
4296
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004297static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004298{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004299 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004301 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004302
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004303 list_for_each_entry(c, &chan_list, global_l) {
4304 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004306 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 +01004307 batostr(&bt_sk(sk)->src),
4308 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan89bc5002011-06-03 00:19:47 -03004309 c->state, __le16_to_cpu(c->psm),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004310 c->scid, c->dcid, c->imtu, c->omtu,
4311 c->sec_level, c->mode);
Gustavo F. Padovan05558912011-06-21 14:52:56 -03004312}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004313
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004314 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004315
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004316 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317}
4318
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004319static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4320{
4321 return single_open(file, l2cap_debugfs_show, inode->i_private);
4322}
4323
4324static const struct file_operations l2cap_debugfs_fops = {
4325 .open = l2cap_debugfs_open,
4326 .read = seq_read,
4327 .llseek = seq_lseek,
4328 .release = single_release,
4329};
4330
4331static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333static struct hci_proto l2cap_hci_proto = {
4334 .name = "L2CAP",
4335 .id = HCI_PROTO_L2CAP,
4336 .connect_ind = l2cap_connect_ind,
4337 .connect_cfm = l2cap_connect_cfm,
4338 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004339 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004340 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341 .recv_acldata = l2cap_recv_acldata
4342};
4343
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004344int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345{
4346 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004347
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004348 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349 if (err < 0)
4350 return err;
4351
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352 err = hci_register_proto(&l2cap_hci_proto);
4353 if (err < 0) {
4354 BT_ERR("L2CAP protocol registration failed");
4355 bt_sock_unregister(BTPROTO_L2CAP);
4356 goto error;
4357 }
4358
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004359 if (bt_debugfs) {
4360 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4361 bt_debugfs, NULL, &l2cap_debugfs_fops);
4362 if (!l2cap_debugfs)
4363 BT_ERR("Failed to create L2CAP debug file");
4364 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365
Linus Torvalds1da177e2005-04-16 15:20:36 -07004366 return 0;
4367
4368error:
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004369 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004370 return err;
4371}
4372
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004373void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004375 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4378 BT_ERR("L2CAP protocol unregistration failed");
4379
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004380 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004381}
4382
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004383module_param(disable_ertm, bool, 0644);
4384MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Andrei Emeltchenkoa5fd6f32011-09-16 16:26:32 +03004385
4386module_param(enable_hs, bool, 0644);
4387MODULE_PARM_DESC(enable_hs, "Enable High Speed");