blob: 56fdd9162da929fcacd0b31cd5e537c71a421c4b [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. Padovanaf05b302009-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>
57
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020058int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020059
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070060static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010061static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030063static struct workqueue_struct *_busy_wq;
64
Gustavo F. Padovan23691d72011-04-27 18:26:32 -030065LIST_HEAD(chan_list);
66DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030068static void l2cap_busy_work(struct work_struct *work);
69
Linus Torvalds1da177e2005-04-16 15:20:36 -070070static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
71 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030072static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070073
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030074static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
75
Marcel Holtmann01394182006-07-03 10:02:46 +020076/* ---- L2CAP channels ---- */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030077static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020078{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030079 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030080
81 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030082 if (c->dcid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030083 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020084 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030085 return NULL;
86
Marcel Holtmann01394182006-07-03 10:02:46 +020087}
88
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030089static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020090{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030091 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030092
93 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030094 if (c->scid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030095 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020096 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030097 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +020098}
99
100/* Find channel with given SCID.
101 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300102static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200103{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300104 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300105
106 read_lock(&conn->chan_lock);
107 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300108 if (c)
109 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300110 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300111 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200112}
113
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300114static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200115{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300116 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300117
118 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300119 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300120 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200121 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300122 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200123}
124
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300125static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200126{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300127 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300128
129 read_lock(&conn->chan_lock);
130 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300131 if (c)
132 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300133 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300134 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200135}
136
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300137static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300138{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300139 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300140
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300141 list_for_each_entry(c, &chan_list, global_l) {
142 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300143 goto found;
144 }
145
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300146 c = NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300147found:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300148 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300149}
150
151int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
152{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300153 int err;
154
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300155 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300156
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300157 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300158 err = -EADDRINUSE;
159 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300160 }
161
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300162 if (psm) {
163 chan->psm = psm;
164 chan->sport = psm;
165 err = 0;
166 } else {
167 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300168
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300169 err = -EINVAL;
170 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300171 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300172 chan->psm = cpu_to_le16(p);
173 chan->sport = cpu_to_le16(p);
174 err = 0;
175 break;
176 }
177 }
178
179done:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300180 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300181 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300182}
183
184int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
185{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300186 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300187
188 chan->scid = scid;
189
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300190 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300191
192 return 0;
193}
194
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300195static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200196{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300197 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200198
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300199 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300200 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200201 return cid;
202 }
203
204 return 0;
205}
206
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300207struct l2cap_chan *l2cap_chan_create(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200208{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300209 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200210
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300211 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
212 if (!chan)
213 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200214
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300215 chan->sk = sk;
216
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300217 write_lock_bh(&chan_list_lock);
218 list_add(&chan->global_l, &chan_list);
219 write_unlock_bh(&chan_list_lock);
220
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300221 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200222}
223
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300224void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300225{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300226 write_lock_bh(&chan_list_lock);
227 list_del(&chan->global_l);
228 write_unlock_bh(&chan_list_lock);
229
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300230 kfree(chan);
231}
232
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300233static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200234{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300235 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200236
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300237 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300238 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200239
Marcel Holtmann2950f212009-02-12 14:02:50 +0100240 conn->disc_reason = 0x13;
241
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300242 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200243
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300244 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Ville Tervob62f3282011-02-10 22:38:50 -0300245 if (conn->hcon->type == LE_LINK) {
246 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300247 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300248 chan->scid = L2CAP_CID_LE_DATA;
249 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300250 } else {
251 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300252 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300253 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300254 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200255 } else if (sk->sk_type == SOCK_DGRAM) {
256 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300257 chan->scid = L2CAP_CID_CONN_LESS;
258 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300259 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200260 } else {
261 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300262 chan->scid = L2CAP_CID_SIGNALING;
263 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300264 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200265 }
266
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300267 sock_hold(sk);
268
269 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200270}
271
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900272/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200273 * Must be called on the locked socket. */
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300274void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200275{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300276 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300277 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200278 struct sock *parent = bt_sk(sk)->parent;
279
280 l2cap_sock_clear_timer(sk);
281
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300282 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200283
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900284 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300285 /* Delete from channel list */
286 write_lock_bh(&conn->chan_lock);
287 list_del(&chan->list);
288 write_unlock_bh(&conn->chan_lock);
289 __sock_put(sk);
290
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300291 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200292 hci_conn_put(conn->hcon);
293 }
294
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200295 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200296 sock_set_flag(sk, SOCK_ZAPPED);
297
298 if (err)
299 sk->sk_err = err;
300
301 if (parent) {
302 bt_accept_unlink(sk);
303 parent->sk_data_ready(parent, 0);
304 } else
305 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300306
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300307 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE &&
308 chan->conf_state & L2CAP_CONF_INPUT_DONE))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300309 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300310
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300311 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300312
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300313 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300314 struct srej_list *l, *tmp;
315
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300316 del_timer(&chan->retrans_timer);
317 del_timer(&chan->monitor_timer);
318 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300319
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300320 skb_queue_purge(&chan->srej_q);
321 skb_queue_purge(&chan->busy_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300322
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300323 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300324 list_del(&l->list);
325 kfree(l);
326 }
327 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200328}
329
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300330static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530331{
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300332 struct sock *sk = chan->sk;
333
Johan Hedberg8556edd32011-01-19 12:06:50 +0530334 if (sk->sk_type == SOCK_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300335 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530336 case BT_SECURITY_HIGH:
337 return HCI_AT_DEDICATED_BONDING_MITM;
338 case BT_SECURITY_MEDIUM:
339 return HCI_AT_DEDICATED_BONDING;
340 default:
341 return HCI_AT_NO_BONDING;
342 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300343 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300344 if (chan->sec_level == BT_SECURITY_LOW)
345 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530346
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300347 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530348 return HCI_AT_NO_BONDING_MITM;
349 else
350 return HCI_AT_NO_BONDING;
351 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300352 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530353 case BT_SECURITY_HIGH:
354 return HCI_AT_GENERAL_BONDING_MITM;
355 case BT_SECURITY_MEDIUM:
356 return HCI_AT_GENERAL_BONDING;
357 default:
358 return HCI_AT_NO_BONDING;
359 }
360 }
361}
362
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200363/* Service level security */
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300364static inline int l2cap_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200365{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300366 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100367 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200368
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300369 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100370
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300371 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200372}
373
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200374u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200375{
376 u8 id;
377
378 /* Get next available identificator.
379 * 1 - 128 are used by kernel.
380 * 129 - 199 are reserved.
381 * 200 - 254 are used by utilities like l2ping, etc.
382 */
383
384 spin_lock_bh(&conn->lock);
385
386 if (++conn->tx_ident > 128)
387 conn->tx_ident = 1;
388
389 id = conn->tx_ident;
390
391 spin_unlock_bh(&conn->lock);
392
393 return id;
394}
395
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200396void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200397{
398 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200399 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200400
401 BT_DBG("code 0x%2.2x", code);
402
403 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300404 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200405
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200406 if (lmp_no_flush_capable(conn->hcon->hdev))
407 flags = ACL_START_NO_FLUSH;
408 else
409 flags = ACL_START;
410
411 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200412}
413
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300414static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300415{
416 struct sk_buff *skb;
417 struct l2cap_hdr *lh;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300418 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300419 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300420 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300421 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200422 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300423
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300424 if (sk->sk_state != BT_CONNECTED)
425 return;
426
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300427 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300428 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300429
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300430 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300431
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300432 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300433 control |= L2CAP_CTRL_FRAME_TYPE;
434
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300435 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300436 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300437 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300438 }
439
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300440 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300441 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300442 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300443 }
444
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300445 skb = bt_skb_alloc(count, GFP_ATOMIC);
446 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300447 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300448
449 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300450 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300451 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300452 put_unaligned_le16(control, skb_put(skb, 2));
453
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300454 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300455 u16 fcs = crc16(0, (u8 *)lh, count - 2);
456 put_unaligned_le16(fcs, skb_put(skb, 2));
457 }
458
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200459 if (lmp_no_flush_capable(conn->hcon->hdev))
460 flags = ACL_START_NO_FLUSH;
461 else
462 flags = ACL_START;
463
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300464 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300465}
466
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300467static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300468{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300469 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300470 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300471 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300472 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300473 control |= L2CAP_SUPER_RCV_READY;
474
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300475 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300476
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300477 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300478}
479
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300480static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300481{
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300482 return !(chan->conf_state & L2CAP_CONF_CONNECT_PEND);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300483}
484
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300485static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200486{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300487 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200488
489 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100490 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
491 return;
492
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300493 if (l2cap_check_security(chan) &&
494 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200495 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300496 req.scid = cpu_to_le16(chan->scid);
497 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200498
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300499 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300500 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200501
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300502 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
503 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200504 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200505 } else {
506 struct l2cap_info_req req;
507 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
508
509 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
510 conn->info_ident = l2cap_get_ident(conn);
511
512 mod_timer(&conn->info_timer, jiffies +
513 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
514
515 l2cap_send_cmd(conn, conn->info_ident,
516 L2CAP_INFO_REQ, sizeof(req), &req);
517 }
518}
519
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300520static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
521{
522 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300523 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300524 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
525
526 switch (mode) {
527 case L2CAP_MODE_ERTM:
528 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
529 case L2CAP_MODE_STREAMING:
530 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
531 default:
532 return 0x00;
533 }
534}
535
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300536void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300537{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300538 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300539 struct l2cap_disconn_req req;
540
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300541 if (!conn)
542 return;
543
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300544 sk = chan->sk;
545
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300546 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300547 del_timer(&chan->retrans_timer);
548 del_timer(&chan->monitor_timer);
549 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300550 }
551
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300552 req.dcid = cpu_to_le16(chan->dcid);
553 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300554 l2cap_send_cmd(conn, l2cap_get_ident(conn),
555 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300556
557 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300558 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300559}
560
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200562static void l2cap_conn_start(struct l2cap_conn *conn)
563{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300564 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200565
566 BT_DBG("conn %p", conn);
567
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300568 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200569
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300570 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300571 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300572
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200573 bh_lock_sock(sk);
574
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300575 if (sk->sk_type != SOCK_SEQPACKET &&
576 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200577 bh_unlock_sock(sk);
578 continue;
579 }
580
581 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300582 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300583
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300584 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300585 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300586 bh_unlock_sock(sk);
587 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200588 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300589
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300590 if (!l2cap_mode_supported(chan->mode,
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300591 conn->feat_mask)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300592 && chan->conf_state &
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300593 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300594 /* __l2cap_sock_close() calls list_del(chan)
595 * so release the lock */
596 read_unlock_bh(&conn->chan_lock);
597 __l2cap_sock_close(sk, ECONNRESET);
598 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300599 bh_unlock_sock(sk);
600 continue;
601 }
602
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300603 req.scid = cpu_to_le16(chan->scid);
604 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300605
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300606 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300607 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300608
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300609 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
610 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300611
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200612 } else if (sk->sk_state == BT_CONNECT2) {
613 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300614 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300615 rsp.scid = cpu_to_le16(chan->dcid);
616 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200617
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300618 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100619 if (bt_sk(sk)->defer_setup) {
620 struct sock *parent = bt_sk(sk)->parent;
621 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
622 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
623 parent->sk_data_ready(parent, 0);
624
625 } else {
626 sk->sk_state = BT_CONFIG;
627 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
628 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
629 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200630 } else {
631 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
632 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
633 }
634
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300635 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
636 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300637
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300638 if (chan->conf_state & L2CAP_CONF_REQ_SENT ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300639 rsp.result != L2CAP_CR_SUCCESS) {
640 bh_unlock_sock(sk);
641 continue;
642 }
643
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300644 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300645 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300646 l2cap_build_conf_req(chan, buf), buf);
647 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200648 }
649
650 bh_unlock_sock(sk);
651 }
652
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300653 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200654}
655
Ville Tervob62f3282011-02-10 22:38:50 -0300656/* Find socket with cid and source bdaddr.
657 * Returns closest match, locked.
658 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300659static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300660{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300661 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300662
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300663 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300664
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300665 list_for_each_entry(c, &chan_list, global_l) {
666 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300667
Ville Tervob62f3282011-02-10 22:38:50 -0300668 if (state && sk->sk_state != state)
669 continue;
670
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300671 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300672 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300673 if (!bacmp(&bt_sk(sk)->src, src)) {
674 read_unlock(&chan_list_lock);
675 return c;
676 }
Ville Tervob62f3282011-02-10 22:38:50 -0300677
678 /* Closest match */
679 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300680 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300681 }
682 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300683
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300684 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300685
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300686 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300687}
688
689static void l2cap_le_conn_ready(struct l2cap_conn *conn)
690{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300691 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300692 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300693
694 BT_DBG("");
695
696 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300697 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300698 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300699 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300700 return;
701
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300702 parent = pchan->sk;
703
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300704 bh_lock_sock(parent);
705
Ville Tervob62f3282011-02-10 22:38:50 -0300706 /* Check for backlog size */
707 if (sk_acceptq_is_full(parent)) {
708 BT_DBG("backlog full %d", parent->sk_ack_backlog);
709 goto clean;
710 }
711
712 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
713 if (!sk)
714 goto clean;
715
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300716 chan = l2cap_chan_create(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300717 if (!chan) {
718 l2cap_sock_kill(sk);
719 goto clean;
720 }
721
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300722 l2cap_pi(sk)->chan = chan;
723
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300724 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300725
726 hci_conn_hold(conn->hcon);
727
728 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300729
Ville Tervob62f3282011-02-10 22:38:50 -0300730 bacpy(&bt_sk(sk)->src, conn->src);
731 bacpy(&bt_sk(sk)->dst, conn->dst);
732
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300733 bt_accept_enqueue(parent, sk);
734
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300735 __l2cap_chan_add(conn, chan);
736
Ville Tervob62f3282011-02-10 22:38:50 -0300737 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
738
739 sk->sk_state = BT_CONNECTED;
740 parent->sk_data_ready(parent, 0);
741
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300742 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300743
744clean:
745 bh_unlock_sock(parent);
746}
747
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200748static void l2cap_conn_ready(struct l2cap_conn *conn)
749{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300750 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200751
752 BT_DBG("conn %p", conn);
753
Ville Tervob62f3282011-02-10 22:38:50 -0300754 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
755 l2cap_le_conn_ready(conn);
756
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300757 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200758
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300759 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300760 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300761
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200762 bh_lock_sock(sk);
763
Ville Tervoacd7d372011-02-10 22:38:49 -0300764 if (conn->hcon->type == LE_LINK) {
765 l2cap_sock_clear_timer(sk);
766 sk->sk_state = BT_CONNECTED;
767 sk->sk_state_change(sk);
768 }
769
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300770 if (sk->sk_type != SOCK_SEQPACKET &&
771 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200772 l2cap_sock_clear_timer(sk);
773 sk->sk_state = BT_CONNECTED;
774 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200775 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300776 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200777
778 bh_unlock_sock(sk);
779 }
780
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300781 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200782}
783
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200784/* Notify sockets that we cannot guaranty reliability anymore */
785static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
786{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300787 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200788
789 BT_DBG("conn %p", conn);
790
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300791 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200792
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300793 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300794 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300795
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300796 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200797 sk->sk_err = err;
798 }
799
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300800 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200801}
802
803static void l2cap_info_timeout(unsigned long arg)
804{
805 struct l2cap_conn *conn = (void *) arg;
806
Marcel Holtmann984947d2009-02-06 23:35:19 +0100807 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100808 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100809
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200810 l2cap_conn_start(conn);
811}
812
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
814{
Marcel Holtmann01394182006-07-03 10:02:46 +0200815 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816
Marcel Holtmann01394182006-07-03 10:02:46 +0200817 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 return conn;
819
Marcel Holtmann01394182006-07-03 10:02:46 +0200820 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
821 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823
824 hcon->l2cap_data = conn;
825 conn->hcon = hcon;
826
Marcel Holtmann01394182006-07-03 10:02:46 +0200827 BT_DBG("hcon %p conn %p", hcon, conn);
828
Ville Tervoacd7d372011-02-10 22:38:49 -0300829 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
830 conn->mtu = hcon->hdev->le_mtu;
831 else
832 conn->mtu = hcon->hdev->acl_mtu;
833
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 conn->src = &hcon->hdev->bdaddr;
835 conn->dst = &hcon->dst;
836
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200837 conn->feat_mask = 0;
838
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300840 rwlock_init(&conn->chan_lock);
841
842 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843
Ville Tervob62f3282011-02-10 22:38:50 -0300844 if (hcon->type != LE_LINK)
845 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000846 (unsigned long) conn);
847
Marcel Holtmann2950f212009-02-12 14:02:50 +0100848 conn->disc_reason = 0x13;
849
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 return conn;
851}
852
Marcel Holtmann01394182006-07-03 10:02:46 +0200853static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854{
Marcel Holtmann01394182006-07-03 10:02:46 +0200855 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300856 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 struct sock *sk;
858
Marcel Holtmann01394182006-07-03 10:02:46 +0200859 if (!conn)
860 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861
862 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
863
Wei Yongjun7585b972009-02-25 18:29:52 +0800864 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865
866 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300867 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300868 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300870 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 bh_unlock_sock(sk);
872 l2cap_sock_kill(sk);
873 }
874
Dave Young8e8440f2008-03-03 12:18:55 -0800875 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
876 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800877
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 hcon->l2cap_data = NULL;
879 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880}
881
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300882static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300884 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300885 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300886 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887}
888
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890
891/* Find socket with psm and source bdaddr.
892 * Returns closest match.
893 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300894static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300896 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300898 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000899
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300900 list_for_each_entry(c, &chan_list, global_l) {
901 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300902
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 if (state && sk->sk_state != state)
904 continue;
905
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300906 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300908 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +0200909 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300910 return c;
911 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912
913 /* Closest match */
914 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300915 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 }
917 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300919 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000920
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300921 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922}
923
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -0300924int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300926 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 bdaddr_t *src = &bt_sk(sk)->src;
928 bdaddr_t *dst = &bt_sk(sk)->dst;
929 struct l2cap_conn *conn;
930 struct hci_conn *hcon;
931 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200932 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200933 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100935 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300936 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -0300938 hdev = hci_get_route(dst, src);
939 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 return -EHOSTUNREACH;
941
942 hci_dev_lock_bh(hdev);
943
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300944 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200945
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300946 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -0300947 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300948 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300949 else
950 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300951 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300952
Ville Tervo30e76272011-02-22 16:10:53 -0300953 if (IS_ERR(hcon)) {
954 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300956 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957
958 conn = l2cap_conn_add(hcon, 0);
959 if (!conn) {
960 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300961 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 goto done;
963 }
964
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 /* Update source addr of the socket */
966 bacpy(src, conn->src);
967
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300968 l2cap_chan_add(conn, chan);
969
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 sk->sk_state = BT_CONNECT;
971 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
972
973 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300974 if (sk->sk_type != SOCK_SEQPACKET &&
975 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 l2cap_sock_clear_timer(sk);
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300977 if (l2cap_check_security(chan))
Johan Hedbergd00ef242011-01-19 12:06:51 +0530978 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200979 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300980 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 }
982
Ville Tervo30e76272011-02-22 16:10:53 -0300983 err = 0;
984
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985done:
986 hci_dev_unlock_bh(hdev);
987 hci_dev_put(hdev);
988 return err;
989}
990
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200991int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300992{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300993 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300994 DECLARE_WAITQUEUE(wait, current);
995 int err = 0;
996 int timeo = HZ/5;
997
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200998 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300999 while ((chan->unacked_frames > 0 && chan->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001000 set_current_state(TASK_INTERRUPTIBLE);
1001
1002 if (!timeo)
1003 timeo = HZ/5;
1004
1005 if (signal_pending(current)) {
1006 err = sock_intr_errno(timeo);
1007 break;
1008 }
1009
1010 release_sock(sk);
1011 timeo = schedule_timeout(timeo);
1012 lock_sock(sk);
1013
1014 err = sock_error(sk);
1015 if (err)
1016 break;
1017 }
1018 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001019 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001020 return err;
1021}
1022
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001023static void l2cap_monitor_timeout(unsigned long arg)
1024{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001025 struct l2cap_chan *chan = (void *) arg;
1026 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001027
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001028 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001029
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001030 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001031 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001032 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001033 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001034 return;
1035 }
1036
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001037 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001038 __mod_monitor_timer();
1039
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001040 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001041 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001042}
1043
1044static void l2cap_retrans_timeout(unsigned long arg)
1045{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001046 struct l2cap_chan *chan = (void *) arg;
1047 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001048
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001049 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001050
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001051 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001052 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001053 __mod_monitor_timer();
1054
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001055 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001056
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001057 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001058 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001059}
1060
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001061static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001062{
1063 struct sk_buff *skb;
1064
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001065 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001066 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001067 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001068 break;
1069
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001070 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001071 kfree_skb(skb);
1072
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001073 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001074 }
1075
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001076 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001077 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001078}
1079
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001080void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001081{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001082 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001083 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001084
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001085 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001086
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001087 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001088 flags = ACL_START_NO_FLUSH;
1089 else
1090 flags = ACL_START;
1091
1092 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001093}
1094
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001095void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001096{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001097 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001098 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001099
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001100 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001101 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001102 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001103 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001104
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001105 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001106 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1107 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001108 }
1109
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001110 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001111
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001112 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001113 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001114}
1115
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001116static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001117{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001118 struct sk_buff *skb, *tx_skb;
1119 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001120
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001121 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001122 if (!skb)
1123 return;
1124
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001125 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001126 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001127 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001128
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001129 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001130 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001131
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001132 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001133
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001134 if (chan->remote_max_tx &&
1135 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001136 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001137 return;
1138 }
1139
1140 tx_skb = skb_clone(skb, GFP_ATOMIC);
1141 bt_cb(skb)->retries++;
1142 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001143 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001144
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001145 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001146 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001147 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001148 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001149
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001150 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001151 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001152
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001153 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1154
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001155 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001156 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1157 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1158 }
1159
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001160 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001161}
1162
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001163int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001164{
1165 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001166 struct sock *sk = chan->sk;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001167 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001168 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001169
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001170 if (sk->sk_state != BT_CONNECTED)
1171 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001172
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001173 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001174
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001175 if (chan->remote_max_tx &&
1176 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001177 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001178 break;
1179 }
1180
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001181 tx_skb = skb_clone(skb, GFP_ATOMIC);
1182
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001183 bt_cb(skb)->retries++;
1184
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001185 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001186 control &= L2CAP_CTRL_SAR;
1187
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001188 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001189 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001190 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001191 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001192 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1193 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001194 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1195
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001196
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001197 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001198 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1199 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1200 }
1201
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001202 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001203
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001204 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001205
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001206 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1207 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001208
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301209 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001210 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301211
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001212 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001213
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001214 if (skb_queue_is_last(&chan->tx_q, skb))
1215 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001216 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001217 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001218
1219 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001220 }
1221
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001222 return nsent;
1223}
1224
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001225static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001226{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001227 int ret;
1228
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001229 if (!skb_queue_empty(&chan->tx_q))
1230 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001231
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001232 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001233 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001234 return ret;
1235}
1236
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001237static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001238{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001239 u16 control = 0;
1240
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001241 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001242
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001243 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001244 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001245 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1246 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001247 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001248 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001249
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001250 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001251 return;
1252
1253 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001254 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001255}
1256
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001257static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001258{
1259 struct srej_list *tail;
1260 u16 control;
1261
1262 control = L2CAP_SUPER_SELECT_REJECT;
1263 control |= L2CAP_CTRL_FINAL;
1264
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001265 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001266 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1267
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001268 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001269}
1270
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001271static 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 -07001272{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001273 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001274 struct sk_buff **frag;
1275 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001277 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001278 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279
1280 sent += count;
1281 len -= count;
1282
1283 /* Continuation fragments (no L2CAP header) */
1284 frag = &skb_shinfo(skb)->frag_list;
1285 while (len) {
1286 count = min_t(unsigned int, conn->mtu, len);
1287
1288 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1289 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001290 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001291 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1292 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293
1294 sent += count;
1295 len -= count;
1296
1297 frag = &(*frag)->next;
1298 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299
1300 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001301}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001303struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001304{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001305 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001306 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001307 struct sk_buff *skb;
1308 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1309 struct l2cap_hdr *lh;
1310
1311 BT_DBG("sk %p len %d", sk, (int)len);
1312
1313 count = min_t(unsigned int, (conn->mtu - hlen), len);
1314 skb = bt_skb_send_alloc(sk, count + hlen,
1315 msg->msg_flags & MSG_DONTWAIT, &err);
1316 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001317 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001318
1319 /* Create L2CAP header */
1320 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001321 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001322 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001323 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001324
1325 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1326 if (unlikely(err < 0)) {
1327 kfree_skb(skb);
1328 return ERR_PTR(err);
1329 }
1330 return skb;
1331}
1332
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001333struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001334{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001335 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001336 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001337 struct sk_buff *skb;
1338 int err, count, hlen = L2CAP_HDR_SIZE;
1339 struct l2cap_hdr *lh;
1340
1341 BT_DBG("sk %p len %d", sk, (int)len);
1342
1343 count = min_t(unsigned int, (conn->mtu - hlen), len);
1344 skb = bt_skb_send_alloc(sk, count + hlen,
1345 msg->msg_flags & MSG_DONTWAIT, &err);
1346 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001347 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001348
1349 /* Create L2CAP header */
1350 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001351 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001352 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1353
1354 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1355 if (unlikely(err < 0)) {
1356 kfree_skb(skb);
1357 return ERR_PTR(err);
1358 }
1359 return skb;
1360}
1361
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001362struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001363{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001364 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001365 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001366 struct sk_buff *skb;
1367 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1368 struct l2cap_hdr *lh;
1369
1370 BT_DBG("sk %p len %d", sk, (int)len);
1371
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001372 if (!conn)
1373 return ERR_PTR(-ENOTCONN);
1374
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001375 if (sdulen)
1376 hlen += 2;
1377
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001378 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001379 hlen += 2;
1380
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001381 count = min_t(unsigned int, (conn->mtu - hlen), len);
1382 skb = bt_skb_send_alloc(sk, count + hlen,
1383 msg->msg_flags & MSG_DONTWAIT, &err);
1384 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001385 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001386
1387 /* Create L2CAP header */
1388 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001389 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001390 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1391 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001392 if (sdulen)
1393 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001394
1395 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1396 if (unlikely(err < 0)) {
1397 kfree_skb(skb);
1398 return ERR_PTR(err);
1399 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001400
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001401 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001402 put_unaligned_le16(0, skb_put(skb, 2));
1403
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001404 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001405 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406}
1407
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001408int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001409{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001410 struct sk_buff *skb;
1411 struct sk_buff_head sar_queue;
1412 u16 control;
1413 size_t size = 0;
1414
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001415 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001416 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001417 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001418 if (IS_ERR(skb))
1419 return PTR_ERR(skb);
1420
1421 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001422 len -= chan->remote_mps;
1423 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001424
1425 while (len > 0) {
1426 size_t buflen;
1427
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001428 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001429 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001430 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001431 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001432 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001433 buflen = len;
1434 }
1435
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001436 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001437 if (IS_ERR(skb)) {
1438 skb_queue_purge(&sar_queue);
1439 return PTR_ERR(skb);
1440 }
1441
1442 __skb_queue_tail(&sar_queue, skb);
1443 len -= buflen;
1444 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001445 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001446 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1447 if (chan->tx_send_head == NULL)
1448 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001449
1450 return size;
1451}
1452
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453static void l2cap_chan_ready(struct sock *sk)
1454{
1455 struct sock *parent = bt_sk(sk)->parent;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001456 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457
1458 BT_DBG("sk %p, parent %p", sk, parent);
1459
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001460 chan->conf_state = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 l2cap_sock_clear_timer(sk);
1462
1463 if (!parent) {
1464 /* Outgoing channel.
1465 * Wake up socket sleeping on connect.
1466 */
1467 sk->sk_state = BT_CONNECTED;
1468 sk->sk_state_change(sk);
1469 } else {
1470 /* Incoming channel.
1471 * Wake up socket sleeping on accept.
1472 */
1473 parent->sk_data_ready(parent, 0);
1474 }
1475}
1476
1477/* Copy frame to all raw sockets on that connection */
1478static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1479{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001481 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482
1483 BT_DBG("conn %p", conn);
1484
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001485 read_lock(&conn->chan_lock);
1486 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001487 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 if (sk->sk_type != SOCK_RAW)
1489 continue;
1490
1491 /* Don't send frame to the socket it came from */
1492 if (skb->sk == sk)
1493 continue;
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001494 nskb = skb_clone(skb, GFP_ATOMIC);
1495 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 continue;
1497
1498 if (sock_queue_rcv_skb(sk, nskb))
1499 kfree_skb(nskb);
1500 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001501 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502}
1503
1504/* ---- L2CAP signalling commands ---- */
1505static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1506 u8 code, u8 ident, u16 dlen, void *data)
1507{
1508 struct sk_buff *skb, **frag;
1509 struct l2cap_cmd_hdr *cmd;
1510 struct l2cap_hdr *lh;
1511 int len, count;
1512
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001513 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1514 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515
1516 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1517 count = min_t(unsigned int, conn->mtu, len);
1518
1519 skb = bt_skb_alloc(count, GFP_ATOMIC);
1520 if (!skb)
1521 return NULL;
1522
1523 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001524 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001525
1526 if (conn->hcon->type == LE_LINK)
1527 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1528 else
1529 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530
1531 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1532 cmd->code = code;
1533 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001534 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535
1536 if (dlen) {
1537 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1538 memcpy(skb_put(skb, count), data, count);
1539 data += count;
1540 }
1541
1542 len -= skb->len;
1543
1544 /* Continuation fragments (no L2CAP header) */
1545 frag = &skb_shinfo(skb)->frag_list;
1546 while (len) {
1547 count = min_t(unsigned int, conn->mtu, len);
1548
1549 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1550 if (!*frag)
1551 goto fail;
1552
1553 memcpy(skb_put(*frag, count), data, count);
1554
1555 len -= count;
1556 data += count;
1557
1558 frag = &(*frag)->next;
1559 }
1560
1561 return skb;
1562
1563fail:
1564 kfree_skb(skb);
1565 return NULL;
1566}
1567
1568static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1569{
1570 struct l2cap_conf_opt *opt = *ptr;
1571 int len;
1572
1573 len = L2CAP_CONF_OPT_SIZE + opt->len;
1574 *ptr += len;
1575
1576 *type = opt->type;
1577 *olen = opt->len;
1578
1579 switch (opt->len) {
1580 case 1:
1581 *val = *((u8 *) opt->val);
1582 break;
1583
1584 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001585 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 break;
1587
1588 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001589 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 break;
1591
1592 default:
1593 *val = (unsigned long) opt->val;
1594 break;
1595 }
1596
1597 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1598 return len;
1599}
1600
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1602{
1603 struct l2cap_conf_opt *opt = *ptr;
1604
1605 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1606
1607 opt->type = type;
1608 opt->len = len;
1609
1610 switch (len) {
1611 case 1:
1612 *((u8 *) opt->val) = val;
1613 break;
1614
1615 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001616 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 break;
1618
1619 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001620 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621 break;
1622
1623 default:
1624 memcpy(opt->val, (void *) val, len);
1625 break;
1626 }
1627
1628 *ptr += L2CAP_CONF_OPT_SIZE + len;
1629}
1630
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001631static void l2cap_ack_timeout(unsigned long arg)
1632{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001633 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001634
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001635 bh_lock_sock(chan->sk);
1636 l2cap_send_ack(chan);
1637 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001638}
1639
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001640static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001641{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001642 struct sock *sk = chan->sk;
1643
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001644 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001645 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001646 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001647 chan->num_acked = 0;
1648 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001649
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001650 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1651 (unsigned long) chan);
1652 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1653 (unsigned long) chan);
1654 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001655
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001656 skb_queue_head_init(&chan->srej_q);
1657 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001658
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001659 INIT_LIST_HEAD(&chan->srej_l);
1660
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001661 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001662
1663 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001664}
1665
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001666static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1667{
1668 switch (mode) {
1669 case L2CAP_MODE_STREAMING:
1670 case L2CAP_MODE_ERTM:
1671 if (l2cap_mode_supported(mode, remote_feat_mask))
1672 return mode;
1673 /* fall through */
1674 default:
1675 return L2CAP_MODE_BASIC;
1676 }
1677}
1678
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001679static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001682 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683 void *ptr = req->data;
1684
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001685 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001687 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001688 goto done;
1689
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001690 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001691 case L2CAP_MODE_STREAMING:
1692 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001693 if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001694 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001695
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001696 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001697 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001698 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001699 break;
1700 }
1701
1702done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001703 if (chan->imtu != L2CAP_DEFAULT_MTU)
1704 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan79906812011-01-24 16:01:43 -02001705
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001706 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001707 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001708 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1709 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001710 break;
1711
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001712 rfc.mode = L2CAP_MODE_BASIC;
1713 rfc.txwin_size = 0;
1714 rfc.max_transmit = 0;
1715 rfc.retrans_timeout = 0;
1716 rfc.monitor_timeout = 0;
1717 rfc.max_pdu_size = 0;
1718
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001719 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1720 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001721 break;
1722
1723 case L2CAP_MODE_ERTM:
1724 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001725 rfc.txwin_size = chan->tx_win;
1726 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001727 rfc.retrans_timeout = 0;
1728 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001729 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001730 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1731 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001732
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001733 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1734 (unsigned long) &rfc);
1735
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001736 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001737 break;
1738
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001739 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001740 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001741 chan->fcs = L2CAP_FCS_NONE;
1742 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001743 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001744 break;
1745
1746 case L2CAP_MODE_STREAMING:
1747 rfc.mode = L2CAP_MODE_STREAMING;
1748 rfc.txwin_size = 0;
1749 rfc.max_transmit = 0;
1750 rfc.retrans_timeout = 0;
1751 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001752 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001753 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1754 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001755
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001756 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1757 (unsigned long) &rfc);
1758
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001759 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001760 break;
1761
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001762 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001763 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001764 chan->fcs = L2CAP_FCS_NONE;
1765 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001766 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001767 break;
1768 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001770 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001771 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772
1773 return ptr - data;
1774}
1775
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001776static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001778 struct l2cap_conf_rsp *rsp = data;
1779 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001780 void *req = chan->conf_req;
1781 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001782 int type, hint, olen;
1783 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001784 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001785 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001786 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001788 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001789
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001790 while (len >= L2CAP_CONF_OPT_SIZE) {
1791 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001793 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001794 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001795
1796 switch (type) {
1797 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001798 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001799 break;
1800
1801 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001802 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001803 break;
1804
1805 case L2CAP_CONF_QOS:
1806 break;
1807
Marcel Holtmann6464f352007-10-20 13:39:51 +02001808 case L2CAP_CONF_RFC:
1809 if (olen == sizeof(rfc))
1810 memcpy(&rfc, (void *) val, olen);
1811 break;
1812
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001813 case L2CAP_CONF_FCS:
1814 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001815 chan->conf_state |= L2CAP_CONF_NO_FCS_RECV;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001816
1817 break;
1818
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001819 default:
1820 if (hint)
1821 break;
1822
1823 result = L2CAP_CONF_UNKNOWN;
1824 *((u8 *) ptr++) = type;
1825 break;
1826 }
1827 }
1828
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001829 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001830 goto done;
1831
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001832 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001833 case L2CAP_MODE_STREAMING:
1834 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001835 if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001836 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001837 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001838 break;
1839 }
1840
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001841 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001842 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001843
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001844 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001845 }
1846
1847done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001848 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001849 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001850 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001851
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001852 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001853 return -ECONNREFUSED;
1854
1855 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1856 sizeof(rfc), (unsigned long) &rfc);
1857 }
1858
1859
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001860 if (result == L2CAP_CONF_SUCCESS) {
1861 /* Configure output options and let the other side know
1862 * which ones we don't like. */
1863
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001864 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1865 result = L2CAP_CONF_UNACCEPT;
1866 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001867 chan->omtu = mtu;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001868 chan->conf_state |= L2CAP_CONF_MTU_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001869 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001870 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001871
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001872 switch (rfc.mode) {
1873 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001874 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001875 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001876 break;
1877
1878 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001879 chan->remote_tx_win = rfc.txwin_size;
1880 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001881
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001882 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
1883 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001884
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001885 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001886
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001887 rfc.retrans_timeout =
1888 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1889 rfc.monitor_timeout =
1890 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001891
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001892 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001893
1894 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1895 sizeof(rfc), (unsigned long) &rfc);
1896
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001897 break;
1898
1899 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001900 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
1901 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001902
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001903 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001904
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001905 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001906
1907 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1908 sizeof(rfc), (unsigned long) &rfc);
1909
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001910 break;
1911
1912 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001913 result = L2CAP_CONF_UNACCEPT;
1914
1915 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001916 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001917 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001918
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001919 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001920 chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001921 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001922 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001923 rsp->result = cpu_to_le16(result);
1924 rsp->flags = cpu_to_le16(0x0000);
1925
1926 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927}
1928
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001929static 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 -03001930{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001931 struct l2cap_conf_req *req = data;
1932 void *ptr = req->data;
1933 int type, olen;
1934 unsigned long val;
1935 struct l2cap_conf_rfc rfc;
1936
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001937 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001938
1939 while (len >= L2CAP_CONF_OPT_SIZE) {
1940 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1941
1942 switch (type) {
1943 case L2CAP_CONF_MTU:
1944 if (val < L2CAP_DEFAULT_MIN_MTU) {
1945 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001946 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001947 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001948 chan->imtu = val;
1949 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001950 break;
1951
1952 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001953 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001954 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001955 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001956 break;
1957
1958 case L2CAP_CONF_RFC:
1959 if (olen == sizeof(rfc))
1960 memcpy(&rfc, (void *)val, olen);
1961
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001962 if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001963 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001964 return -ECONNREFUSED;
1965
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001966 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001967
1968 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1969 sizeof(rfc), (unsigned long) &rfc);
1970 break;
1971 }
1972 }
1973
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001974 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001975 return -ECONNREFUSED;
1976
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001977 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001978
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001979 if (*result == L2CAP_CONF_SUCCESS) {
1980 switch (rfc.mode) {
1981 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001982 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1983 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
1984 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001985 break;
1986 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001987 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001988 }
1989 }
1990
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001991 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001992 req->flags = cpu_to_le16(0x0000);
1993
1994 return ptr - data;
1995}
1996
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001997static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998{
1999 struct l2cap_conf_rsp *rsp = data;
2000 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002002 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002004 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002005 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002006 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007
2008 return ptr - data;
2009}
2010
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002011void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002012{
2013 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002014 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002015 u8 buf[128];
2016
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002017 rsp.scid = cpu_to_le16(chan->dcid);
2018 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002019 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2020 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2021 l2cap_send_cmd(conn, chan->ident,
2022 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2023
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002024 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002025 return;
2026
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002027 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002028 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2029 l2cap_build_conf_req(chan, buf), buf);
2030 chan->num_conf_req++;
2031}
2032
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002033static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002034{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002035 int type, olen;
2036 unsigned long val;
2037 struct l2cap_conf_rfc rfc;
2038
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002039 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002040
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002041 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002042 return;
2043
2044 while (len >= L2CAP_CONF_OPT_SIZE) {
2045 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2046
2047 switch (type) {
2048 case L2CAP_CONF_RFC:
2049 if (olen == sizeof(rfc))
2050 memcpy(&rfc, (void *)val, olen);
2051 goto done;
2052 }
2053 }
2054
2055done:
2056 switch (rfc.mode) {
2057 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002058 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2059 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2060 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002061 break;
2062 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002063 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002064 }
2065}
2066
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002067static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2068{
2069 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2070
2071 if (rej->reason != 0x0000)
2072 return 0;
2073
2074 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2075 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002076 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002077
2078 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002079 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002080
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002081 l2cap_conn_start(conn);
2082 }
2083
2084 return 0;
2085}
2086
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2088{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2090 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002091 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002092 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002093 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094
2095 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002096 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097
2098 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2099
2100 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002101 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2102 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 result = L2CAP_CR_BAD_PSM;
2104 goto sendresp;
2105 }
2106
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002107 parent = pchan->sk;
2108
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002109 bh_lock_sock(parent);
2110
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002111 /* Check if the ACL is secure enough (if not SDP) */
2112 if (psm != cpu_to_le16(0x0001) &&
2113 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002114 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002115 result = L2CAP_CR_SEC_BLOCK;
2116 goto response;
2117 }
2118
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 result = L2CAP_CR_NO_MEM;
2120
2121 /* Check for backlog size */
2122 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002123 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 goto response;
2125 }
2126
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002127 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 if (!sk)
2129 goto response;
2130
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002131 chan = l2cap_chan_create(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002132 if (!chan) {
2133 l2cap_sock_kill(sk);
2134 goto response;
2135 }
2136
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03002137 l2cap_pi(sk)->chan = chan;
2138
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002139 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140
2141 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002142 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2143 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 sock_set_flag(sk, SOCK_ZAPPED);
2145 l2cap_sock_kill(sk);
2146 goto response;
2147 }
2148
2149 hci_conn_hold(conn->hcon);
2150
2151 l2cap_sock_init(sk, parent);
2152 bacpy(&bt_sk(sk)->src, conn->src);
2153 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002154 chan->psm = psm;
2155 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002157 bt_accept_enqueue(parent, sk);
2158
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002159 __l2cap_chan_add(conn, chan);
2160
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002161 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162
2163 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2164
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002165 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166
Marcel Holtmann984947d2009-02-06 23:35:19 +01002167 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002168 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002169 if (bt_sk(sk)->defer_setup) {
2170 sk->sk_state = BT_CONNECT2;
2171 result = L2CAP_CR_PEND;
2172 status = L2CAP_CS_AUTHOR_PEND;
2173 parent->sk_data_ready(parent, 0);
2174 } else {
2175 sk->sk_state = BT_CONFIG;
2176 result = L2CAP_CR_SUCCESS;
2177 status = L2CAP_CS_NO_INFO;
2178 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002179 } else {
2180 sk->sk_state = BT_CONNECT2;
2181 result = L2CAP_CR_PEND;
2182 status = L2CAP_CS_AUTHEN_PEND;
2183 }
2184 } else {
2185 sk->sk_state = BT_CONNECT2;
2186 result = L2CAP_CR_PEND;
2187 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 }
2189
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002190 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191
2192response:
2193 bh_unlock_sock(parent);
2194
2195sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002196 rsp.scid = cpu_to_le16(scid);
2197 rsp.dcid = cpu_to_le16(dcid);
2198 rsp.result = cpu_to_le16(result);
2199 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002201
2202 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2203 struct l2cap_info_req info;
2204 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2205
2206 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2207 conn->info_ident = l2cap_get_ident(conn);
2208
2209 mod_timer(&conn->info_timer, jiffies +
2210 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2211
2212 l2cap_send_cmd(conn, conn->info_ident,
2213 L2CAP_INFO_REQ, sizeof(info), &info);
2214 }
2215
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002216 if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002217 result == L2CAP_CR_SUCCESS) {
2218 u8 buf[128];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002219 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002220 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002221 l2cap_build_conf_req(chan, buf), buf);
2222 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002223 }
2224
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 return 0;
2226}
2227
2228static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2229{
2230 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2231 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002232 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 struct sock *sk;
2234 u8 req[128];
2235
2236 scid = __le16_to_cpu(rsp->scid);
2237 dcid = __le16_to_cpu(rsp->dcid);
2238 result = __le16_to_cpu(rsp->result);
2239 status = __le16_to_cpu(rsp->status);
2240
2241 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2242
2243 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002244 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002245 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002246 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002248 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002249 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002250 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251 }
2252
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002253 sk = chan->sk;
2254
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255 switch (result) {
2256 case L2CAP_CR_SUCCESS:
2257 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002258 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002259 chan->dcid = dcid;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002260 chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002261
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002262 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002263 break;
2264
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002265 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002266
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002268 l2cap_build_conf_req(chan, req), req);
2269 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 break;
2271
2272 case L2CAP_CR_PEND:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002273 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274 break;
2275
2276 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002277 /* don't delete l2cap channel if sk is owned by user */
2278 if (sock_owned_by_user(sk)) {
2279 sk->sk_state = BT_DISCONN;
2280 l2cap_sock_clear_timer(sk);
2281 l2cap_sock_set_timer(sk, HZ / 5);
2282 break;
2283 }
2284
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002285 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286 break;
2287 }
2288
2289 bh_unlock_sock(sk);
2290 return 0;
2291}
2292
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002293static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002294{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002295 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
2296
Mat Martineau8c462b62010-08-24 15:35:42 -07002297 /* FCS is enabled only in ERTM or streaming mode, if one or both
2298 * sides request it.
2299 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002300 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002301 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002302 else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002303 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002304}
2305
Al Viro88219a02007-07-29 00:17:25 -07002306static 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 -07002307{
2308 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2309 u16 dcid, flags;
2310 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002311 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002313 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314
2315 dcid = __le16_to_cpu(req->dcid);
2316 flags = __le16_to_cpu(req->flags);
2317
2318 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2319
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002320 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002321 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 return -ENOENT;
2323
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002324 sk = chan->sk;
2325
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002326 if (sk->sk_state != BT_CONFIG) {
2327 struct l2cap_cmd_rej rej;
2328
2329 rej.reason = cpu_to_le16(0x0002);
2330 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2331 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002332 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002333 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002334
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002335 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002336 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002337 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002338 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002339 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002340 L2CAP_CONF_REJECT, flags), rsp);
2341 goto unlock;
2342 }
2343
2344 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002345 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2346 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347
2348 if (flags & 0x0001) {
2349 /* Incomplete config. Send empty response. */
2350 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002351 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002352 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353 goto unlock;
2354 }
2355
2356 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002357 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002358 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002359 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002361 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002363 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002364 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002365
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002366 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002367 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002368
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002369 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002370 goto unlock;
2371
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002372 if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002373 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002374
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002376
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002377 chan->next_tx_seq = 0;
2378 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002379 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002380 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002381 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002382
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002384 goto unlock;
2385 }
2386
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002387 if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002388 u8 buf[64];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002389 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002391 l2cap_build_conf_req(chan, buf), buf);
2392 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393 }
2394
2395unlock:
2396 bh_unlock_sock(sk);
2397 return 0;
2398}
2399
2400static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2401{
2402 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2403 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002404 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002406 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407
2408 scid = __le16_to_cpu(rsp->scid);
2409 flags = __le16_to_cpu(rsp->flags);
2410 result = __le16_to_cpu(rsp->result);
2411
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002412 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2413 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002415 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002416 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 return 0;
2418
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002419 sk = chan->sk;
2420
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 switch (result) {
2422 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002423 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 break;
2425
2426 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002427 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002428 char req[64];
2429
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002430 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002431 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002432 goto done;
2433 }
2434
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002435 /* throw out any old stored conf requests */
2436 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002437 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2438 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002439 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002440 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002441 goto done;
2442 }
2443
2444 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2445 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002446 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002447 if (result != L2CAP_CONF_SUCCESS)
2448 goto done;
2449 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450 }
2451
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002452 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002453 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002455 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456 goto done;
2457 }
2458
2459 if (flags & 0x01)
2460 goto done;
2461
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002462 chan->conf_state |= L2CAP_CONF_INPUT_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002464 if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002465 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002466
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002468 chan->next_tx_seq = 0;
2469 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002470 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002471 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002472 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002473
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 l2cap_chan_ready(sk);
2475 }
2476
2477done:
2478 bh_unlock_sock(sk);
2479 return 0;
2480}
2481
2482static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2483{
2484 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2485 struct l2cap_disconn_rsp rsp;
2486 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002487 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 struct sock *sk;
2489
2490 scid = __le16_to_cpu(req->scid);
2491 dcid = __le16_to_cpu(req->dcid);
2492
2493 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2494
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002495 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002496 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 return 0;
2498
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002499 sk = chan->sk;
2500
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002501 rsp.dcid = cpu_to_le16(chan->scid);
2502 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2504
2505 sk->sk_shutdown = SHUTDOWN_MASK;
2506
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002507 /* don't delete l2cap channel if sk is owned by user */
2508 if (sock_owned_by_user(sk)) {
2509 sk->sk_state = BT_DISCONN;
2510 l2cap_sock_clear_timer(sk);
2511 l2cap_sock_set_timer(sk, HZ / 5);
2512 bh_unlock_sock(sk);
2513 return 0;
2514 }
2515
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002516 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 bh_unlock_sock(sk);
2518
2519 l2cap_sock_kill(sk);
2520 return 0;
2521}
2522
2523static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2524{
2525 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2526 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002527 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528 struct sock *sk;
2529
2530 scid = __le16_to_cpu(rsp->scid);
2531 dcid = __le16_to_cpu(rsp->dcid);
2532
2533 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2534
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002535 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002536 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537 return 0;
2538
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002539 sk = chan->sk;
2540
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002541 /* don't delete l2cap channel if sk is owned by user */
2542 if (sock_owned_by_user(sk)) {
2543 sk->sk_state = BT_DISCONN;
2544 l2cap_sock_clear_timer(sk);
2545 l2cap_sock_set_timer(sk, HZ / 5);
2546 bh_unlock_sock(sk);
2547 return 0;
2548 }
2549
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002550 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551 bh_unlock_sock(sk);
2552
2553 l2cap_sock_kill(sk);
2554 return 0;
2555}
2556
2557static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2558{
2559 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 u16 type;
2561
2562 type = __le16_to_cpu(req->type);
2563
2564 BT_DBG("type 0x%4.4x", type);
2565
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002566 if (type == L2CAP_IT_FEAT_MASK) {
2567 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002568 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002569 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2570 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2571 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002572 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002573 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2574 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002575 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002576 l2cap_send_cmd(conn, cmd->ident,
2577 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002578 } else if (type == L2CAP_IT_FIXED_CHAN) {
2579 u8 buf[12];
2580 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2581 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2582 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2583 memcpy(buf + 4, l2cap_fixed_chan, 8);
2584 l2cap_send_cmd(conn, cmd->ident,
2585 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002586 } else {
2587 struct l2cap_info_rsp rsp;
2588 rsp.type = cpu_to_le16(type);
2589 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2590 l2cap_send_cmd(conn, cmd->ident,
2591 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2592 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593
2594 return 0;
2595}
2596
2597static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2598{
2599 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2600 u16 type, result;
2601
2602 type = __le16_to_cpu(rsp->type);
2603 result = __le16_to_cpu(rsp->result);
2604
2605 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2606
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002607 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2608 if (cmd->ident != conn->info_ident ||
2609 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2610 return 0;
2611
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002612 del_timer(&conn->info_timer);
2613
Ville Tervoadb08ed2010-08-04 09:43:33 +03002614 if (result != L2CAP_IR_SUCCESS) {
2615 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2616 conn->info_ident = 0;
2617
2618 l2cap_conn_start(conn);
2619
2620 return 0;
2621 }
2622
Marcel Holtmann984947d2009-02-06 23:35:19 +01002623 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002624 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002625
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002626 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002627 struct l2cap_info_req req;
2628 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2629
2630 conn->info_ident = l2cap_get_ident(conn);
2631
2632 l2cap_send_cmd(conn, conn->info_ident,
2633 L2CAP_INFO_REQ, sizeof(req), &req);
2634 } else {
2635 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2636 conn->info_ident = 0;
2637
2638 l2cap_conn_start(conn);
2639 }
2640 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002641 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002642 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002643
2644 l2cap_conn_start(conn);
2645 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002646
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647 return 0;
2648}
2649
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002650static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002651 u16 to_multiplier)
2652{
2653 u16 max_latency;
2654
2655 if (min > max || min < 6 || max > 3200)
2656 return -EINVAL;
2657
2658 if (to_multiplier < 10 || to_multiplier > 3200)
2659 return -EINVAL;
2660
2661 if (max >= to_multiplier * 8)
2662 return -EINVAL;
2663
2664 max_latency = (to_multiplier * 8 / max) - 1;
2665 if (latency > 499 || latency > max_latency)
2666 return -EINVAL;
2667
2668 return 0;
2669}
2670
2671static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2672 struct l2cap_cmd_hdr *cmd, u8 *data)
2673{
2674 struct hci_conn *hcon = conn->hcon;
2675 struct l2cap_conn_param_update_req *req;
2676 struct l2cap_conn_param_update_rsp rsp;
2677 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002678 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002679
2680 if (!(hcon->link_mode & HCI_LM_MASTER))
2681 return -EINVAL;
2682
2683 cmd_len = __le16_to_cpu(cmd->len);
2684 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2685 return -EPROTO;
2686
2687 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002688 min = __le16_to_cpu(req->min);
2689 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002690 latency = __le16_to_cpu(req->latency);
2691 to_multiplier = __le16_to_cpu(req->to_multiplier);
2692
2693 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2694 min, max, latency, to_multiplier);
2695
2696 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002697
2698 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2699 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002700 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2701 else
2702 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2703
2704 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2705 sizeof(rsp), &rsp);
2706
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002707 if (!err)
2708 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2709
Claudio Takahaside731152011-02-11 19:28:55 -02002710 return 0;
2711}
2712
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002713static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2714 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2715{
2716 int err = 0;
2717
2718 switch (cmd->code) {
2719 case L2CAP_COMMAND_REJ:
2720 l2cap_command_rej(conn, cmd, data);
2721 break;
2722
2723 case L2CAP_CONN_REQ:
2724 err = l2cap_connect_req(conn, cmd, data);
2725 break;
2726
2727 case L2CAP_CONN_RSP:
2728 err = l2cap_connect_rsp(conn, cmd, data);
2729 break;
2730
2731 case L2CAP_CONF_REQ:
2732 err = l2cap_config_req(conn, cmd, cmd_len, data);
2733 break;
2734
2735 case L2CAP_CONF_RSP:
2736 err = l2cap_config_rsp(conn, cmd, data);
2737 break;
2738
2739 case L2CAP_DISCONN_REQ:
2740 err = l2cap_disconnect_req(conn, cmd, data);
2741 break;
2742
2743 case L2CAP_DISCONN_RSP:
2744 err = l2cap_disconnect_rsp(conn, cmd, data);
2745 break;
2746
2747 case L2CAP_ECHO_REQ:
2748 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2749 break;
2750
2751 case L2CAP_ECHO_RSP:
2752 break;
2753
2754 case L2CAP_INFO_REQ:
2755 err = l2cap_information_req(conn, cmd, data);
2756 break;
2757
2758 case L2CAP_INFO_RSP:
2759 err = l2cap_information_rsp(conn, cmd, data);
2760 break;
2761
2762 default:
2763 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2764 err = -EINVAL;
2765 break;
2766 }
2767
2768 return err;
2769}
2770
2771static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2772 struct l2cap_cmd_hdr *cmd, u8 *data)
2773{
2774 switch (cmd->code) {
2775 case L2CAP_COMMAND_REJ:
2776 return 0;
2777
2778 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002779 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002780
2781 case L2CAP_CONN_PARAM_UPDATE_RSP:
2782 return 0;
2783
2784 default:
2785 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2786 return -EINVAL;
2787 }
2788}
2789
2790static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2791 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792{
2793 u8 *data = skb->data;
2794 int len = skb->len;
2795 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002796 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797
2798 l2cap_raw_recv(conn, skb);
2799
2800 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002801 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2803 data += L2CAP_CMD_HDR_SIZE;
2804 len -= L2CAP_CMD_HDR_SIZE;
2805
Al Viro88219a02007-07-29 00:17:25 -07002806 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807
Al Viro88219a02007-07-29 00:17:25 -07002808 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 -07002809
Al Viro88219a02007-07-29 00:17:25 -07002810 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811 BT_DBG("corrupted command");
2812 break;
2813 }
2814
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002815 if (conn->hcon->type == LE_LINK)
2816 err = l2cap_le_sig_cmd(conn, &cmd, data);
2817 else
2818 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819
2820 if (err) {
2821 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002822
2823 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824
2825 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002826 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002827 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2828 }
2829
Al Viro88219a02007-07-29 00:17:25 -07002830 data += cmd_len;
2831 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832 }
2833
2834 kfree_skb(skb);
2835}
2836
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002837static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002838{
2839 u16 our_fcs, rcv_fcs;
2840 int hdr_size = L2CAP_HDR_SIZE + 2;
2841
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002842 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002843 skb_trim(skb, skb->len - 2);
2844 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2845 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2846
2847 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002848 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002849 }
2850 return 0;
2851}
2852
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002853static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002854{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002855 u16 control = 0;
2856
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002857 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002858
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002859 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002860
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002861 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002862 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002863 l2cap_send_sframe(chan, control);
2864 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002865 }
2866
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002867 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2868 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002869
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002870 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002871
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002872 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002873 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002874 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002875 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002876 }
2877}
2878
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002879static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u8 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002880{
2881 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002882 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002883
2884 bt_cb(skb)->tx_seq = tx_seq;
2885 bt_cb(skb)->sar = sar;
2886
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002887 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002888 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002889 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002890 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002891 }
2892
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002893 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002894 if (tx_seq_offset < 0)
2895 tx_seq_offset += 64;
2896
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002897 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002898 if (bt_cb(next_skb)->tx_seq == tx_seq)
2899 return -EINVAL;
2900
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002901 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002902 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002903 if (next_tx_seq_offset < 0)
2904 next_tx_seq_offset += 64;
2905
2906 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002907 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002908 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002909 }
2910
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002911 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002912 break;
2913
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002914 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002915
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002916 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002917
2918 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002919}
2920
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002921static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002922{
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002923 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002924 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002925
2926 switch (control & L2CAP_CTRL_SAR) {
2927 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002928 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002929 goto drop;
2930
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002931 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002932 if (!err)
2933 return err;
2934
2935 break;
2936
2937 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002938 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002939 goto drop;
2940
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002941 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002942
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002943 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002944 goto disconnect;
2945
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002946 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
2947 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002948 return -ENOMEM;
2949
2950 /* pull sdu_len bytes only after alloc, because of Local Busy
2951 * condition we have to be sure that this will be executed
2952 * only once, i.e., when alloc does not fail */
2953 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002954
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002955 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002956
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002957 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002958 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002959 break;
2960
2961 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002962 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002963 goto disconnect;
2964
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002965 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002966 goto disconnect;
2967
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002968 chan->partial_sdu_len += skb->len;
2969 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002970 goto drop;
2971
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002972 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002973
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002974 break;
2975
2976 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002977 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002978 goto disconnect;
2979
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002980 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002981 goto disconnect;
2982
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002983 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002984 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002985
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002986 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002987 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002988
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002989 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002990 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002991
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002992 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002993 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002994
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03002995 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002996 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002997 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002998 return -ENOMEM;
2999 }
3000
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003001 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003002 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003003 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003004 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003005 return err;
3006 }
3007
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003008 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
3009 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003010
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003011 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003012 break;
3013 }
3014
3015 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003016 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003017
3018drop:
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003019 kfree_skb(chan->sdu);
3020 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003021
3022disconnect:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003023 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003024 kfree_skb(skb);
3025 return 0;
3026}
3027
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003028static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003029{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003030 struct sk_buff *skb;
3031 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003032 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003033
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003034 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003035 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003036 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003037 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003038 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003039 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003040 }
3041
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003042 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003043 }
3044
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003045 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003046 goto done;
3047
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003048 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003049 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003050 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003051 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003052
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003053 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003054 __mod_monitor_timer();
3055
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003056 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003057
3058done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003059 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3060 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003061
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003062 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003063
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003064 return 0;
3065}
3066
3067static void l2cap_busy_work(struct work_struct *work)
3068{
3069 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003070 struct l2cap_chan *chan =
3071 container_of(work, struct l2cap_chan, busy_work);
3072 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003073 int n_tries = 0, timeo = HZ/5, err;
3074 struct sk_buff *skb;
3075
3076 lock_sock(sk);
3077
3078 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003079 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003080 set_current_state(TASK_INTERRUPTIBLE);
3081
3082 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3083 err = -EBUSY;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003084 l2cap_send_disconn_req(chan->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003085 break;
3086 }
3087
3088 if (!timeo)
3089 timeo = HZ/5;
3090
3091 if (signal_pending(current)) {
3092 err = sock_intr_errno(timeo);
3093 break;
3094 }
3095
3096 release_sock(sk);
3097 timeo = schedule_timeout(timeo);
3098 lock_sock(sk);
3099
3100 err = sock_error(sk);
3101 if (err)
3102 break;
3103
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003104 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003105 break;
3106 }
3107
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003108 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003109 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003110
3111 release_sock(sk);
3112}
3113
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003114static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003115{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003116 int sctrl, err;
3117
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003118 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003119 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003120 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003121 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003122
3123
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003124 }
3125
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003126 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003127 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003128 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003129 return err;
3130 }
3131
3132 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003133 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003134
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003135 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003136 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003137 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003138
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003139 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003140 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003141 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003142
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003143 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003144
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003145 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003146
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003147 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003148
3149 return err;
3150}
3151
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003152static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003153{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003154 struct sk_buff *_skb;
3155 int err = -EINVAL;
3156
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003157 /*
3158 * TODO: We have to notify the userland if some data is lost with the
3159 * Streaming Mode.
3160 */
3161
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003162 switch (control & L2CAP_CTRL_SAR) {
3163 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003164 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003165 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003166 break;
3167 }
3168
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003169 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003170 if (!err)
3171 return 0;
3172
3173 break;
3174
3175 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003176 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003177 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003178 break;
3179 }
3180
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003181 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003182 skb_pull(skb, 2);
3183
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003184 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003185 err = -EMSGSIZE;
3186 break;
3187 }
3188
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003189 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3190 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003191 err = -ENOMEM;
3192 break;
3193 }
3194
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003195 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003196
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003197 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003198 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003199 err = 0;
3200 break;
3201
3202 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003203 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003204 break;
3205
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003206 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003207
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003208 chan->partial_sdu_len += skb->len;
3209 if (chan->partial_sdu_len > chan->sdu_len)
3210 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003211 else
3212 err = 0;
3213
3214 break;
3215
3216 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003217 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003218 break;
3219
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003220 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003221
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003222 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003223 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003224
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003225 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003226 goto drop;
3227
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003228 if (chan->partial_sdu_len == chan->sdu_len) {
3229 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003230 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003231 if (err < 0)
3232 kfree_skb(_skb);
3233 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003234 err = 0;
3235
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003236drop:
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003237 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003238 break;
3239 }
3240
3241 kfree_skb(skb);
3242 return err;
3243}
3244
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003245static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003246{
3247 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003248 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003249
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003250 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003251 if (bt_cb(skb)->tx_seq != tx_seq)
3252 break;
3253
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003254 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003255 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003256 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003257 chan->buffer_seq_srej =
3258 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003259 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003260 }
3261}
3262
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003263static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003264{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003265 struct srej_list *l, *tmp;
3266 u16 control;
3267
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003268 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003269 if (l->tx_seq == tx_seq) {
3270 list_del(&l->list);
3271 kfree(l);
3272 return;
3273 }
3274 control = L2CAP_SUPER_SELECT_REJECT;
3275 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003276 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003277 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003278 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003279 }
3280}
3281
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003282static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003283{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003284 struct srej_list *new;
3285 u16 control;
3286
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003287 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003288 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003289 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003290 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003291
3292 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003293 new->tx_seq = chan->expected_tx_seq;
3294 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003295 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003296 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003297 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003298}
3299
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003300static 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 -03003301{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003302 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003303 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003304 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003305 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003306 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003307 int err = 0;
3308
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003309 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3310 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003311
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003312 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003313 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003314 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003315 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003316 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003317 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003318 }
3319
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003320 chan->expected_ack_seq = req_seq;
3321 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003322
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003323 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003324 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003325
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003326 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003327 if (tx_seq_offset < 0)
3328 tx_seq_offset += 64;
3329
3330 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003331 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003332 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003333 goto drop;
3334 }
3335
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003336 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003337 goto drop;
3338
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003339 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003340 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003341
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003342 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003343 struct srej_list, list);
3344 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003345 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003346 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003347
3348 list_del(&first->list);
3349 kfree(first);
3350
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003351 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003352 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003353 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3354 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003355 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003356 }
3357 } else {
3358 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003359
3360 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003361 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003362 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003363
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003364 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003365 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003366 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003367 return 0;
3368 }
3369 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003370 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003371 }
3372 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003373 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003374 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003375 if (expected_tx_seq_offset < 0)
3376 expected_tx_seq_offset += 64;
3377
3378 /* duplicated tx_seq */
3379 if (tx_seq_offset < expected_tx_seq_offset)
3380 goto drop;
3381
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003382 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003383
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003384 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003385
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003386 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003387 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003388
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003389 __skb_queue_head_init(&chan->srej_q);
3390 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003391 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003392
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003393 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003394
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003395 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003396
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003397 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003398 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003399 return 0;
3400
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003401expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003402 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003403
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003404 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003405 bt_cb(skb)->tx_seq = tx_seq;
3406 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003407 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003408 return 0;
3409 }
3410
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003411 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003412 if (err < 0)
3413 return 0;
3414
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003415 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003416 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3417 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003418 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003419 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003420 }
3421
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003422 __mod_ack_timer();
3423
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003424 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3425 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003426 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003427
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003428 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003429
3430drop:
3431 kfree_skb(skb);
3432 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003433}
3434
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003435static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003436{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003437 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003438 rx_control);
3439
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003440 chan->expected_ack_seq = __get_reqseq(rx_control);
3441 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003442
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003443 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003444 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3445 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3446 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003447 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003448 __mod_retrans_timer();
3449
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003450 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3451 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003452 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003453 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003454 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003455
3456 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003457 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003458
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003459 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3460 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003461 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003462 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003463
3464 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003465 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003466 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003467 __mod_retrans_timer();
3468
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003469 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3470 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3471 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003472 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003473 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003474 }
3475}
3476
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003477static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003478{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003479 u8 tx_seq = __get_reqseq(rx_control);
3480
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003481 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003482
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003483 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003484
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003485 chan->expected_ack_seq = tx_seq;
3486 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003487
3488 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003489 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3490 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003491 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003492 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003493 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003494 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003495
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003496 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3497 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003498 }
3499}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003500static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003501{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003502 u8 tx_seq = __get_reqseq(rx_control);
3503
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003504 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003505
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003506 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003507
3508 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003509 chan->expected_ack_seq = tx_seq;
3510 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003511
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003512 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3513 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003514
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003515 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003516
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003517 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003518 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003519 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003520 }
3521 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003522 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003523 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003524 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003525 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003526 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003527 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003528 l2cap_retransmit_one_frame(chan, tx_seq);
3529 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003530 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003531 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003532 }
3533 }
3534}
3535
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003536static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003537{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003538 u8 tx_seq = __get_reqseq(rx_control);
3539
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003540 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003541
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003542 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003543 chan->expected_ack_seq = tx_seq;
3544 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003545
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003546 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003547 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003548
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003549 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003550 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003551 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003552 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003553 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003554 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003555
3556 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003557 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003558 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003559 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003560}
3561
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003562static 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 -03003563{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003564 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003565
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003566 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003567 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003568 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003569 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003570 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003571 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003572 }
3573
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003574 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3575 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003576 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003577 break;
3578
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003579 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003580 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003581 break;
3582
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003583 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003584 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003585 break;
3586
3587 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003588 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003589 break;
3590 }
3591
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003592 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003593 return 0;
3594}
3595
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003596static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3597{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003598 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003599 u16 control;
3600 u8 req_seq;
3601 int len, next_tx_seq_offset, req_seq_offset;
3602
3603 control = get_unaligned_le16(skb->data);
3604 skb_pull(skb, 2);
3605 len = skb->len;
3606
3607 /*
3608 * We can just drop the corrupted I-frame here.
3609 * Receiver will miss it and start proper recovery
3610 * procedures and ask retransmission.
3611 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003612 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003613 goto drop;
3614
3615 if (__is_sar_start(control) && __is_iframe(control))
3616 len -= 2;
3617
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003618 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003619 len -= 2;
3620
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003621 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003622 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003623 goto drop;
3624 }
3625
3626 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003627 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003628 if (req_seq_offset < 0)
3629 req_seq_offset += 64;
3630
3631 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003632 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003633 if (next_tx_seq_offset < 0)
3634 next_tx_seq_offset += 64;
3635
3636 /* check for invalid req-seq */
3637 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003638 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003639 goto drop;
3640 }
3641
3642 if (__is_iframe(control)) {
3643 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003644 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003645 goto drop;
3646 }
3647
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003648 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003649 } else {
3650 if (len != 0) {
3651 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003652 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003653 goto drop;
3654 }
3655
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003656 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003657 }
3658
3659 return 0;
3660
3661drop:
3662 kfree_skb(skb);
3663 return 0;
3664}
3665
Linus Torvalds1da177e2005-04-16 15:20:36 -07003666static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3667{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003668 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003669 struct sock *sk = NULL;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003670 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003671 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003672 u8 tx_seq;
3673 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003675 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003676 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677 BT_DBG("unknown cid 0x%4.4x", cid);
3678 goto drop;
3679 }
3680
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003681 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003682 pi = l2cap_pi(sk);
3683
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003684 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685
3686 if (sk->sk_state != BT_CONNECTED)
3687 goto drop;
3688
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003689 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003690 case L2CAP_MODE_BASIC:
3691 /* If socket recv buffers overflows we drop data here
3692 * which is *bad* because L2CAP has to be reliable.
3693 * But we don't have any other choice. L2CAP doesn't
3694 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003695
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003696 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003697 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003699 if (!sock_queue_rcv_skb(sk, skb))
3700 goto done;
3701 break;
3702
3703 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003704 if (!sock_owned_by_user(sk)) {
3705 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003706 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003707 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003708 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003709 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003710
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003711 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003712
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003713 case L2CAP_MODE_STREAMING:
3714 control = get_unaligned_le16(skb->data);
3715 skb_pull(skb, 2);
3716 len = skb->len;
3717
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003718 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003719 goto drop;
3720
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003721 if (__is_sar_start(control))
3722 len -= 2;
3723
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003724 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003725 len -= 2;
3726
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003727 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003728 goto drop;
3729
3730 tx_seq = __get_txseq(control);
3731
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003732 if (chan->expected_tx_seq == tx_seq)
3733 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003734 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003735 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003736
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003737 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003738
3739 goto done;
3740
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003741 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003742 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003743 break;
3744 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003745
3746drop:
3747 kfree_skb(skb);
3748
3749done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003750 if (sk)
3751 bh_unlock_sock(sk);
3752
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753 return 0;
3754}
3755
Al Viro8e036fc2007-07-29 00:16:36 -07003756static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003757{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003758 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003759 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003761 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3762 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763 goto drop;
3764
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003765 sk = chan->sk;
3766
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003767 bh_lock_sock(sk);
3768
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769 BT_DBG("sk %p, len %d", sk, skb->len);
3770
3771 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3772 goto drop;
3773
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003774 if (l2cap_pi(sk)->chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775 goto drop;
3776
3777 if (!sock_queue_rcv_skb(sk, skb))
3778 goto done;
3779
3780drop:
3781 kfree_skb(skb);
3782
3783done:
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003784 if (sk)
3785 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786 return 0;
3787}
3788
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003789static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3790{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003791 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003792 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003793
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003794 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3795 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003796 goto drop;
3797
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003798 sk = chan->sk;
3799
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003800 bh_lock_sock(sk);
3801
3802 BT_DBG("sk %p, len %d", sk, skb->len);
3803
3804 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3805 goto drop;
3806
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003807 if (l2cap_pi(sk)->chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003808 goto drop;
3809
3810 if (!sock_queue_rcv_skb(sk, skb))
3811 goto done;
3812
3813drop:
3814 kfree_skb(skb);
3815
3816done:
3817 if (sk)
3818 bh_unlock_sock(sk);
3819 return 0;
3820}
3821
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3823{
3824 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003825 u16 cid, len;
3826 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827
3828 skb_pull(skb, L2CAP_HDR_SIZE);
3829 cid = __le16_to_cpu(lh->cid);
3830 len = __le16_to_cpu(lh->len);
3831
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003832 if (len != skb->len) {
3833 kfree_skb(skb);
3834 return;
3835 }
3836
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3838
3839 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003840 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003841 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842 l2cap_sig_channel(conn, skb);
3843 break;
3844
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003845 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003846 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003847 skb_pull(skb, 2);
3848 l2cap_conless_channel(conn, psm, skb);
3849 break;
3850
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003851 case L2CAP_CID_LE_DATA:
3852 l2cap_att_channel(conn, cid, skb);
3853 break;
3854
Linus Torvalds1da177e2005-04-16 15:20:36 -07003855 default:
3856 l2cap_data_channel(conn, cid, skb);
3857 break;
3858 }
3859}
3860
3861/* ---- L2CAP interface with lower layer (HCI) ---- */
3862
3863static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3864{
3865 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003866 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867
3868 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003869 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870
3871 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3872
3873 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003874 read_lock(&chan_list_lock);
3875 list_for_each_entry(c, &chan_list, global_l) {
3876 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003877
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878 if (sk->sk_state != BT_LISTEN)
3879 continue;
3880
3881 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003882 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003883 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003884 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003886 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3887 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003888 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003889 lm2 |= HCI_LM_MASTER;
3890 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003892 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893
3894 return exact ? lm1 : lm2;
3895}
3896
3897static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3898{
Marcel Holtmann01394182006-07-03 10:02:46 +02003899 struct l2cap_conn *conn;
3900
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3902
Ville Tervoacd7d372011-02-10 22:38:49 -03003903 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003904 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905
3906 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907 conn = l2cap_conn_add(hcon, status);
3908 if (conn)
3909 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003910 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911 l2cap_conn_del(hcon, bt_err(status));
3912
3913 return 0;
3914}
3915
Marcel Holtmann2950f212009-02-12 14:02:50 +01003916static int l2cap_disconn_ind(struct hci_conn *hcon)
3917{
3918 struct l2cap_conn *conn = hcon->l2cap_data;
3919
3920 BT_DBG("hcon %p", hcon);
3921
3922 if (hcon->type != ACL_LINK || !conn)
3923 return 0x13;
3924
3925 return conn->disc_reason;
3926}
3927
3928static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929{
3930 BT_DBG("hcon %p reason %d", hcon, reason);
3931
Ville Tervoacd7d372011-02-10 22:38:49 -03003932 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003933 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934
3935 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003936
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937 return 0;
3938}
3939
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003940static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003941{
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003942 struct sock *sk = chan->sk;
3943
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003944 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003945 return;
3946
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003947 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003948 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003949 l2cap_sock_clear_timer(sk);
3950 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003951 } else if (chan->sec_level == BT_SECURITY_HIGH)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003952 __l2cap_sock_close(sk, ECONNREFUSED);
3953 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003954 if (chan->sec_level == BT_SECURITY_MEDIUM)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003955 l2cap_sock_clear_timer(sk);
3956 }
3957}
3958
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003959static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003961 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003962 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963
Marcel Holtmann01394182006-07-03 10:02:46 +02003964 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003966
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967 BT_DBG("conn %p", conn);
3968
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003969 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003971 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003972 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003973
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974 bh_lock_sock(sk);
3975
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003976 if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003977 bh_unlock_sock(sk);
3978 continue;
3979 }
3980
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003981 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003982 sk->sk_state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003983 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003984 bh_unlock_sock(sk);
3985 continue;
3986 }
3987
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003988 if (sk->sk_state == BT_CONNECT) {
3989 if (!status) {
3990 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03003991 req.scid = cpu_to_le16(chan->scid);
3992 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003993
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003994 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003995 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003996
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003997 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003998 L2CAP_CONN_REQ, sizeof(req), &req);
3999 } else {
4000 l2cap_sock_clear_timer(sk);
4001 l2cap_sock_set_timer(sk, HZ / 10);
4002 }
4003 } else if (sk->sk_state == BT_CONNECT2) {
4004 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004005 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004006
4007 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004008 if (bt_sk(sk)->defer_setup) {
4009 struct sock *parent = bt_sk(sk)->parent;
4010 res = L2CAP_CR_PEND;
4011 stat = L2CAP_CS_AUTHOR_PEND;
4012 parent->sk_data_ready(parent, 0);
4013 } else {
4014 sk->sk_state = BT_CONFIG;
4015 res = L2CAP_CR_SUCCESS;
4016 stat = L2CAP_CS_NO_INFO;
4017 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004018 } else {
4019 sk->sk_state = BT_DISCONN;
4020 l2cap_sock_set_timer(sk, HZ / 10);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004021 res = L2CAP_CR_SEC_BLOCK;
4022 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004023 }
4024
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004025 rsp.scid = cpu_to_le16(chan->dcid);
4026 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004027 rsp.result = cpu_to_le16(res);
4028 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004029 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4030 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031 }
4032
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033 bh_unlock_sock(sk);
4034 }
4035
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004036 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004037
Linus Torvalds1da177e2005-04-16 15:20:36 -07004038 return 0;
4039}
4040
4041static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4042{
4043 struct l2cap_conn *conn = hcon->l2cap_data;
4044
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004045 if (!conn)
4046 conn = l2cap_conn_add(hcon, 0);
4047
4048 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049 goto drop;
4050
4051 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4052
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004053 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004055 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004056 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057 int len;
4058
4059 if (conn->rx_len) {
4060 BT_ERR("Unexpected start frame (len %d)", skb->len);
4061 kfree_skb(conn->rx_skb);
4062 conn->rx_skb = NULL;
4063 conn->rx_len = 0;
4064 l2cap_conn_unreliable(conn, ECOMM);
4065 }
4066
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004067 /* Start fragment always begin with Basic L2CAP header */
4068 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069 BT_ERR("Frame is too short (len %d)", skb->len);
4070 l2cap_conn_unreliable(conn, ECOMM);
4071 goto drop;
4072 }
4073
4074 hdr = (struct l2cap_hdr *) skb->data;
4075 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004076 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077
4078 if (len == skb->len) {
4079 /* Complete frame received */
4080 l2cap_recv_frame(conn, skb);
4081 return 0;
4082 }
4083
4084 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4085
4086 if (skb->len > len) {
4087 BT_ERR("Frame is too long (len %d, expected len %d)",
4088 skb->len, len);
4089 l2cap_conn_unreliable(conn, ECOMM);
4090 goto drop;
4091 }
4092
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004093 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004094
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004095 if (chan && chan->sk) {
4096 struct sock *sk = chan->sk;
4097
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004098 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004099 BT_ERR("Frame exceeding recv MTU (len %d, "
4100 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004101 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004102 bh_unlock_sock(sk);
4103 l2cap_conn_unreliable(conn, ECOMM);
4104 goto drop;
4105 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004106 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004107 }
4108
Linus Torvalds1da177e2005-04-16 15:20:36 -07004109 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03004110 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4111 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112 goto drop;
4113
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004114 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004115 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116 conn->rx_len = len - skb->len;
4117 } else {
4118 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4119
4120 if (!conn->rx_len) {
4121 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4122 l2cap_conn_unreliable(conn, ECOMM);
4123 goto drop;
4124 }
4125
4126 if (skb->len > conn->rx_len) {
4127 BT_ERR("Fragment is too long (len %d, expected %d)",
4128 skb->len, conn->rx_len);
4129 kfree_skb(conn->rx_skb);
4130 conn->rx_skb = NULL;
4131 conn->rx_len = 0;
4132 l2cap_conn_unreliable(conn, ECOMM);
4133 goto drop;
4134 }
4135
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004136 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004137 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138 conn->rx_len -= skb->len;
4139
4140 if (!conn->rx_len) {
4141 /* Complete frame received */
4142 l2cap_recv_frame(conn, conn->rx_skb);
4143 conn->rx_skb = NULL;
4144 }
4145 }
4146
4147drop:
4148 kfree_skb(skb);
4149 return 0;
4150}
4151
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004152static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004154 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004156 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004158 list_for_each_entry(c, &chan_list, global_l) {
4159 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004161 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 +01004162 batostr(&bt_sk(sk)->src),
4163 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004164 sk->sk_state, __le16_to_cpu(c->psm),
4165 c->scid, c->dcid, c->imtu, c->omtu,
4166 c->sec_level, c->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004167 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004169 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004170
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004171 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172}
4173
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004174static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4175{
4176 return single_open(file, l2cap_debugfs_show, inode->i_private);
4177}
4178
4179static const struct file_operations l2cap_debugfs_fops = {
4180 .open = l2cap_debugfs_open,
4181 .read = seq_read,
4182 .llseek = seq_lseek,
4183 .release = single_release,
4184};
4185
4186static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004187
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188static struct hci_proto l2cap_hci_proto = {
4189 .name = "L2CAP",
4190 .id = HCI_PROTO_L2CAP,
4191 .connect_ind = l2cap_connect_ind,
4192 .connect_cfm = l2cap_connect_cfm,
4193 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004194 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004195 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004196 .recv_acldata = l2cap_recv_acldata
4197};
4198
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004199int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200{
4201 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004202
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004203 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204 if (err < 0)
4205 return err;
4206
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004207 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004208 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004209 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004210 goto error;
4211 }
4212
4213 err = hci_register_proto(&l2cap_hci_proto);
4214 if (err < 0) {
4215 BT_ERR("L2CAP protocol registration failed");
4216 bt_sock_unregister(BTPROTO_L2CAP);
4217 goto error;
4218 }
4219
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004220 if (bt_debugfs) {
4221 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4222 bt_debugfs, NULL, &l2cap_debugfs_fops);
4223 if (!l2cap_debugfs)
4224 BT_ERR("Failed to create L2CAP debug file");
4225 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227 return 0;
4228
4229error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004230 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004231 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232 return err;
4233}
4234
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004235void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004237 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004238
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004239 flush_workqueue(_busy_wq);
4240 destroy_workqueue(_busy_wq);
4241
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4243 BT_ERR("L2CAP protocol unregistration failed");
4244
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004245 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246}
4247
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004248module_param(disable_ertm, bool, 0644);
4249MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");