blob: e65f63130113bd3d7de4a911fa96f3679077996e [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
7 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation;
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
16 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090017 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090022 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
23 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 SOFTWARE IS DISCLAIMED.
25*/
26
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020027/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30
31#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080032#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
34#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/poll.h>
38#include <linux/fcntl.h>
39#include <linux/init.h>
40#include <linux/interrupt.h>
41#include <linux/socket.h>
42#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080044#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010045#include <linux/debugfs.h>
46#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030047#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030048#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/sock.h>
50
51#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
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. Padovan4519de92011-04-28 17:55:53 -030072static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
73 void *data);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030074static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030075static void l2cap_send_disconn_req(struct l2cap_conn *conn,
76 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030078static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
79
Marcel Holtmann01394182006-07-03 10:02:46 +020080/* ---- L2CAP channels ---- */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030081static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020082{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030083 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030084
85 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030086 if (c->dcid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030087 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020088 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030089 return NULL;
90
Marcel Holtmann01394182006-07-03 10:02:46 +020091}
92
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030093static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020094{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030095 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030096
97 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030098 if (c->scid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030099 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200100 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300101 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200102}
103
104/* Find channel with given SCID.
105 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300106static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200107{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300108 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300109
110 read_lock(&conn->chan_lock);
111 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300112 if (c)
113 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300114 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300115 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200116}
117
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300118static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200119{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300120 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300121
122 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300123 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300124 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200125 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300126 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200127}
128
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300129static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200130{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300131 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300132
133 read_lock(&conn->chan_lock);
134 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300135 if (c)
136 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300137 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300138 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200139}
140
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300141static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300142{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300143 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300144
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300145 list_for_each_entry(c, &chan_list, global_l) {
146 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300147 goto found;
148 }
149
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300150 c = NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300151found:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300152 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300153}
154
155int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
156{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300157 int err;
158
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300159 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300160
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300161 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300162 err = -EADDRINUSE;
163 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300164 }
165
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300166 if (psm) {
167 chan->psm = psm;
168 chan->sport = psm;
169 err = 0;
170 } else {
171 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300172
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300173 err = -EINVAL;
174 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300175 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300176 chan->psm = cpu_to_le16(p);
177 chan->sport = cpu_to_le16(p);
178 err = 0;
179 break;
180 }
181 }
182
183done:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300184 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300185 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300186}
187
188int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
189{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300190 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300191
192 chan->scid = scid;
193
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300194 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300195
196 return 0;
197}
198
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300199static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200200{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300201 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200202
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300203 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300204 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200205 return cid;
206 }
207
208 return 0;
209}
210
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300211struct l2cap_chan *l2cap_chan_create(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200212{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300213 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200214
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300215 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
216 if (!chan)
217 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200218
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300219 chan->sk = sk;
220
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300221 write_lock_bh(&chan_list_lock);
222 list_add(&chan->global_l, &chan_list);
223 write_unlock_bh(&chan_list_lock);
224
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300225 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200226}
227
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300228void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300229{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300230 write_lock_bh(&chan_list_lock);
231 list_del(&chan->global_l);
232 write_unlock_bh(&chan_list_lock);
233
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300234 kfree(chan);
235}
236
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300237static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200238{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300239 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200240
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300241 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300242 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200243
Marcel Holtmann2950f212009-02-12 14:02:50 +0100244 conn->disc_reason = 0x13;
245
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300246 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200247
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300248 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Ville Tervob62f3282011-02-10 22:38:50 -0300249 if (conn->hcon->type == LE_LINK) {
250 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300251 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300252 chan->scid = L2CAP_CID_LE_DATA;
253 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300254 } else {
255 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300256 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300257 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300258 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200259 } else if (sk->sk_type == SOCK_DGRAM) {
260 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300261 chan->scid = L2CAP_CID_CONN_LESS;
262 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300263 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200264 } else {
265 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300266 chan->scid = L2CAP_CID_SIGNALING;
267 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300268 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200269 }
270
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300271 sock_hold(sk);
272
273 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200274}
275
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900276/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200277 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300278static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200279{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300280 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300281 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200282 struct sock *parent = bt_sk(sk)->parent;
283
284 l2cap_sock_clear_timer(sk);
285
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300286 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200287
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900288 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300289 /* Delete from channel list */
290 write_lock_bh(&conn->chan_lock);
291 list_del(&chan->list);
292 write_unlock_bh(&conn->chan_lock);
293 __sock_put(sk);
294
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300295 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200296 hci_conn_put(conn->hcon);
297 }
298
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200299 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200300 sock_set_flag(sk, SOCK_ZAPPED);
301
302 if (err)
303 sk->sk_err = err;
304
305 if (parent) {
306 bt_accept_unlink(sk);
307 parent->sk_data_ready(parent, 0);
308 } else
309 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300310
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300311 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE &&
312 chan->conf_state & L2CAP_CONF_INPUT_DONE))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300313 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300314
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300315 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300316
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300317 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300318 struct srej_list *l, *tmp;
319
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300320 del_timer(&chan->retrans_timer);
321 del_timer(&chan->monitor_timer);
322 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300323
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300324 skb_queue_purge(&chan->srej_q);
325 skb_queue_purge(&chan->busy_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300326
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300327 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300328 list_del(&l->list);
329 kfree(l);
330 }
331 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200332}
333
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300334/* Must be called on unlocked socket. */
335static void l2cap_chan_close(struct sock *sk)
336{
337 l2cap_sock_clear_timer(sk);
338 lock_sock(sk);
339 __l2cap_chan_close(l2cap_pi(sk)->chan, ECONNRESET);
340 release_sock(sk);
341 l2cap_sock_kill(sk);
342}
343
344static void l2cap_chan_cleanup_listen(struct sock *parent)
345{
346 struct sock *sk;
347
348 BT_DBG("parent %p", parent);
349
350 /* Close not yet accepted channels */
351 while ((sk = bt_accept_dequeue(parent, NULL)))
352 l2cap_chan_close(sk);
353
354 parent->sk_state = BT_CLOSED;
355 sock_set_flag(parent, SOCK_ZAPPED);
356}
357
358void __l2cap_chan_close(struct l2cap_chan *chan, int reason)
359{
360 struct l2cap_conn *conn = chan->conn;
361 struct sock *sk = chan->sk;
362
363 BT_DBG("chan %p state %d socket %p", chan, sk->sk_state, sk->sk_socket);
364
365 switch (sk->sk_state) {
366 case BT_LISTEN:
367 l2cap_chan_cleanup_listen(sk);
368 break;
369
370 case BT_CONNECTED:
371 case BT_CONFIG:
372 if ((sk->sk_type == SOCK_SEQPACKET ||
373 sk->sk_type == SOCK_STREAM) &&
374 conn->hcon->type == ACL_LINK) {
375 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
376 l2cap_send_disconn_req(conn, chan, reason);
377 } else
378 l2cap_chan_del(chan, reason);
379 break;
380
381 case BT_CONNECT2:
382 if ((sk->sk_type == SOCK_SEQPACKET ||
383 sk->sk_type == SOCK_STREAM) &&
384 conn->hcon->type == ACL_LINK) {
385 struct l2cap_conn_rsp rsp;
386 __u16 result;
387
388 if (bt_sk(sk)->defer_setup)
389 result = L2CAP_CR_SEC_BLOCK;
390 else
391 result = L2CAP_CR_BAD_PSM;
392
393 rsp.scid = cpu_to_le16(chan->dcid);
394 rsp.dcid = cpu_to_le16(chan->scid);
395 rsp.result = cpu_to_le16(result);
396 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
397 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
398 sizeof(rsp), &rsp);
399 }
400
401 l2cap_chan_del(chan, reason);
402 break;
403
404 case BT_CONNECT:
405 case BT_DISCONN:
406 l2cap_chan_del(chan, reason);
407 break;
408
409 default:
410 sock_set_flag(sk, SOCK_ZAPPED);
411 break;
412 }
413}
414
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300415static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530416{
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300417 struct sock *sk = chan->sk;
418
Johan Hedberg8556edd32011-01-19 12:06:50 +0530419 if (sk->sk_type == SOCK_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300420 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530421 case BT_SECURITY_HIGH:
422 return HCI_AT_DEDICATED_BONDING_MITM;
423 case BT_SECURITY_MEDIUM:
424 return HCI_AT_DEDICATED_BONDING;
425 default:
426 return HCI_AT_NO_BONDING;
427 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300428 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300429 if (chan->sec_level == BT_SECURITY_LOW)
430 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530431
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300432 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530433 return HCI_AT_NO_BONDING_MITM;
434 else
435 return HCI_AT_NO_BONDING;
436 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300437 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530438 case BT_SECURITY_HIGH:
439 return HCI_AT_GENERAL_BONDING_MITM;
440 case BT_SECURITY_MEDIUM:
441 return HCI_AT_GENERAL_BONDING;
442 default:
443 return HCI_AT_NO_BONDING;
444 }
445 }
446}
447
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200448/* Service level security */
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300449static inline int l2cap_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200450{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300451 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100452 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200453
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300454 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100455
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300456 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200457}
458
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200459u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200460{
461 u8 id;
462
463 /* Get next available identificator.
464 * 1 - 128 are used by kernel.
465 * 129 - 199 are reserved.
466 * 200 - 254 are used by utilities like l2ping, etc.
467 */
468
469 spin_lock_bh(&conn->lock);
470
471 if (++conn->tx_ident > 128)
472 conn->tx_ident = 1;
473
474 id = conn->tx_ident;
475
476 spin_unlock_bh(&conn->lock);
477
478 return id;
479}
480
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300481static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200482{
483 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200484 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200485
486 BT_DBG("code 0x%2.2x", code);
487
488 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300489 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200490
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200491 if (lmp_no_flush_capable(conn->hcon->hdev))
492 flags = ACL_START_NO_FLUSH;
493 else
494 flags = ACL_START;
495
496 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200497}
498
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300499static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300500{
501 struct sk_buff *skb;
502 struct l2cap_hdr *lh;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300503 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300504 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300505 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300506 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200507 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300508
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300509 if (sk->sk_state != BT_CONNECTED)
510 return;
511
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300512 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300513 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300514
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300515 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300516
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300517 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300518 control |= L2CAP_CTRL_FRAME_TYPE;
519
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300520 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300521 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300522 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300523 }
524
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300525 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300526 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300527 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300528 }
529
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300530 skb = bt_skb_alloc(count, GFP_ATOMIC);
531 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300532 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300533
534 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300535 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300536 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300537 put_unaligned_le16(control, skb_put(skb, 2));
538
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300539 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300540 u16 fcs = crc16(0, (u8 *)lh, count - 2);
541 put_unaligned_le16(fcs, skb_put(skb, 2));
542 }
543
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200544 if (lmp_no_flush_capable(conn->hcon->hdev))
545 flags = ACL_START_NO_FLUSH;
546 else
547 flags = ACL_START;
548
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300549 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300550}
551
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300552static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300553{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300554 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300555 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300556 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300557 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300558 control |= L2CAP_SUPER_RCV_READY;
559
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300560 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300561
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300562 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300563}
564
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300565static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300566{
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300567 return !(chan->conf_state & L2CAP_CONF_CONNECT_PEND);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300568}
569
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300570static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200571{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300572 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200573
574 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100575 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
576 return;
577
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300578 if (l2cap_check_security(chan) &&
579 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200580 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300581 req.scid = cpu_to_le16(chan->scid);
582 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200583
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300584 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300585 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200586
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300587 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
588 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200589 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200590 } else {
591 struct l2cap_info_req req;
592 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
593
594 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
595 conn->info_ident = l2cap_get_ident(conn);
596
597 mod_timer(&conn->info_timer, jiffies +
598 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
599
600 l2cap_send_cmd(conn, conn->info_ident,
601 L2CAP_INFO_REQ, sizeof(req), &req);
602 }
603}
604
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300605static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
606{
607 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300608 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300609 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
610
611 switch (mode) {
612 case L2CAP_MODE_ERTM:
613 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
614 case L2CAP_MODE_STREAMING:
615 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
616 default:
617 return 0x00;
618 }
619}
620
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300621static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300622{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300623 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300624 struct l2cap_disconn_req req;
625
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300626 if (!conn)
627 return;
628
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300629 sk = chan->sk;
630
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300631 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300632 del_timer(&chan->retrans_timer);
633 del_timer(&chan->monitor_timer);
634 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300635 }
636
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300637 req.dcid = cpu_to_le16(chan->dcid);
638 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300639 l2cap_send_cmd(conn, l2cap_get_ident(conn),
640 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300641
642 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300643 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300644}
645
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200647static void l2cap_conn_start(struct l2cap_conn *conn)
648{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300649 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200650
651 BT_DBG("conn %p", conn);
652
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300653 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200654
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300655 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300656 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300657
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200658 bh_lock_sock(sk);
659
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300660 if (sk->sk_type != SOCK_SEQPACKET &&
661 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200662 bh_unlock_sock(sk);
663 continue;
664 }
665
666 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300667 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300668
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300669 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300670 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300671 bh_unlock_sock(sk);
672 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200673 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300674
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300675 if (!l2cap_mode_supported(chan->mode,
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300676 conn->feat_mask)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300677 && chan->conf_state &
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300678 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300679 /* __l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300680 * so release the lock */
681 read_unlock_bh(&conn->chan_lock);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300682 __l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300683 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300684 bh_unlock_sock(sk);
685 continue;
686 }
687
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300688 req.scid = cpu_to_le16(chan->scid);
689 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300690
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300691 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300692 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300693
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300694 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
695 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300696
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200697 } else if (sk->sk_state == BT_CONNECT2) {
698 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300699 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300700 rsp.scid = cpu_to_le16(chan->dcid);
701 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200702
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300703 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100704 if (bt_sk(sk)->defer_setup) {
705 struct sock *parent = bt_sk(sk)->parent;
706 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
707 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
708 parent->sk_data_ready(parent, 0);
709
710 } else {
711 sk->sk_state = BT_CONFIG;
712 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
713 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
714 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200715 } else {
716 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
717 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
718 }
719
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300720 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
721 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300722
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300723 if (chan->conf_state & L2CAP_CONF_REQ_SENT ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300724 rsp.result != L2CAP_CR_SUCCESS) {
725 bh_unlock_sock(sk);
726 continue;
727 }
728
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300729 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300730 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300731 l2cap_build_conf_req(chan, buf), buf);
732 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200733 }
734
735 bh_unlock_sock(sk);
736 }
737
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300738 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200739}
740
Ville Tervob62f3282011-02-10 22:38:50 -0300741/* Find socket with cid and source bdaddr.
742 * Returns closest match, locked.
743 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300744static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300745{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300746 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300747
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300748 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300749
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300750 list_for_each_entry(c, &chan_list, global_l) {
751 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300752
Ville Tervob62f3282011-02-10 22:38:50 -0300753 if (state && sk->sk_state != state)
754 continue;
755
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300756 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300757 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300758 if (!bacmp(&bt_sk(sk)->src, src)) {
759 read_unlock(&chan_list_lock);
760 return c;
761 }
Ville Tervob62f3282011-02-10 22:38:50 -0300762
763 /* Closest match */
764 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300765 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300766 }
767 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300768
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300769 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300770
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300771 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300772}
773
774static void l2cap_le_conn_ready(struct l2cap_conn *conn)
775{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300776 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300777 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300778
779 BT_DBG("");
780
781 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300782 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300783 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300784 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300785 return;
786
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300787 parent = pchan->sk;
788
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300789 bh_lock_sock(parent);
790
Ville Tervob62f3282011-02-10 22:38:50 -0300791 /* Check for backlog size */
792 if (sk_acceptq_is_full(parent)) {
793 BT_DBG("backlog full %d", parent->sk_ack_backlog);
794 goto clean;
795 }
796
797 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
798 if (!sk)
799 goto clean;
800
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300801 chan = l2cap_chan_create(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300802 if (!chan) {
803 l2cap_sock_kill(sk);
804 goto clean;
805 }
806
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300807 l2cap_pi(sk)->chan = chan;
808
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300809 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300810
811 hci_conn_hold(conn->hcon);
812
813 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300814
Ville Tervob62f3282011-02-10 22:38:50 -0300815 bacpy(&bt_sk(sk)->src, conn->src);
816 bacpy(&bt_sk(sk)->dst, conn->dst);
817
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300818 bt_accept_enqueue(parent, sk);
819
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300820 __l2cap_chan_add(conn, chan);
821
Ville Tervob62f3282011-02-10 22:38:50 -0300822 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
823
824 sk->sk_state = BT_CONNECTED;
825 parent->sk_data_ready(parent, 0);
826
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300827 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300828
829clean:
830 bh_unlock_sock(parent);
831}
832
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200833static void l2cap_conn_ready(struct l2cap_conn *conn)
834{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300835 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200836
837 BT_DBG("conn %p", conn);
838
Ville Tervob62f3282011-02-10 22:38:50 -0300839 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
840 l2cap_le_conn_ready(conn);
841
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300842 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200843
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300844 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300845 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300846
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200847 bh_lock_sock(sk);
848
Ville Tervoacd7d372011-02-10 22:38:49 -0300849 if (conn->hcon->type == LE_LINK) {
850 l2cap_sock_clear_timer(sk);
851 sk->sk_state = BT_CONNECTED;
852 sk->sk_state_change(sk);
853 }
854
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300855 if (sk->sk_type != SOCK_SEQPACKET &&
856 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200857 l2cap_sock_clear_timer(sk);
858 sk->sk_state = BT_CONNECTED;
859 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200860 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300861 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200862
863 bh_unlock_sock(sk);
864 }
865
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300866 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200867}
868
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200869/* Notify sockets that we cannot guaranty reliability anymore */
870static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
871{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300872 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200873
874 BT_DBG("conn %p", conn);
875
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300876 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200877
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300878 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300879 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300880
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300881 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200882 sk->sk_err = err;
883 }
884
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300885 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200886}
887
888static void l2cap_info_timeout(unsigned long arg)
889{
890 struct l2cap_conn *conn = (void *) arg;
891
Marcel Holtmann984947d2009-02-06 23:35:19 +0100892 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100893 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100894
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200895 l2cap_conn_start(conn);
896}
897
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
899{
Marcel Holtmann01394182006-07-03 10:02:46 +0200900 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901
Marcel Holtmann01394182006-07-03 10:02:46 +0200902 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 return conn;
904
Marcel Holtmann01394182006-07-03 10:02:46 +0200905 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
906 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908
909 hcon->l2cap_data = conn;
910 conn->hcon = hcon;
911
Marcel Holtmann01394182006-07-03 10:02:46 +0200912 BT_DBG("hcon %p conn %p", hcon, conn);
913
Ville Tervoacd7d372011-02-10 22:38:49 -0300914 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
915 conn->mtu = hcon->hdev->le_mtu;
916 else
917 conn->mtu = hcon->hdev->acl_mtu;
918
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 conn->src = &hcon->hdev->bdaddr;
920 conn->dst = &hcon->dst;
921
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200922 conn->feat_mask = 0;
923
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300925 rwlock_init(&conn->chan_lock);
926
927 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928
Ville Tervob62f3282011-02-10 22:38:50 -0300929 if (hcon->type != LE_LINK)
930 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000931 (unsigned long) conn);
932
Marcel Holtmann2950f212009-02-12 14:02:50 +0100933 conn->disc_reason = 0x13;
934
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 return conn;
936}
937
Marcel Holtmann01394182006-07-03 10:02:46 +0200938static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939{
Marcel Holtmann01394182006-07-03 10:02:46 +0200940 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300941 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 struct sock *sk;
943
Marcel Holtmann01394182006-07-03 10:02:46 +0200944 if (!conn)
945 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946
947 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
948
Wei Yongjun7585b972009-02-25 18:29:52 +0800949 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950
951 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300952 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300953 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300955 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 bh_unlock_sock(sk);
957 l2cap_sock_kill(sk);
958 }
959
Dave Young8e8440f2008-03-03 12:18:55 -0800960 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
961 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800962
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 hcon->l2cap_data = NULL;
964 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965}
966
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300967static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300969 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300970 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300971 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972}
973
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975
976/* Find socket with psm and source bdaddr.
977 * Returns closest match.
978 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300979static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300981 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300983 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000984
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300985 list_for_each_entry(c, &chan_list, global_l) {
986 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300987
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 if (state && sk->sk_state != state)
989 continue;
990
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300991 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300993 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +0200994 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300995 return c;
996 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997
998 /* Closest match */
999 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001000 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 }
1002 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001004 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001005
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001006 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007}
1008
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001009int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001011 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 bdaddr_t *src = &bt_sk(sk)->src;
1013 bdaddr_t *dst = &bt_sk(sk)->dst;
1014 struct l2cap_conn *conn;
1015 struct hci_conn *hcon;
1016 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001017 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001018 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001020 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001021 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001023 hdev = hci_get_route(dst, src);
1024 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 return -EHOSTUNREACH;
1026
1027 hci_dev_lock_bh(hdev);
1028
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001029 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001030
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001031 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001032 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001033 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001034 else
1035 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001036 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001037
Ville Tervo30e76272011-02-22 16:10:53 -03001038 if (IS_ERR(hcon)) {
1039 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001041 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042
1043 conn = l2cap_conn_add(hcon, 0);
1044 if (!conn) {
1045 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001046 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 goto done;
1048 }
1049
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 /* Update source addr of the socket */
1051 bacpy(src, conn->src);
1052
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001053 l2cap_chan_add(conn, chan);
1054
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 sk->sk_state = BT_CONNECT;
1056 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
1057
1058 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001059 if (sk->sk_type != SOCK_SEQPACKET &&
1060 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 l2cap_sock_clear_timer(sk);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001062 if (l2cap_check_security(chan))
Johan Hedbergd00ef242011-01-19 12:06:51 +05301063 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001064 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001065 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 }
1067
Ville Tervo30e76272011-02-22 16:10:53 -03001068 err = 0;
1069
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070done:
1071 hci_dev_unlock_bh(hdev);
1072 hci_dev_put(hdev);
1073 return err;
1074}
1075
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001076int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001077{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001078 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001079 DECLARE_WAITQUEUE(wait, current);
1080 int err = 0;
1081 int timeo = HZ/5;
1082
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001083 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001084 while ((chan->unacked_frames > 0 && chan->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001085 set_current_state(TASK_INTERRUPTIBLE);
1086
1087 if (!timeo)
1088 timeo = HZ/5;
1089
1090 if (signal_pending(current)) {
1091 err = sock_intr_errno(timeo);
1092 break;
1093 }
1094
1095 release_sock(sk);
1096 timeo = schedule_timeout(timeo);
1097 lock_sock(sk);
1098
1099 err = sock_error(sk);
1100 if (err)
1101 break;
1102 }
1103 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001104 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001105 return err;
1106}
1107
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001108static void l2cap_monitor_timeout(unsigned long arg)
1109{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001110 struct l2cap_chan *chan = (void *) arg;
1111 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001112
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001113 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001114
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001115 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001116 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001117 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001118 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001119 return;
1120 }
1121
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001122 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001123 __mod_monitor_timer();
1124
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001125 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001126 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001127}
1128
1129static void l2cap_retrans_timeout(unsigned long arg)
1130{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001131 struct l2cap_chan *chan = (void *) arg;
1132 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001133
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001134 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001135
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001136 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001137 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001138 __mod_monitor_timer();
1139
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001140 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001141
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001142 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001143 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001144}
1145
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001146static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001147{
1148 struct sk_buff *skb;
1149
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001150 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001151 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001152 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001153 break;
1154
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001155 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001156 kfree_skb(skb);
1157
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001158 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001159 }
1160
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001161 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001162 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001163}
1164
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001165void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001166{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001167 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001168 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001169
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001170 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001171
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001172 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001173 flags = ACL_START_NO_FLUSH;
1174 else
1175 flags = ACL_START;
1176
1177 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001178}
1179
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001180void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001181{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001182 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001183 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001184
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001185 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001186 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001187 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001188 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001189
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001190 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001191 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1192 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001193 }
1194
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001195 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001196
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001197 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001198 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001199}
1200
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001201static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001202{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001203 struct sk_buff *skb, *tx_skb;
1204 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001205
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001206 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001207 if (!skb)
1208 return;
1209
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001210 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001211 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001212 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001213
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001214 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001215 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001216
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001217 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001218
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001219 if (chan->remote_max_tx &&
1220 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001221 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001222 return;
1223 }
1224
1225 tx_skb = skb_clone(skb, GFP_ATOMIC);
1226 bt_cb(skb)->retries++;
1227 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001228 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001229
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001230 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001231 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001232 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001233 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001234
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001235 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001236 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001237
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001238 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1239
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001240 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001241 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1242 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1243 }
1244
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001245 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001246}
1247
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001248int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001249{
1250 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001251 struct sock *sk = chan->sk;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001252 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001253 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001254
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001255 if (sk->sk_state != BT_CONNECTED)
1256 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001257
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001258 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001259
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001260 if (chan->remote_max_tx &&
1261 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001262 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001263 break;
1264 }
1265
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001266 tx_skb = skb_clone(skb, GFP_ATOMIC);
1267
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001268 bt_cb(skb)->retries++;
1269
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001270 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001271 control &= L2CAP_CTRL_SAR;
1272
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001273 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001274 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001275 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001276 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001277 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1278 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001279 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1280
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001281
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001282 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001283 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1284 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1285 }
1286
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001287 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001288
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001289 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001290
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001291 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1292 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001293
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301294 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001295 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301296
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001297 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001298
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001299 if (skb_queue_is_last(&chan->tx_q, skb))
1300 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001301 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001302 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001303
1304 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001305 }
1306
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001307 return nsent;
1308}
1309
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001310static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001311{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001312 int ret;
1313
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001314 if (!skb_queue_empty(&chan->tx_q))
1315 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001316
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001317 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001318 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001319 return ret;
1320}
1321
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001322static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001323{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001324 u16 control = 0;
1325
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001326 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001327
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001328 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001329 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001330 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1331 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001332 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001333 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001334
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001335 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001336 return;
1337
1338 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001339 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001340}
1341
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001342static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001343{
1344 struct srej_list *tail;
1345 u16 control;
1346
1347 control = L2CAP_SUPER_SELECT_REJECT;
1348 control |= L2CAP_CTRL_FINAL;
1349
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001350 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001351 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1352
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001353 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001354}
1355
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001356static 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 -07001357{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001358 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001359 struct sk_buff **frag;
1360 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001362 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001363 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364
1365 sent += count;
1366 len -= count;
1367
1368 /* Continuation fragments (no L2CAP header) */
1369 frag = &skb_shinfo(skb)->frag_list;
1370 while (len) {
1371 count = min_t(unsigned int, conn->mtu, len);
1372
1373 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1374 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001375 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001376 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1377 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378
1379 sent += count;
1380 len -= count;
1381
1382 frag = &(*frag)->next;
1383 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384
1385 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001386}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001388struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001389{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001390 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001391 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001392 struct sk_buff *skb;
1393 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1394 struct l2cap_hdr *lh;
1395
1396 BT_DBG("sk %p len %d", sk, (int)len);
1397
1398 count = min_t(unsigned int, (conn->mtu - hlen), len);
1399 skb = bt_skb_send_alloc(sk, count + hlen,
1400 msg->msg_flags & MSG_DONTWAIT, &err);
1401 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001402 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001403
1404 /* Create L2CAP header */
1405 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001406 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001407 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001408 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001409
1410 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1411 if (unlikely(err < 0)) {
1412 kfree_skb(skb);
1413 return ERR_PTR(err);
1414 }
1415 return skb;
1416}
1417
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001418struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001419{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001420 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001421 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001422 struct sk_buff *skb;
1423 int err, count, hlen = L2CAP_HDR_SIZE;
1424 struct l2cap_hdr *lh;
1425
1426 BT_DBG("sk %p len %d", sk, (int)len);
1427
1428 count = min_t(unsigned int, (conn->mtu - hlen), len);
1429 skb = bt_skb_send_alloc(sk, count + hlen,
1430 msg->msg_flags & MSG_DONTWAIT, &err);
1431 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001432 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001433
1434 /* Create L2CAP header */
1435 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001436 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001437 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1438
1439 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1440 if (unlikely(err < 0)) {
1441 kfree_skb(skb);
1442 return ERR_PTR(err);
1443 }
1444 return skb;
1445}
1446
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001447struct 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 -03001448{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001449 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001450 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001451 struct sk_buff *skb;
1452 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1453 struct l2cap_hdr *lh;
1454
1455 BT_DBG("sk %p len %d", sk, (int)len);
1456
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001457 if (!conn)
1458 return ERR_PTR(-ENOTCONN);
1459
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001460 if (sdulen)
1461 hlen += 2;
1462
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001463 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001464 hlen += 2;
1465
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001466 count = min_t(unsigned int, (conn->mtu - hlen), len);
1467 skb = bt_skb_send_alloc(sk, count + hlen,
1468 msg->msg_flags & MSG_DONTWAIT, &err);
1469 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001470 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001471
1472 /* Create L2CAP header */
1473 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001474 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001475 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1476 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001477 if (sdulen)
1478 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001479
1480 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1481 if (unlikely(err < 0)) {
1482 kfree_skb(skb);
1483 return ERR_PTR(err);
1484 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001485
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001486 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001487 put_unaligned_le16(0, skb_put(skb, 2));
1488
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001489 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001490 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491}
1492
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001493int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001494{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001495 struct sk_buff *skb;
1496 struct sk_buff_head sar_queue;
1497 u16 control;
1498 size_t size = 0;
1499
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001500 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001501 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001502 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001503 if (IS_ERR(skb))
1504 return PTR_ERR(skb);
1505
1506 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001507 len -= chan->remote_mps;
1508 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001509
1510 while (len > 0) {
1511 size_t buflen;
1512
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001513 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001514 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001515 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001516 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001517 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001518 buflen = len;
1519 }
1520
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001521 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001522 if (IS_ERR(skb)) {
1523 skb_queue_purge(&sar_queue);
1524 return PTR_ERR(skb);
1525 }
1526
1527 __skb_queue_tail(&sar_queue, skb);
1528 len -= buflen;
1529 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001530 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001531 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1532 if (chan->tx_send_head == NULL)
1533 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001534
1535 return size;
1536}
1537
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001538int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1539{
1540 struct sock *sk = chan->sk;
1541 struct sk_buff *skb;
1542 u16 control;
1543 int err;
1544
1545 /* Connectionless channel */
1546 if (sk->sk_type == SOCK_DGRAM) {
1547 skb = l2cap_create_connless_pdu(chan, msg, len);
1548 if (IS_ERR(skb))
1549 return PTR_ERR(skb);
1550
1551 l2cap_do_send(chan, skb);
1552 return len;
1553 }
1554
1555 switch (chan->mode) {
1556 case L2CAP_MODE_BASIC:
1557 /* Check outgoing MTU */
1558 if (len > chan->omtu)
1559 return -EMSGSIZE;
1560
1561 /* Create a basic PDU */
1562 skb = l2cap_create_basic_pdu(chan, msg, len);
1563 if (IS_ERR(skb))
1564 return PTR_ERR(skb);
1565
1566 l2cap_do_send(chan, skb);
1567 err = len;
1568 break;
1569
1570 case L2CAP_MODE_ERTM:
1571 case L2CAP_MODE_STREAMING:
1572 /* Entire SDU fits into one PDU */
1573 if (len <= chan->remote_mps) {
1574 control = L2CAP_SDU_UNSEGMENTED;
1575 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1576 0);
1577 if (IS_ERR(skb))
1578 return PTR_ERR(skb);
1579
1580 __skb_queue_tail(&chan->tx_q, skb);
1581
1582 if (chan->tx_send_head == NULL)
1583 chan->tx_send_head = skb;
1584
1585 } else {
1586 /* Segment SDU into multiples PDUs */
1587 err = l2cap_sar_segment_sdu(chan, msg, len);
1588 if (err < 0)
1589 return err;
1590 }
1591
1592 if (chan->mode == L2CAP_MODE_STREAMING) {
1593 l2cap_streaming_send(chan);
1594 err = len;
1595 break;
1596 }
1597
1598 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
1599 (chan->conn_state & L2CAP_CONN_WAIT_F)) {
1600 err = len;
1601 break;
1602 }
1603
1604 err = l2cap_ertm_send(chan);
1605 if (err >= 0)
1606 err = len;
1607
1608 break;
1609
1610 default:
1611 BT_DBG("bad state %1.1x", chan->mode);
1612 err = -EBADFD;
1613 }
1614
1615 return err;
1616}
1617
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618static void l2cap_chan_ready(struct sock *sk)
1619{
1620 struct sock *parent = bt_sk(sk)->parent;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001621 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622
1623 BT_DBG("sk %p, parent %p", sk, parent);
1624
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001625 chan->conf_state = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 l2cap_sock_clear_timer(sk);
1627
1628 if (!parent) {
1629 /* Outgoing channel.
1630 * Wake up socket sleeping on connect.
1631 */
1632 sk->sk_state = BT_CONNECTED;
1633 sk->sk_state_change(sk);
1634 } else {
1635 /* Incoming channel.
1636 * Wake up socket sleeping on accept.
1637 */
1638 parent->sk_data_ready(parent, 0);
1639 }
1640}
1641
1642/* Copy frame to all raw sockets on that connection */
1643static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1644{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001646 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647
1648 BT_DBG("conn %p", conn);
1649
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001650 read_lock(&conn->chan_lock);
1651 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001652 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653 if (sk->sk_type != SOCK_RAW)
1654 continue;
1655
1656 /* Don't send frame to the socket it came from */
1657 if (skb->sk == sk)
1658 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001659 nskb = skb_clone(skb, GFP_ATOMIC);
1660 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 continue;
1662
1663 if (sock_queue_rcv_skb(sk, nskb))
1664 kfree_skb(nskb);
1665 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001666 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667}
1668
1669/* ---- L2CAP signalling commands ---- */
1670static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1671 u8 code, u8 ident, u16 dlen, void *data)
1672{
1673 struct sk_buff *skb, **frag;
1674 struct l2cap_cmd_hdr *cmd;
1675 struct l2cap_hdr *lh;
1676 int len, count;
1677
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001678 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1679 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680
1681 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1682 count = min_t(unsigned int, conn->mtu, len);
1683
1684 skb = bt_skb_alloc(count, GFP_ATOMIC);
1685 if (!skb)
1686 return NULL;
1687
1688 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001689 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001690
1691 if (conn->hcon->type == LE_LINK)
1692 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1693 else
1694 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695
1696 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1697 cmd->code = code;
1698 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001699 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700
1701 if (dlen) {
1702 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1703 memcpy(skb_put(skb, count), data, count);
1704 data += count;
1705 }
1706
1707 len -= skb->len;
1708
1709 /* Continuation fragments (no L2CAP header) */
1710 frag = &skb_shinfo(skb)->frag_list;
1711 while (len) {
1712 count = min_t(unsigned int, conn->mtu, len);
1713
1714 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1715 if (!*frag)
1716 goto fail;
1717
1718 memcpy(skb_put(*frag, count), data, count);
1719
1720 len -= count;
1721 data += count;
1722
1723 frag = &(*frag)->next;
1724 }
1725
1726 return skb;
1727
1728fail:
1729 kfree_skb(skb);
1730 return NULL;
1731}
1732
1733static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1734{
1735 struct l2cap_conf_opt *opt = *ptr;
1736 int len;
1737
1738 len = L2CAP_CONF_OPT_SIZE + opt->len;
1739 *ptr += len;
1740
1741 *type = opt->type;
1742 *olen = opt->len;
1743
1744 switch (opt->len) {
1745 case 1:
1746 *val = *((u8 *) opt->val);
1747 break;
1748
1749 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001750 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 break;
1752
1753 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001754 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 break;
1756
1757 default:
1758 *val = (unsigned long) opt->val;
1759 break;
1760 }
1761
1762 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1763 return len;
1764}
1765
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1767{
1768 struct l2cap_conf_opt *opt = *ptr;
1769
1770 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1771
1772 opt->type = type;
1773 opt->len = len;
1774
1775 switch (len) {
1776 case 1:
1777 *((u8 *) opt->val) = val;
1778 break;
1779
1780 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001781 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782 break;
1783
1784 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001785 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786 break;
1787
1788 default:
1789 memcpy(opt->val, (void *) val, len);
1790 break;
1791 }
1792
1793 *ptr += L2CAP_CONF_OPT_SIZE + len;
1794}
1795
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001796static void l2cap_ack_timeout(unsigned long arg)
1797{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001798 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001799
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001800 bh_lock_sock(chan->sk);
1801 l2cap_send_ack(chan);
1802 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001803}
1804
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001805static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001806{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001807 struct sock *sk = chan->sk;
1808
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001809 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001810 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001811 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001812 chan->num_acked = 0;
1813 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001814
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001815 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1816 (unsigned long) chan);
1817 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1818 (unsigned long) chan);
1819 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001820
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001821 skb_queue_head_init(&chan->srej_q);
1822 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001823
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001824 INIT_LIST_HEAD(&chan->srej_l);
1825
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001826 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001827
1828 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001829}
1830
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001831static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1832{
1833 switch (mode) {
1834 case L2CAP_MODE_STREAMING:
1835 case L2CAP_MODE_ERTM:
1836 if (l2cap_mode_supported(mode, remote_feat_mask))
1837 return mode;
1838 /* fall through */
1839 default:
1840 return L2CAP_MODE_BASIC;
1841 }
1842}
1843
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001844static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001847 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 void *ptr = req->data;
1849
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001850 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001852 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001853 goto done;
1854
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001855 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001856 case L2CAP_MODE_STREAMING:
1857 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001858 if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001859 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001860
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001861 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001862 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001863 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001864 break;
1865 }
1866
1867done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001868 if (chan->imtu != L2CAP_DEFAULT_MTU)
1869 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001870
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001871 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001872 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001873 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1874 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001875 break;
1876
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001877 rfc.mode = L2CAP_MODE_BASIC;
1878 rfc.txwin_size = 0;
1879 rfc.max_transmit = 0;
1880 rfc.retrans_timeout = 0;
1881 rfc.monitor_timeout = 0;
1882 rfc.max_pdu_size = 0;
1883
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001884 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1885 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001886 break;
1887
1888 case L2CAP_MODE_ERTM:
1889 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001890 rfc.txwin_size = chan->tx_win;
1891 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001892 rfc.retrans_timeout = 0;
1893 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001894 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001895 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1896 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001897
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001898 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1899 (unsigned long) &rfc);
1900
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001901 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001902 break;
1903
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001904 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001905 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001906 chan->fcs = L2CAP_FCS_NONE;
1907 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001908 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001909 break;
1910
1911 case L2CAP_MODE_STREAMING:
1912 rfc.mode = L2CAP_MODE_STREAMING;
1913 rfc.txwin_size = 0;
1914 rfc.max_transmit = 0;
1915 rfc.retrans_timeout = 0;
1916 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001917 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001918 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1919 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001920
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001921 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1922 (unsigned long) &rfc);
1923
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001924 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001925 break;
1926
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001927 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001928 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001929 chan->fcs = L2CAP_FCS_NONE;
1930 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001931 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001932 break;
1933 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001935 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001936 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937
1938 return ptr - data;
1939}
1940
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001941static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001943 struct l2cap_conf_rsp *rsp = data;
1944 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001945 void *req = chan->conf_req;
1946 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001947 int type, hint, olen;
1948 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001949 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001950 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001951 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001953 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001954
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001955 while (len >= L2CAP_CONF_OPT_SIZE) {
1956 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001958 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001959 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001960
1961 switch (type) {
1962 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001963 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001964 break;
1965
1966 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001967 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001968 break;
1969
1970 case L2CAP_CONF_QOS:
1971 break;
1972
Marcel Holtmann6464f352007-10-20 13:39:51 +02001973 case L2CAP_CONF_RFC:
1974 if (olen == sizeof(rfc))
1975 memcpy(&rfc, (void *) val, olen);
1976 break;
1977
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001978 case L2CAP_CONF_FCS:
1979 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001980 chan->conf_state |= L2CAP_CONF_NO_FCS_RECV;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001981
1982 break;
1983
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001984 default:
1985 if (hint)
1986 break;
1987
1988 result = L2CAP_CONF_UNKNOWN;
1989 *((u8 *) ptr++) = type;
1990 break;
1991 }
1992 }
1993
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001994 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001995 goto done;
1996
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001997 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001998 case L2CAP_MODE_STREAMING:
1999 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002000 if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002001 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002002 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002003 break;
2004 }
2005
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002006 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002007 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002008
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002009 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002010 }
2011
2012done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002013 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002014 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002015 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002016
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002017 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002018 return -ECONNREFUSED;
2019
2020 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2021 sizeof(rfc), (unsigned long) &rfc);
2022 }
2023
2024
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002025 if (result == L2CAP_CONF_SUCCESS) {
2026 /* Configure output options and let the other side know
2027 * which ones we don't like. */
2028
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002029 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2030 result = L2CAP_CONF_UNACCEPT;
2031 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002032 chan->omtu = mtu;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002033 chan->conf_state |= L2CAP_CONF_MTU_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002034 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002035 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002036
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002037 switch (rfc.mode) {
2038 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002039 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002040 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002041 break;
2042
2043 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002044 chan->remote_tx_win = rfc.txwin_size;
2045 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002046
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002047 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2048 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002049
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002050 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002051
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002052 rfc.retrans_timeout =
2053 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2054 rfc.monitor_timeout =
2055 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002056
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002057 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002058
2059 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2060 sizeof(rfc), (unsigned long) &rfc);
2061
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002062 break;
2063
2064 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002065 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2066 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002067
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002068 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002069
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002070 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002071
2072 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2073 sizeof(rfc), (unsigned long) &rfc);
2074
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002075 break;
2076
2077 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002078 result = L2CAP_CONF_UNACCEPT;
2079
2080 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002081 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002082 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002083
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002084 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002085 chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002086 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002087 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002088 rsp->result = cpu_to_le16(result);
2089 rsp->flags = cpu_to_le16(0x0000);
2090
2091 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092}
2093
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002094static 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 -03002095{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002096 struct l2cap_conf_req *req = data;
2097 void *ptr = req->data;
2098 int type, olen;
2099 unsigned long val;
2100 struct l2cap_conf_rfc rfc;
2101
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002102 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002103
2104 while (len >= L2CAP_CONF_OPT_SIZE) {
2105 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2106
2107 switch (type) {
2108 case L2CAP_CONF_MTU:
2109 if (val < L2CAP_DEFAULT_MIN_MTU) {
2110 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002111 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002112 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002113 chan->imtu = val;
2114 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002115 break;
2116
2117 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002118 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002119 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002120 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002121 break;
2122
2123 case L2CAP_CONF_RFC:
2124 if (olen == sizeof(rfc))
2125 memcpy(&rfc, (void *)val, olen);
2126
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002127 if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002128 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002129 return -ECONNREFUSED;
2130
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002131 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002132
2133 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2134 sizeof(rfc), (unsigned long) &rfc);
2135 break;
2136 }
2137 }
2138
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002139 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002140 return -ECONNREFUSED;
2141
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002142 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002143
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002144 if (*result == L2CAP_CONF_SUCCESS) {
2145 switch (rfc.mode) {
2146 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002147 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2148 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2149 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002150 break;
2151 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002152 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002153 }
2154 }
2155
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002156 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002157 req->flags = cpu_to_le16(0x0000);
2158
2159 return ptr - data;
2160}
2161
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002162static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163{
2164 struct l2cap_conf_rsp *rsp = data;
2165 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002167 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002169 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002170 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002171 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172
2173 return ptr - data;
2174}
2175
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002176void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002177{
2178 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002179 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002180 u8 buf[128];
2181
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002182 rsp.scid = cpu_to_le16(chan->dcid);
2183 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002184 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2185 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2186 l2cap_send_cmd(conn, chan->ident,
2187 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2188
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002189 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002190 return;
2191
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002192 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002193 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2194 l2cap_build_conf_req(chan, buf), buf);
2195 chan->num_conf_req++;
2196}
2197
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002198static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002199{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002200 int type, olen;
2201 unsigned long val;
2202 struct l2cap_conf_rfc rfc;
2203
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002204 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002205
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002206 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002207 return;
2208
2209 while (len >= L2CAP_CONF_OPT_SIZE) {
2210 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2211
2212 switch (type) {
2213 case L2CAP_CONF_RFC:
2214 if (olen == sizeof(rfc))
2215 memcpy(&rfc, (void *)val, olen);
2216 goto done;
2217 }
2218 }
2219
2220done:
2221 switch (rfc.mode) {
2222 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002223 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2224 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2225 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002226 break;
2227 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002228 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002229 }
2230}
2231
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002232static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2233{
2234 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2235
2236 if (rej->reason != 0x0000)
2237 return 0;
2238
2239 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2240 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002241 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002242
2243 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002244 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002245
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002246 l2cap_conn_start(conn);
2247 }
2248
2249 return 0;
2250}
2251
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2253{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2255 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002256 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002257 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002258 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259
2260 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002261 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262
2263 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2264
2265 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002266 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2267 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268 result = L2CAP_CR_BAD_PSM;
2269 goto sendresp;
2270 }
2271
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002272 parent = pchan->sk;
2273
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002274 bh_lock_sock(parent);
2275
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002276 /* Check if the ACL is secure enough (if not SDP) */
2277 if (psm != cpu_to_le16(0x0001) &&
2278 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002279 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002280 result = L2CAP_CR_SEC_BLOCK;
2281 goto response;
2282 }
2283
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284 result = L2CAP_CR_NO_MEM;
2285
2286 /* Check for backlog size */
2287 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002288 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289 goto response;
2290 }
2291
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002292 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293 if (!sk)
2294 goto response;
2295
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002296 chan = l2cap_chan_create(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002297 if (!chan) {
2298 l2cap_sock_kill(sk);
2299 goto response;
2300 }
2301
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03002302 l2cap_pi(sk)->chan = chan;
2303
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002304 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305
2306 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002307 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2308 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 sock_set_flag(sk, SOCK_ZAPPED);
2310 l2cap_sock_kill(sk);
2311 goto response;
2312 }
2313
2314 hci_conn_hold(conn->hcon);
2315
2316 l2cap_sock_init(sk, parent);
2317 bacpy(&bt_sk(sk)->src, conn->src);
2318 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002319 chan->psm = psm;
2320 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002322 bt_accept_enqueue(parent, sk);
2323
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002324 __l2cap_chan_add(conn, chan);
2325
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002326 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327
2328 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2329
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002330 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331
Marcel Holtmann984947d2009-02-06 23:35:19 +01002332 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002333 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002334 if (bt_sk(sk)->defer_setup) {
2335 sk->sk_state = BT_CONNECT2;
2336 result = L2CAP_CR_PEND;
2337 status = L2CAP_CS_AUTHOR_PEND;
2338 parent->sk_data_ready(parent, 0);
2339 } else {
2340 sk->sk_state = BT_CONFIG;
2341 result = L2CAP_CR_SUCCESS;
2342 status = L2CAP_CS_NO_INFO;
2343 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002344 } else {
2345 sk->sk_state = BT_CONNECT2;
2346 result = L2CAP_CR_PEND;
2347 status = L2CAP_CS_AUTHEN_PEND;
2348 }
2349 } else {
2350 sk->sk_state = BT_CONNECT2;
2351 result = L2CAP_CR_PEND;
2352 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353 }
2354
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002355 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356
2357response:
2358 bh_unlock_sock(parent);
2359
2360sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002361 rsp.scid = cpu_to_le16(scid);
2362 rsp.dcid = cpu_to_le16(dcid);
2363 rsp.result = cpu_to_le16(result);
2364 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002366
2367 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2368 struct l2cap_info_req info;
2369 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2370
2371 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2372 conn->info_ident = l2cap_get_ident(conn);
2373
2374 mod_timer(&conn->info_timer, jiffies +
2375 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2376
2377 l2cap_send_cmd(conn, conn->info_ident,
2378 L2CAP_INFO_REQ, sizeof(info), &info);
2379 }
2380
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002381 if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002382 result == L2CAP_CR_SUCCESS) {
2383 u8 buf[128];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002384 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002385 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002386 l2cap_build_conf_req(chan, buf), buf);
2387 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002388 }
2389
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 return 0;
2391}
2392
2393static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2394{
2395 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2396 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002397 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 struct sock *sk;
2399 u8 req[128];
2400
2401 scid = __le16_to_cpu(rsp->scid);
2402 dcid = __le16_to_cpu(rsp->dcid);
2403 result = __le16_to_cpu(rsp->result);
2404 status = __le16_to_cpu(rsp->status);
2405
2406 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2407
2408 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002409 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002410 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002411 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002413 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002414 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002415 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416 }
2417
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002418 sk = chan->sk;
2419
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420 switch (result) {
2421 case L2CAP_CR_SUCCESS:
2422 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002423 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002424 chan->dcid = dcid;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002425 chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002426
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002427 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002428 break;
2429
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002430 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002431
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002433 l2cap_build_conf_req(chan, req), req);
2434 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 break;
2436
2437 case L2CAP_CR_PEND:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002438 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439 break;
2440
2441 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002442 /* don't delete l2cap channel if sk is owned by user */
2443 if (sock_owned_by_user(sk)) {
2444 sk->sk_state = BT_DISCONN;
2445 l2cap_sock_clear_timer(sk);
2446 l2cap_sock_set_timer(sk, HZ / 5);
2447 break;
2448 }
2449
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002450 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 break;
2452 }
2453
2454 bh_unlock_sock(sk);
2455 return 0;
2456}
2457
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002458static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002459{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002460 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
2461
Mat Martineau8c462b62010-08-24 15:35:42 -07002462 /* FCS is enabled only in ERTM or streaming mode, if one or both
2463 * sides request it.
2464 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002465 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002466 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002467 else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002468 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002469}
2470
Al Viro88219a02007-07-29 00:17:25 -07002471static 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 -07002472{
2473 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2474 u16 dcid, flags;
2475 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002476 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002478 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479
2480 dcid = __le16_to_cpu(req->dcid);
2481 flags = __le16_to_cpu(req->flags);
2482
2483 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2484
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002485 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002486 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487 return -ENOENT;
2488
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002489 sk = chan->sk;
2490
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002491 if (sk->sk_state != BT_CONFIG) {
2492 struct l2cap_cmd_rej rej;
2493
2494 rej.reason = cpu_to_le16(0x0002);
2495 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2496 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002497 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002498 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002499
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002500 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002501 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002502 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002503 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002504 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002505 L2CAP_CONF_REJECT, flags), rsp);
2506 goto unlock;
2507 }
2508
2509 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002510 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2511 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512
2513 if (flags & 0x0001) {
2514 /* Incomplete config. Send empty response. */
2515 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002516 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002517 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518 goto unlock;
2519 }
2520
2521 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002522 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002523 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002524 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002526 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002528 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002529 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002530
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002531 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002532 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002533
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002534 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002535 goto unlock;
2536
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002537 if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002538 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002539
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002541
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002542 chan->next_tx_seq = 0;
2543 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002544 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002545 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002546 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002547
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002549 goto unlock;
2550 }
2551
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002552 if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002553 u8 buf[64];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002554 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002556 l2cap_build_conf_req(chan, buf), buf);
2557 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558 }
2559
2560unlock:
2561 bh_unlock_sock(sk);
2562 return 0;
2563}
2564
2565static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2566{
2567 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2568 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002569 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002571 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572
2573 scid = __le16_to_cpu(rsp->scid);
2574 flags = __le16_to_cpu(rsp->flags);
2575 result = __le16_to_cpu(rsp->result);
2576
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002577 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2578 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002580 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002581 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582 return 0;
2583
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002584 sk = chan->sk;
2585
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 switch (result) {
2587 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002588 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589 break;
2590
2591 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002592 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002593 char req[64];
2594
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002595 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002596 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002597 goto done;
2598 }
2599
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002600 /* throw out any old stored conf requests */
2601 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002602 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2603 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002604 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002605 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002606 goto done;
2607 }
2608
2609 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2610 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002611 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002612 if (result != L2CAP_CONF_SUCCESS)
2613 goto done;
2614 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615 }
2616
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002617 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002618 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002620 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621 goto done;
2622 }
2623
2624 if (flags & 0x01)
2625 goto done;
2626
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002627 chan->conf_state |= L2CAP_CONF_INPUT_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002629 if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002630 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002631
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002633 chan->next_tx_seq = 0;
2634 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002635 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002636 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002637 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002638
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639 l2cap_chan_ready(sk);
2640 }
2641
2642done:
2643 bh_unlock_sock(sk);
2644 return 0;
2645}
2646
2647static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2648{
2649 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2650 struct l2cap_disconn_rsp rsp;
2651 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002652 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653 struct sock *sk;
2654
2655 scid = __le16_to_cpu(req->scid);
2656 dcid = __le16_to_cpu(req->dcid);
2657
2658 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2659
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002660 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002661 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 return 0;
2663
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002664 sk = chan->sk;
2665
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002666 rsp.dcid = cpu_to_le16(chan->scid);
2667 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2669
2670 sk->sk_shutdown = SHUTDOWN_MASK;
2671
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002672 /* don't delete l2cap channel if sk is owned by user */
2673 if (sock_owned_by_user(sk)) {
2674 sk->sk_state = BT_DISCONN;
2675 l2cap_sock_clear_timer(sk);
2676 l2cap_sock_set_timer(sk, HZ / 5);
2677 bh_unlock_sock(sk);
2678 return 0;
2679 }
2680
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002681 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682 bh_unlock_sock(sk);
2683
2684 l2cap_sock_kill(sk);
2685 return 0;
2686}
2687
2688static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2689{
2690 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2691 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002692 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693 struct sock *sk;
2694
2695 scid = __le16_to_cpu(rsp->scid);
2696 dcid = __le16_to_cpu(rsp->dcid);
2697
2698 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2699
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002700 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002701 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 return 0;
2703
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002704 sk = chan->sk;
2705
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002706 /* don't delete l2cap channel if sk is owned by user */
2707 if (sock_owned_by_user(sk)) {
2708 sk->sk_state = BT_DISCONN;
2709 l2cap_sock_clear_timer(sk);
2710 l2cap_sock_set_timer(sk, HZ / 5);
2711 bh_unlock_sock(sk);
2712 return 0;
2713 }
2714
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002715 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716 bh_unlock_sock(sk);
2717
2718 l2cap_sock_kill(sk);
2719 return 0;
2720}
2721
2722static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2723{
2724 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725 u16 type;
2726
2727 type = __le16_to_cpu(req->type);
2728
2729 BT_DBG("type 0x%4.4x", type);
2730
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002731 if (type == L2CAP_IT_FEAT_MASK) {
2732 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002733 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002734 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2735 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2736 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002737 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002738 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2739 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002740 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002741 l2cap_send_cmd(conn, cmd->ident,
2742 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002743 } else if (type == L2CAP_IT_FIXED_CHAN) {
2744 u8 buf[12];
2745 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2746 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2747 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2748 memcpy(buf + 4, l2cap_fixed_chan, 8);
2749 l2cap_send_cmd(conn, cmd->ident,
2750 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002751 } else {
2752 struct l2cap_info_rsp rsp;
2753 rsp.type = cpu_to_le16(type);
2754 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2755 l2cap_send_cmd(conn, cmd->ident,
2756 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2757 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758
2759 return 0;
2760}
2761
2762static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2763{
2764 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2765 u16 type, result;
2766
2767 type = __le16_to_cpu(rsp->type);
2768 result = __le16_to_cpu(rsp->result);
2769
2770 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2771
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002772 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2773 if (cmd->ident != conn->info_ident ||
2774 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2775 return 0;
2776
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002777 del_timer(&conn->info_timer);
2778
Ville Tervoadb08ed2010-08-04 09:43:33 +03002779 if (result != L2CAP_IR_SUCCESS) {
2780 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2781 conn->info_ident = 0;
2782
2783 l2cap_conn_start(conn);
2784
2785 return 0;
2786 }
2787
Marcel Holtmann984947d2009-02-06 23:35:19 +01002788 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002789 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002790
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002791 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002792 struct l2cap_info_req req;
2793 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2794
2795 conn->info_ident = l2cap_get_ident(conn);
2796
2797 l2cap_send_cmd(conn, conn->info_ident,
2798 L2CAP_INFO_REQ, sizeof(req), &req);
2799 } else {
2800 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2801 conn->info_ident = 0;
2802
2803 l2cap_conn_start(conn);
2804 }
2805 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002806 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002807 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002808
2809 l2cap_conn_start(conn);
2810 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002811
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812 return 0;
2813}
2814
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002815static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002816 u16 to_multiplier)
2817{
2818 u16 max_latency;
2819
2820 if (min > max || min < 6 || max > 3200)
2821 return -EINVAL;
2822
2823 if (to_multiplier < 10 || to_multiplier > 3200)
2824 return -EINVAL;
2825
2826 if (max >= to_multiplier * 8)
2827 return -EINVAL;
2828
2829 max_latency = (to_multiplier * 8 / max) - 1;
2830 if (latency > 499 || latency > max_latency)
2831 return -EINVAL;
2832
2833 return 0;
2834}
2835
2836static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2837 struct l2cap_cmd_hdr *cmd, u8 *data)
2838{
2839 struct hci_conn *hcon = conn->hcon;
2840 struct l2cap_conn_param_update_req *req;
2841 struct l2cap_conn_param_update_rsp rsp;
2842 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002843 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002844
2845 if (!(hcon->link_mode & HCI_LM_MASTER))
2846 return -EINVAL;
2847
2848 cmd_len = __le16_to_cpu(cmd->len);
2849 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2850 return -EPROTO;
2851
2852 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002853 min = __le16_to_cpu(req->min);
2854 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002855 latency = __le16_to_cpu(req->latency);
2856 to_multiplier = __le16_to_cpu(req->to_multiplier);
2857
2858 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2859 min, max, latency, to_multiplier);
2860
2861 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002862
2863 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2864 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002865 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2866 else
2867 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2868
2869 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2870 sizeof(rsp), &rsp);
2871
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002872 if (!err)
2873 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2874
Claudio Takahaside731152011-02-11 19:28:55 -02002875 return 0;
2876}
2877
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002878static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2879 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2880{
2881 int err = 0;
2882
2883 switch (cmd->code) {
2884 case L2CAP_COMMAND_REJ:
2885 l2cap_command_rej(conn, cmd, data);
2886 break;
2887
2888 case L2CAP_CONN_REQ:
2889 err = l2cap_connect_req(conn, cmd, data);
2890 break;
2891
2892 case L2CAP_CONN_RSP:
2893 err = l2cap_connect_rsp(conn, cmd, data);
2894 break;
2895
2896 case L2CAP_CONF_REQ:
2897 err = l2cap_config_req(conn, cmd, cmd_len, data);
2898 break;
2899
2900 case L2CAP_CONF_RSP:
2901 err = l2cap_config_rsp(conn, cmd, data);
2902 break;
2903
2904 case L2CAP_DISCONN_REQ:
2905 err = l2cap_disconnect_req(conn, cmd, data);
2906 break;
2907
2908 case L2CAP_DISCONN_RSP:
2909 err = l2cap_disconnect_rsp(conn, cmd, data);
2910 break;
2911
2912 case L2CAP_ECHO_REQ:
2913 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2914 break;
2915
2916 case L2CAP_ECHO_RSP:
2917 break;
2918
2919 case L2CAP_INFO_REQ:
2920 err = l2cap_information_req(conn, cmd, data);
2921 break;
2922
2923 case L2CAP_INFO_RSP:
2924 err = l2cap_information_rsp(conn, cmd, data);
2925 break;
2926
2927 default:
2928 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2929 err = -EINVAL;
2930 break;
2931 }
2932
2933 return err;
2934}
2935
2936static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2937 struct l2cap_cmd_hdr *cmd, u8 *data)
2938{
2939 switch (cmd->code) {
2940 case L2CAP_COMMAND_REJ:
2941 return 0;
2942
2943 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002944 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002945
2946 case L2CAP_CONN_PARAM_UPDATE_RSP:
2947 return 0;
2948
2949 default:
2950 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2951 return -EINVAL;
2952 }
2953}
2954
2955static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2956 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957{
2958 u8 *data = skb->data;
2959 int len = skb->len;
2960 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002961 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962
2963 l2cap_raw_recv(conn, skb);
2964
2965 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002966 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2968 data += L2CAP_CMD_HDR_SIZE;
2969 len -= L2CAP_CMD_HDR_SIZE;
2970
Al Viro88219a02007-07-29 00:17:25 -07002971 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972
Al Viro88219a02007-07-29 00:17:25 -07002973 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 -07002974
Al Viro88219a02007-07-29 00:17:25 -07002975 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976 BT_DBG("corrupted command");
2977 break;
2978 }
2979
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002980 if (conn->hcon->type == LE_LINK)
2981 err = l2cap_le_sig_cmd(conn, &cmd, data);
2982 else
2983 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002984
2985 if (err) {
2986 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002987
2988 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989
2990 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002991 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2993 }
2994
Al Viro88219a02007-07-29 00:17:25 -07002995 data += cmd_len;
2996 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997 }
2998
2999 kfree_skb(skb);
3000}
3001
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003002static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003003{
3004 u16 our_fcs, rcv_fcs;
3005 int hdr_size = L2CAP_HDR_SIZE + 2;
3006
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003007 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003008 skb_trim(skb, skb->len - 2);
3009 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3010 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3011
3012 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003013 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003014 }
3015 return 0;
3016}
3017
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003018static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003019{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003020 u16 control = 0;
3021
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003022 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003023
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003024 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003025
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003026 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003027 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003028 l2cap_send_sframe(chan, control);
3029 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003030 }
3031
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003032 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
3033 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003034
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003035 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003036
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003037 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003038 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003039 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003040 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003041 }
3042}
3043
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003044static 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 -03003045{
3046 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03003047 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003048
3049 bt_cb(skb)->tx_seq = tx_seq;
3050 bt_cb(skb)->sar = sar;
3051
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003052 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003053 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003054 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003055 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003056 }
3057
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003058 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03003059 if (tx_seq_offset < 0)
3060 tx_seq_offset += 64;
3061
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003062 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003063 if (bt_cb(next_skb)->tx_seq == tx_seq)
3064 return -EINVAL;
3065
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03003066 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003067 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03003068 if (next_tx_seq_offset < 0)
3069 next_tx_seq_offset += 64;
3070
3071 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003072 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003073 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003074 }
3075
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003076 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003077 break;
3078
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003079 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003080
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003081 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003082
3083 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003084}
3085
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003086static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003087{
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003088 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003089 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003090
3091 switch (control & L2CAP_CTRL_SAR) {
3092 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003093 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003094 goto drop;
3095
Ruiyi Zhang224f8af2011-05-13 13:07:52 +08003096 return sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003097
3098 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003099 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003100 goto drop;
3101
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003102 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003103
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003104 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003105 goto disconnect;
3106
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003107 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3108 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003109 return -ENOMEM;
3110
3111 /* pull sdu_len bytes only after alloc, because of Local Busy
3112 * condition we have to be sure that this will be executed
3113 * only once, i.e., when alloc does not fail */
3114 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003115
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003116 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003117
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003118 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003119 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003120 break;
3121
3122 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003123 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003124 goto disconnect;
3125
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003126 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003127 goto disconnect;
3128
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003129 chan->partial_sdu_len += skb->len;
3130 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003131 goto drop;
3132
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003133 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003134
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003135 break;
3136
3137 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003138 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003139 goto disconnect;
3140
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003141 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003142 goto disconnect;
3143
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003144 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003145 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003146
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003147 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003148 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003149
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003150 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003151 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003152
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003153 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003154 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003155
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003156 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003157 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003158 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003159 return -ENOMEM;
3160 }
3161
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003162 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003163 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003164 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003165 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003166 return err;
3167 }
3168
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003169 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
3170 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003171
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003172 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003173 break;
3174 }
3175
3176 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003177 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003178
3179drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003180 kfree_skb(chan->sdu);
3181 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003182
3183disconnect:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003184 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003185 kfree_skb(skb);
3186 return 0;
3187}
3188
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003189static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003190{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003191 struct sk_buff *skb;
3192 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003193 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003194
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003195 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003196 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003197 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003198 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003199 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003200 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003201 }
3202
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003203 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003204 }
3205
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003206 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003207 goto done;
3208
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003209 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003210 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003211 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003212 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003213
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003214 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003215 __mod_monitor_timer();
3216
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003217 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003218
3219done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003220 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3221 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003222
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003223 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003224
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003225 return 0;
3226}
3227
3228static void l2cap_busy_work(struct work_struct *work)
3229{
3230 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003231 struct l2cap_chan *chan =
3232 container_of(work, struct l2cap_chan, busy_work);
3233 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003234 int n_tries = 0, timeo = HZ/5, err;
3235 struct sk_buff *skb;
3236
3237 lock_sock(sk);
3238
3239 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003240 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003241 set_current_state(TASK_INTERRUPTIBLE);
3242
3243 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3244 err = -EBUSY;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003245 l2cap_send_disconn_req(chan->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003246 break;
3247 }
3248
3249 if (!timeo)
3250 timeo = HZ/5;
3251
3252 if (signal_pending(current)) {
3253 err = sock_intr_errno(timeo);
3254 break;
3255 }
3256
3257 release_sock(sk);
3258 timeo = schedule_timeout(timeo);
3259 lock_sock(sk);
3260
3261 err = sock_error(sk);
3262 if (err)
3263 break;
3264
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003265 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003266 break;
3267 }
3268
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003269 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003270 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003271
3272 release_sock(sk);
3273}
3274
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003275static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003276{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003277 int sctrl, err;
3278
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003279 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003280 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003281 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003282 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003283
3284
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003285 }
3286
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003287 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003288 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003289 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003290 return err;
3291 }
3292
3293 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003294 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003295
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003296 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003297 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003298 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003299
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003300 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003301 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003302 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003303
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003304 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003305
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003306 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003307
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003308 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003309
3310 return err;
3311}
3312
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003313static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003314{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003315 struct sk_buff *_skb;
3316 int err = -EINVAL;
3317
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003318 /*
3319 * TODO: We have to notify the userland if some data is lost with the
3320 * Streaming Mode.
3321 */
3322
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003323 switch (control & L2CAP_CTRL_SAR) {
3324 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003325 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003326 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003327 break;
3328 }
3329
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003330 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003331 if (!err)
3332 return 0;
3333
3334 break;
3335
3336 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003337 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003338 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003339 break;
3340 }
3341
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003342 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003343 skb_pull(skb, 2);
3344
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003345 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003346 err = -EMSGSIZE;
3347 break;
3348 }
3349
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003350 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3351 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003352 err = -ENOMEM;
3353 break;
3354 }
3355
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003356 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003357
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003358 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003359 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003360 err = 0;
3361 break;
3362
3363 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003364 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003365 break;
3366
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003367 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003368
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003369 chan->partial_sdu_len += skb->len;
3370 if (chan->partial_sdu_len > chan->sdu_len)
3371 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003372 else
3373 err = 0;
3374
3375 break;
3376
3377 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003378 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003379 break;
3380
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003381 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003382
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003383 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003384 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003385
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003386 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003387 goto drop;
3388
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003389 if (chan->partial_sdu_len == chan->sdu_len) {
3390 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003391 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003392 if (err < 0)
3393 kfree_skb(_skb);
3394 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003395 err = 0;
3396
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003397drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003398 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003399 break;
3400 }
3401
3402 kfree_skb(skb);
3403 return err;
3404}
3405
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003406static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003407{
3408 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003409 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003410
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003411 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003412 if (bt_cb(skb)->tx_seq != tx_seq)
3413 break;
3414
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003415 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003416 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003417 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003418 chan->buffer_seq_srej =
3419 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003420 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003421 }
3422}
3423
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003424static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003425{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003426 struct srej_list *l, *tmp;
3427 u16 control;
3428
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003429 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003430 if (l->tx_seq == tx_seq) {
3431 list_del(&l->list);
3432 kfree(l);
3433 return;
3434 }
3435 control = L2CAP_SUPER_SELECT_REJECT;
3436 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003437 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003438 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003439 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003440 }
3441}
3442
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003443static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003444{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003445 struct srej_list *new;
3446 u16 control;
3447
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003448 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003449 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003450 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003451 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003452
3453 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003454 new->tx_seq = chan->expected_tx_seq;
3455 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003456 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003457 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003458 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003459}
3460
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003461static 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 -03003462{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003463 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003464 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003465 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003466 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003467 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003468 int err = 0;
3469
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003470 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3471 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003472
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003473 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003474 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003475 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003476 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003477 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003478 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003479 }
3480
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003481 chan->expected_ack_seq = req_seq;
3482 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003483
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003484 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003485 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003486
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003487 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003488 if (tx_seq_offset < 0)
3489 tx_seq_offset += 64;
3490
3491 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003492 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003493 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003494 goto drop;
3495 }
3496
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003497 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003498 goto drop;
3499
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003500 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003501 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003502
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003503 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003504 struct srej_list, list);
3505 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003506 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003507 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003508
3509 list_del(&first->list);
3510 kfree(first);
3511
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003512 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003513 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003514 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3515 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003516 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003517 }
3518 } else {
3519 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003520
3521 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003522 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003523 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003524
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003525 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003526 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003527 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003528 return 0;
3529 }
3530 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003531 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003532 }
3533 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003534 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003535 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003536 if (expected_tx_seq_offset < 0)
3537 expected_tx_seq_offset += 64;
3538
3539 /* duplicated tx_seq */
3540 if (tx_seq_offset < expected_tx_seq_offset)
3541 goto drop;
3542
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003543 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003544
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003545 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003546
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003547 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003548 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003549
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003550 __skb_queue_head_init(&chan->srej_q);
3551 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003552 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003553
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003554 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003555
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003556 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003557
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003558 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003559 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003560 return 0;
3561
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003562expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003563 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003564
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003565 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003566 bt_cb(skb)->tx_seq = tx_seq;
3567 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003568 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003569 return 0;
3570 }
3571
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003572 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003573 if (err < 0)
3574 return 0;
3575
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003576 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003577 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3578 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003579 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003580 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003581 }
3582
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003583 __mod_ack_timer();
3584
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003585 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3586 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003587 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003588
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003589 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003590
3591drop:
3592 kfree_skb(skb);
3593 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003594}
3595
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003596static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003597{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003598 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003599 rx_control);
3600
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003601 chan->expected_ack_seq = __get_reqseq(rx_control);
3602 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003603
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003604 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003605 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3606 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3607 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003608 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003609 __mod_retrans_timer();
3610
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003611 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3612 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003613 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003614 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003615 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003616
3617 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003618 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003619
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003620 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3621 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003622 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003623 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003624
3625 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003626 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003627 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003628 __mod_retrans_timer();
3629
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003630 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3631 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3632 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003633 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003634 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003635 }
3636}
3637
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003638static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003639{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003640 u8 tx_seq = __get_reqseq(rx_control);
3641
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003642 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003643
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003644 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003645
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003646 chan->expected_ack_seq = tx_seq;
3647 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003648
3649 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003650 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3651 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003652 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003653 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003654 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003655 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003656
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003657 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3658 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003659 }
3660}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003661static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003662{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003663 u8 tx_seq = __get_reqseq(rx_control);
3664
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003665 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003666
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003667 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003668
3669 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003670 chan->expected_ack_seq = tx_seq;
3671 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003672
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003673 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3674 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003675
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003676 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003677
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003678 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003679 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003680 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003681 }
3682 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003683 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003684 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003685 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003686 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003687 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003688 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003689 l2cap_retransmit_one_frame(chan, tx_seq);
3690 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003691 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003692 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003693 }
3694 }
3695}
3696
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003697static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003698{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003699 u8 tx_seq = __get_reqseq(rx_control);
3700
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003701 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003702
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003703 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003704 chan->expected_ack_seq = tx_seq;
3705 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003706
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003707 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003708 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003709
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003710 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003711 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003712 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003713 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003714 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003715 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003716
3717 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003718 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003719 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003720 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003721}
3722
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003723static 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 -03003724{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003725 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003726
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003727 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003728 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003729 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003730 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003731 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003732 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003733 }
3734
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003735 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3736 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003737 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003738 break;
3739
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003740 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003741 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003742 break;
3743
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003744 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003745 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003746 break;
3747
3748 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003749 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003750 break;
3751 }
3752
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003753 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003754 return 0;
3755}
3756
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003757static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3758{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003759 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003760 u16 control;
3761 u8 req_seq;
3762 int len, next_tx_seq_offset, req_seq_offset;
3763
3764 control = get_unaligned_le16(skb->data);
3765 skb_pull(skb, 2);
3766 len = skb->len;
3767
3768 /*
3769 * We can just drop the corrupted I-frame here.
3770 * Receiver will miss it and start proper recovery
3771 * procedures and ask retransmission.
3772 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003773 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003774 goto drop;
3775
3776 if (__is_sar_start(control) && __is_iframe(control))
3777 len -= 2;
3778
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003779 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003780 len -= 2;
3781
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003782 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003783 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003784 goto drop;
3785 }
3786
3787 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003788 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003789 if (req_seq_offset < 0)
3790 req_seq_offset += 64;
3791
3792 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003793 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003794 if (next_tx_seq_offset < 0)
3795 next_tx_seq_offset += 64;
3796
3797 /* check for invalid req-seq */
3798 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003799 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003800 goto drop;
3801 }
3802
3803 if (__is_iframe(control)) {
3804 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003805 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003806 goto drop;
3807 }
3808
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003809 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003810 } else {
3811 if (len != 0) {
3812 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003813 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003814 goto drop;
3815 }
3816
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003817 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003818 }
3819
3820 return 0;
3821
3822drop:
3823 kfree_skb(skb);
3824 return 0;
3825}
3826
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3828{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003829 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003830 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003831 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003832 u8 tx_seq;
3833 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003834
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003835 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003836 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837 BT_DBG("unknown cid 0x%4.4x", cid);
3838 goto drop;
3839 }
3840
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003841 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003842
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003843 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844
3845 if (sk->sk_state != BT_CONNECTED)
3846 goto drop;
3847
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003848 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003849 case L2CAP_MODE_BASIC:
3850 /* If socket recv buffers overflows we drop data here
3851 * which is *bad* because L2CAP has to be reliable.
3852 * But we don't have any other choice. L2CAP doesn't
3853 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003855 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003856 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003858 if (!sock_queue_rcv_skb(sk, skb))
3859 goto done;
3860 break;
3861
3862 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003863 if (!sock_owned_by_user(sk)) {
3864 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003865 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003866 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003867 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003868 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003869
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003870 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003871
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003872 case L2CAP_MODE_STREAMING:
3873 control = get_unaligned_le16(skb->data);
3874 skb_pull(skb, 2);
3875 len = skb->len;
3876
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003877 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003878 goto drop;
3879
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003880 if (__is_sar_start(control))
3881 len -= 2;
3882
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003883 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003884 len -= 2;
3885
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003886 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003887 goto drop;
3888
3889 tx_seq = __get_txseq(control);
3890
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003891 if (chan->expected_tx_seq == tx_seq)
3892 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003893 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003894 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003895
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003896 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003897
3898 goto done;
3899
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003900 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003901 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003902 break;
3903 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904
3905drop:
3906 kfree_skb(skb);
3907
3908done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003909 if (sk)
3910 bh_unlock_sock(sk);
3911
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912 return 0;
3913}
3914
Al Viro8e036fc2007-07-29 00:16:36 -07003915static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003917 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003918 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003920 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3921 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922 goto drop;
3923
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003924 sk = chan->sk;
3925
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003926 bh_lock_sock(sk);
3927
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928 BT_DBG("sk %p, len %d", sk, skb->len);
3929
3930 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3931 goto drop;
3932
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003933 if (l2cap_pi(sk)->chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934 goto drop;
3935
3936 if (!sock_queue_rcv_skb(sk, skb))
3937 goto done;
3938
3939drop:
3940 kfree_skb(skb);
3941
3942done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003943 if (sk)
3944 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945 return 0;
3946}
3947
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003948static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3949{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003950 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003951 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003952
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003953 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3954 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003955 goto drop;
3956
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003957 sk = chan->sk;
3958
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003959 bh_lock_sock(sk);
3960
3961 BT_DBG("sk %p, len %d", sk, skb->len);
3962
3963 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3964 goto drop;
3965
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003966 if (l2cap_pi(sk)->chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003967 goto drop;
3968
3969 if (!sock_queue_rcv_skb(sk, skb))
3970 goto done;
3971
3972drop:
3973 kfree_skb(skb);
3974
3975done:
3976 if (sk)
3977 bh_unlock_sock(sk);
3978 return 0;
3979}
3980
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3982{
3983 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003984 u16 cid, len;
3985 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986
3987 skb_pull(skb, L2CAP_HDR_SIZE);
3988 cid = __le16_to_cpu(lh->cid);
3989 len = __le16_to_cpu(lh->len);
3990
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003991 if (len != skb->len) {
3992 kfree_skb(skb);
3993 return;
3994 }
3995
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3997
3998 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003999 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004000 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004001 l2cap_sig_channel(conn, skb);
4002 break;
4003
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004004 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004005 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006 skb_pull(skb, 2);
4007 l2cap_conless_channel(conn, psm, skb);
4008 break;
4009
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004010 case L2CAP_CID_LE_DATA:
4011 l2cap_att_channel(conn, cid, skb);
4012 break;
4013
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014 default:
4015 l2cap_data_channel(conn, cid, skb);
4016 break;
4017 }
4018}
4019
4020/* ---- L2CAP interface with lower layer (HCI) ---- */
4021
4022static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4023{
4024 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004025 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026
4027 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004028 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029
4030 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4031
4032 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004033 read_lock(&chan_list_lock);
4034 list_for_each_entry(c, &chan_list, global_l) {
4035 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004036
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037 if (sk->sk_state != BT_LISTEN)
4038 continue;
4039
4040 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004041 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004042 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004043 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004045 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4046 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004047 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004048 lm2 |= HCI_LM_MASTER;
4049 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004050 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004051 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052
4053 return exact ? lm1 : lm2;
4054}
4055
4056static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4057{
Marcel Holtmann01394182006-07-03 10:02:46 +02004058 struct l2cap_conn *conn;
4059
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4061
Ville Tervoacd7d372011-02-10 22:38:49 -03004062 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004063 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064
4065 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066 conn = l2cap_conn_add(hcon, status);
4067 if (conn)
4068 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004069 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070 l2cap_conn_del(hcon, bt_err(status));
4071
4072 return 0;
4073}
4074
Marcel Holtmann2950f212009-02-12 14:02:50 +01004075static int l2cap_disconn_ind(struct hci_conn *hcon)
4076{
4077 struct l2cap_conn *conn = hcon->l2cap_data;
4078
4079 BT_DBG("hcon %p", hcon);
4080
4081 if (hcon->type != ACL_LINK || !conn)
4082 return 0x13;
4083
4084 return conn->disc_reason;
4085}
4086
4087static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004088{
4089 BT_DBG("hcon %p reason %d", hcon, reason);
4090
Ville Tervoacd7d372011-02-10 22:38:49 -03004091 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004092 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093
4094 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004095
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096 return 0;
4097}
4098
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004099static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004100{
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004101 struct sock *sk = chan->sk;
4102
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03004103 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004104 return;
4105
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004106 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004107 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004108 l2cap_sock_clear_timer(sk);
4109 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004110 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -03004111 __l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004112 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004113 if (chan->sec_level == BT_SECURITY_MEDIUM)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004114 l2cap_sock_clear_timer(sk);
4115 }
4116}
4117
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004118static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004120 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004121 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122
Marcel Holtmann01394182006-07-03 10:02:46 +02004123 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004125
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126 BT_DBG("conn %p", conn);
4127
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004128 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004130 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004131 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004132
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133 bh_lock_sock(sk);
4134
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03004135 if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004136 bh_unlock_sock(sk);
4137 continue;
4138 }
4139
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004140 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004141 sk->sk_state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004142 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004143 bh_unlock_sock(sk);
4144 continue;
4145 }
4146
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004147 if (sk->sk_state == BT_CONNECT) {
4148 if (!status) {
4149 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004150 req.scid = cpu_to_le16(chan->scid);
4151 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004152
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004153 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03004154 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004155
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004156 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004157 L2CAP_CONN_REQ, sizeof(req), &req);
4158 } else {
4159 l2cap_sock_clear_timer(sk);
4160 l2cap_sock_set_timer(sk, HZ / 10);
4161 }
4162 } else if (sk->sk_state == BT_CONNECT2) {
4163 struct l2cap_conn_rsp rsp;
4164 __u16 result;
4165
4166 if (!status) {
4167 sk->sk_state = BT_CONFIG;
4168 result = L2CAP_CR_SUCCESS;
4169 } else {
4170 sk->sk_state = BT_DISCONN;
4171 l2cap_sock_set_timer(sk, HZ / 10);
4172 result = L2CAP_CR_SEC_BLOCK;
4173 }
4174
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004175 rsp.scid = cpu_to_le16(chan->dcid);
4176 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004177 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02004178 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004179 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4180 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004181 }
4182
Linus Torvalds1da177e2005-04-16 15:20:36 -07004183 bh_unlock_sock(sk);
4184 }
4185
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004186 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004187
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188 return 0;
4189}
4190
4191static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4192{
4193 struct l2cap_conn *conn = hcon->l2cap_data;
4194
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004195 if (!conn)
4196 conn = l2cap_conn_add(hcon, 0);
4197
4198 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199 goto drop;
4200
4201 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4202
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004203 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004205 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004206 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207 int len;
4208
4209 if (conn->rx_len) {
4210 BT_ERR("Unexpected start frame (len %d)", skb->len);
4211 kfree_skb(conn->rx_skb);
4212 conn->rx_skb = NULL;
4213 conn->rx_len = 0;
4214 l2cap_conn_unreliable(conn, ECOMM);
4215 }
4216
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004217 /* Start fragment always begin with Basic L2CAP header */
4218 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004219 BT_ERR("Frame is too short (len %d)", skb->len);
4220 l2cap_conn_unreliable(conn, ECOMM);
4221 goto drop;
4222 }
4223
4224 hdr = (struct l2cap_hdr *) skb->data;
4225 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004226 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227
4228 if (len == skb->len) {
4229 /* Complete frame received */
4230 l2cap_recv_frame(conn, skb);
4231 return 0;
4232 }
4233
4234 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4235
4236 if (skb->len > len) {
4237 BT_ERR("Frame is too long (len %d, expected len %d)",
4238 skb->len, len);
4239 l2cap_conn_unreliable(conn, ECOMM);
4240 goto drop;
4241 }
4242
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004243 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004244
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004245 if (chan && chan->sk) {
4246 struct sock *sk = chan->sk;
4247
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004248 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004249 BT_ERR("Frame exceeding recv MTU (len %d, "
4250 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004251 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004252 bh_unlock_sock(sk);
4253 l2cap_conn_unreliable(conn, ECOMM);
4254 goto drop;
4255 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004256 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004257 }
4258
Linus Torvalds1da177e2005-04-16 15:20:36 -07004259 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004260 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4261 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262 goto drop;
4263
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004264 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004265 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266 conn->rx_len = len - skb->len;
4267 } else {
4268 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4269
4270 if (!conn->rx_len) {
4271 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4272 l2cap_conn_unreliable(conn, ECOMM);
4273 goto drop;
4274 }
4275
4276 if (skb->len > conn->rx_len) {
4277 BT_ERR("Fragment is too long (len %d, expected %d)",
4278 skb->len, conn->rx_len);
4279 kfree_skb(conn->rx_skb);
4280 conn->rx_skb = NULL;
4281 conn->rx_len = 0;
4282 l2cap_conn_unreliable(conn, ECOMM);
4283 goto drop;
4284 }
4285
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004286 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004287 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288 conn->rx_len -= skb->len;
4289
4290 if (!conn->rx_len) {
4291 /* Complete frame received */
4292 l2cap_recv_frame(conn, conn->rx_skb);
4293 conn->rx_skb = NULL;
4294 }
4295 }
4296
4297drop:
4298 kfree_skb(skb);
4299 return 0;
4300}
4301
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004302static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004304 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004306 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004308 list_for_each_entry(c, &chan_list, global_l) {
4309 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004311 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 +01004312 batostr(&bt_sk(sk)->src),
4313 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004314 sk->sk_state, __le16_to_cpu(c->psm),
4315 c->scid, c->dcid, c->imtu, c->omtu,
4316 c->sec_level, c->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004317 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004319 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004320
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004321 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322}
4323
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004324static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4325{
4326 return single_open(file, l2cap_debugfs_show, inode->i_private);
4327}
4328
4329static const struct file_operations l2cap_debugfs_fops = {
4330 .open = l2cap_debugfs_open,
4331 .read = seq_read,
4332 .llseek = seq_lseek,
4333 .release = single_release,
4334};
4335
4336static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338static struct hci_proto l2cap_hci_proto = {
4339 .name = "L2CAP",
4340 .id = HCI_PROTO_L2CAP,
4341 .connect_ind = l2cap_connect_ind,
4342 .connect_cfm = l2cap_connect_cfm,
4343 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004344 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004345 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346 .recv_acldata = l2cap_recv_acldata
4347};
4348
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004349int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350{
4351 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004352
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004353 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354 if (err < 0)
4355 return err;
4356
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004357 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004358 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004359 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004360 goto error;
4361 }
4362
4363 err = hci_register_proto(&l2cap_hci_proto);
4364 if (err < 0) {
4365 BT_ERR("L2CAP protocol registration failed");
4366 bt_sock_unregister(BTPROTO_L2CAP);
4367 goto error;
4368 }
4369
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004370 if (bt_debugfs) {
4371 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4372 bt_debugfs, NULL, &l2cap_debugfs_fops);
4373 if (!l2cap_debugfs)
4374 BT_ERR("Failed to create L2CAP debug file");
4375 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377 return 0;
4378
4379error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004380 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004381 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382 return err;
4383}
4384
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004385void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004386{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004387 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004388
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004389 flush_workqueue(_busy_wq);
4390 destroy_workqueue(_busy_wq);
4391
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4393 BT_ERR("L2CAP protocol unregistration failed");
4394
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004395 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396}
4397
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004398module_param(disable_ertm, bool, 0644);
4399MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");