blob: eb58cf45fed9eaec0fb24fb661895214d90c5021 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
7 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation;
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
16 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090017 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090022 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
23 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 SOFTWARE IS DISCLAIMED.
25*/
26
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020027/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30
31#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080032#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
34#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/poll.h>
38#include <linux/fcntl.h>
39#include <linux/init.h>
40#include <linux/interrupt.h>
41#include <linux/socket.h>
42#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080044#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010045#include <linux/debugfs.h>
46#include <linux/seq_file.h>
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -030047#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030048#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/sock.h>
50
51#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
57
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020058int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020059
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070060static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010061static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030063static struct workqueue_struct *_busy_wq;
64
Gustavo F. Padovan23691d72011-04-27 18:26:32 -030065LIST_HEAD(chan_list);
66DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030068static void l2cap_busy_work(struct work_struct *work);
69
Linus Torvalds1da177e2005-04-16 15:20:36 -070070static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
71 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan6e9e43f2011-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. Padovan6e9e43f2011-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. Padovanaf05b302009-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. Padovan6e9e43f2011-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. Padovan6e9e43f2011-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. Padovan6e9e43f2011-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. Padovan6e9e43f2011-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. Padovan6e9e43f2011-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. Padovan6e9e43f2011-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);
Nick Pellyf86e4b02010-04-08 16:23:32 -0700708 if (parent)
709 parent->sk_data_ready(parent, 0);
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100710
711 } else {
712 sk->sk_state = BT_CONFIG;
713 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
714 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
715 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200716 } else {
717 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
718 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
719 }
720
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300721 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
722 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300723
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300724 if (chan->conf_state & L2CAP_CONF_REQ_SENT ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300725 rsp.result != L2CAP_CR_SUCCESS) {
726 bh_unlock_sock(sk);
727 continue;
728 }
729
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300730 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300731 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300732 l2cap_build_conf_req(chan, buf), buf);
733 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200734 }
735
736 bh_unlock_sock(sk);
737 }
738
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300739 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200740}
741
Ville Tervob62f3282011-02-10 22:38:50 -0300742/* Find socket with cid and source bdaddr.
743 * Returns closest match, locked.
744 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300745static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300746{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300747 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300748
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300749 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300750
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300751 list_for_each_entry(c, &chan_list, global_l) {
752 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300753
Ville Tervob62f3282011-02-10 22:38:50 -0300754 if (state && sk->sk_state != state)
755 continue;
756
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300757 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300758 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300759 if (!bacmp(&bt_sk(sk)->src, src)) {
760 read_unlock(&chan_list_lock);
761 return c;
762 }
Ville Tervob62f3282011-02-10 22:38:50 -0300763
764 /* Closest match */
765 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300766 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300767 }
768 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300769
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300770 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300771
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300772 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300773}
774
775static void l2cap_le_conn_ready(struct l2cap_conn *conn)
776{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300777 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300778 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300779
780 BT_DBG("");
781
782 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300783 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300784 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300785 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300786 return;
787
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300788 parent = pchan->sk;
789
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300790 bh_lock_sock(parent);
791
Ville Tervob62f3282011-02-10 22:38:50 -0300792 /* Check for backlog size */
793 if (sk_acceptq_is_full(parent)) {
794 BT_DBG("backlog full %d", parent->sk_ack_backlog);
795 goto clean;
796 }
797
798 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
799 if (!sk)
800 goto clean;
801
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300802 chan = l2cap_chan_create(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300803 if (!chan) {
804 l2cap_sock_kill(sk);
805 goto clean;
806 }
807
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300808 l2cap_pi(sk)->chan = chan;
809
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300810 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300811
812 hci_conn_hold(conn->hcon);
813
814 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300815
Ville Tervob62f3282011-02-10 22:38:50 -0300816 bacpy(&bt_sk(sk)->src, conn->src);
817 bacpy(&bt_sk(sk)->dst, conn->dst);
818
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300819 bt_accept_enqueue(parent, sk);
820
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300821 __l2cap_chan_add(conn, chan);
822
Ville Tervob62f3282011-02-10 22:38:50 -0300823 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
824
825 sk->sk_state = BT_CONNECTED;
826 parent->sk_data_ready(parent, 0);
827
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300828 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300829
830clean:
831 bh_unlock_sock(parent);
832}
833
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200834static void l2cap_conn_ready(struct l2cap_conn *conn)
835{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300836 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200837
838 BT_DBG("conn %p", conn);
839
Ville Tervob62f3282011-02-10 22:38:50 -0300840 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
841 l2cap_le_conn_ready(conn);
842
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300843 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200844
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300845 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300846 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300847
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200848 bh_lock_sock(sk);
849
Ville Tervoacd7d372011-02-10 22:38:49 -0300850 if (conn->hcon->type == LE_LINK) {
851 l2cap_sock_clear_timer(sk);
852 sk->sk_state = BT_CONNECTED;
853 sk->sk_state_change(sk);
854 }
855
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300856 if (sk->sk_type != SOCK_SEQPACKET &&
857 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200858 l2cap_sock_clear_timer(sk);
859 sk->sk_state = BT_CONNECTED;
860 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200861 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300862 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200863
864 bh_unlock_sock(sk);
865 }
866
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300867 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200868}
869
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200870/* Notify sockets that we cannot guaranty reliability anymore */
871static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
872{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300873 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200874
875 BT_DBG("conn %p", conn);
876
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300877 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200878
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300879 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300880 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300881
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300882 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200883 sk->sk_err = err;
884 }
885
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300886 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200887}
888
889static void l2cap_info_timeout(unsigned long arg)
890{
891 struct l2cap_conn *conn = (void *) arg;
892
Marcel Holtmann984947d2009-02-06 23:35:19 +0100893 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100894 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100895
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200896 l2cap_conn_start(conn);
897}
898
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
900{
Marcel Holtmann01394182006-07-03 10:02:46 +0200901 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902
Marcel Holtmann01394182006-07-03 10:02:46 +0200903 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 return conn;
905
Marcel Holtmann01394182006-07-03 10:02:46 +0200906 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
907 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909
910 hcon->l2cap_data = conn;
911 conn->hcon = hcon;
912
Marcel Holtmann01394182006-07-03 10:02:46 +0200913 BT_DBG("hcon %p conn %p", hcon, conn);
914
Ville Tervoacd7d372011-02-10 22:38:49 -0300915 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
916 conn->mtu = hcon->hdev->le_mtu;
917 else
918 conn->mtu = hcon->hdev->acl_mtu;
919
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 conn->src = &hcon->hdev->bdaddr;
921 conn->dst = &hcon->dst;
922
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200923 conn->feat_mask = 0;
924
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300926 rwlock_init(&conn->chan_lock);
927
928 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929
Ville Tervob62f3282011-02-10 22:38:50 -0300930 if (hcon->type != LE_LINK)
931 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000932 (unsigned long) conn);
933
Marcel Holtmann2950f212009-02-12 14:02:50 +0100934 conn->disc_reason = 0x13;
935
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 return conn;
937}
938
Marcel Holtmann01394182006-07-03 10:02:46 +0200939static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940{
Marcel Holtmann01394182006-07-03 10:02:46 +0200941 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300942 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 struct sock *sk;
944
Marcel Holtmann01394182006-07-03 10:02:46 +0200945 if (!conn)
946 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947
948 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
949
Wei Yongjun7585b972009-02-25 18:29:52 +0800950 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951
952 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300953 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300954 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300956 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 bh_unlock_sock(sk);
958 l2cap_sock_kill(sk);
959 }
960
Dave Young8e8440f2008-03-03 12:18:55 -0800961 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
962 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800963
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 hcon->l2cap_data = NULL;
965 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966}
967
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300968static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300970 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300971 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300972 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973}
974
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976
977/* Find socket with psm and source bdaddr.
978 * Returns closest match.
979 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300980static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300982 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300984 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000985
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300986 list_for_each_entry(c, &chan_list, global_l) {
987 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300988
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 if (state && sk->sk_state != state)
990 continue;
991
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300992 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300994 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +0200995 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300996 return c;
997 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998
999 /* Closest match */
1000 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001001 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 }
1003 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001005 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001006
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001007 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008}
1009
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001010int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001012 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 bdaddr_t *src = &bt_sk(sk)->src;
1014 bdaddr_t *dst = &bt_sk(sk)->dst;
1015 struct l2cap_conn *conn;
1016 struct hci_conn *hcon;
1017 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001018 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001019 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001021 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001022 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001024 hdev = hci_get_route(dst, src);
1025 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 return -EHOSTUNREACH;
1027
1028 hci_dev_lock_bh(hdev);
1029
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001030 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001031
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001032 if (chan->dcid == L2CAP_CID_LE_DATA)
Nick Pellybbcda3b2010-02-11 11:54:28 -08001033 hcon = hci_connect(hdev, LE_LINK, 0, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001034 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001035 else
Nick Pellybbcda3b2010-02-11 11:54:28 -08001036 hcon = hci_connect(hdev, ACL_LINK, 0, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001037 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001038
Ville Tervo30e76272011-02-22 16:10:53 -03001039 if (IS_ERR(hcon)) {
1040 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001042 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043
1044 conn = l2cap_conn_add(hcon, 0);
1045 if (!conn) {
1046 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001047 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 goto done;
1049 }
1050
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 /* Update source addr of the socket */
1052 bacpy(src, conn->src);
1053
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001054 l2cap_chan_add(conn, chan);
1055
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 sk->sk_state = BT_CONNECT;
1057 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
1058
1059 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001060 if (sk->sk_type != SOCK_SEQPACKET &&
1061 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 l2cap_sock_clear_timer(sk);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001063 if (l2cap_check_security(chan))
Johan Hedbergd00ef242011-01-19 12:06:51 +05301064 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001065 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001066 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 }
1068
Ville Tervo30e76272011-02-22 16:10:53 -03001069 err = 0;
1070
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071done:
1072 hci_dev_unlock_bh(hdev);
1073 hci_dev_put(hdev);
1074 return err;
1075}
1076
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001077int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001078{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001079 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001080 DECLARE_WAITQUEUE(wait, current);
1081 int err = 0;
1082 int timeo = HZ/5;
1083
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001084 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001085 while ((chan->unacked_frames > 0 && chan->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001086 set_current_state(TASK_INTERRUPTIBLE);
1087
1088 if (!timeo)
1089 timeo = HZ/5;
1090
1091 if (signal_pending(current)) {
1092 err = sock_intr_errno(timeo);
1093 break;
1094 }
1095
1096 release_sock(sk);
1097 timeo = schedule_timeout(timeo);
1098 lock_sock(sk);
1099
1100 err = sock_error(sk);
1101 if (err)
1102 break;
1103 }
1104 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001105 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001106 return err;
1107}
1108
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001109static void l2cap_monitor_timeout(unsigned long arg)
1110{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001111 struct l2cap_chan *chan = (void *) arg;
1112 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001113
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001114 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001115
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001116 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001117 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001118 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001119 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001120 return;
1121 }
1122
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001123 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001124 __mod_monitor_timer();
1125
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001126 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001127 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001128}
1129
1130static void l2cap_retrans_timeout(unsigned long arg)
1131{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001132 struct l2cap_chan *chan = (void *) arg;
1133 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001134
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001135 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001136
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001137 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001138 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001139 __mod_monitor_timer();
1140
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001141 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001142
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001143 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001144 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001145}
1146
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001147static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001148{
1149 struct sk_buff *skb;
1150
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001151 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001152 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001153 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001154 break;
1155
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001156 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001157 kfree_skb(skb);
1158
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001159 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001160 }
1161
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001162 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001163 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001164}
1165
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001166void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001167{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001168 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001169 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001170
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001171 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001172
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001173 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001174 flags = ACL_START_NO_FLUSH;
1175 else
1176 flags = ACL_START;
1177
1178 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001179}
1180
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001181void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001182{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001183 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001184 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001185
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001186 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001187 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001188 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001189 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001190
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001191 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001192 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1193 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001194 }
1195
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001196 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001197
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001198 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001199 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001200}
1201
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001202static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001203{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001204 struct sk_buff *skb, *tx_skb;
1205 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001206
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001207 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001208 if (!skb)
1209 return;
1210
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001211 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001212 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001213 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001214
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001215 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001216 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001217
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001218 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001219
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001220 if (chan->remote_max_tx &&
1221 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001222 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001223 return;
1224 }
1225
1226 tx_skb = skb_clone(skb, GFP_ATOMIC);
1227 bt_cb(skb)->retries++;
1228 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001229 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001230
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001231 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001232 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001233 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001234 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001235
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001236 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001237 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001238
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001239 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1240
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001241 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001242 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1243 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1244 }
1245
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001246 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001247}
1248
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001249int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001250{
1251 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001252 struct sock *sk = chan->sk;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001253 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001254 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001255
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001256 if (sk->sk_state != BT_CONNECTED)
1257 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001258
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001259 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001260
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001261 if (chan->remote_max_tx &&
1262 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001263 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001264 break;
1265 }
1266
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001267 tx_skb = skb_clone(skb, GFP_ATOMIC);
1268
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001269 bt_cb(skb)->retries++;
1270
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001271 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001272 control &= L2CAP_CTRL_SAR;
1273
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001274 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001275 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001276 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001277 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001278 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1279 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001280 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1281
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001282
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001283 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001284 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1285 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1286 }
1287
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001288 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001289
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001290 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001291
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001292 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1293 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001294
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301295 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001296 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301297
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001298 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001299
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001300 if (skb_queue_is_last(&chan->tx_q, skb))
1301 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001302 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001303 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001304
1305 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001306 }
1307
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001308 return nsent;
1309}
1310
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001311static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001312{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001313 int ret;
1314
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001315 if (!skb_queue_empty(&chan->tx_q))
1316 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001317
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001318 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001319 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001320 return ret;
1321}
1322
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001323static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001324{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001325 u16 control = 0;
1326
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001327 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001328
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001329 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001330 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001331 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1332 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001333 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001334 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001335
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001336 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001337 return;
1338
1339 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001340 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001341}
1342
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001343static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001344{
1345 struct srej_list *tail;
1346 u16 control;
1347
1348 control = L2CAP_SUPER_SELECT_REJECT;
1349 control |= L2CAP_CTRL_FINAL;
1350
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001351 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001352 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1353
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001354 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001355}
1356
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001357static 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 -07001358{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001359 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001360 struct sk_buff **frag;
1361 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001363 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001364 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365
1366 sent += count;
1367 len -= count;
1368
1369 /* Continuation fragments (no L2CAP header) */
1370 frag = &skb_shinfo(skb)->frag_list;
1371 while (len) {
1372 count = min_t(unsigned int, conn->mtu, len);
1373
1374 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1375 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001376 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001377 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1378 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379
1380 sent += count;
1381 len -= count;
1382
1383 frag = &(*frag)->next;
1384 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385
1386 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001387}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001389struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001390{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001391 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001392 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001393 struct sk_buff *skb;
1394 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1395 struct l2cap_hdr *lh;
1396
1397 BT_DBG("sk %p len %d", sk, (int)len);
1398
1399 count = min_t(unsigned int, (conn->mtu - hlen), len);
1400 skb = bt_skb_send_alloc(sk, count + hlen,
1401 msg->msg_flags & MSG_DONTWAIT, &err);
1402 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001403 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001404
1405 /* Create L2CAP header */
1406 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001407 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001408 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001409 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001410
1411 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1412 if (unlikely(err < 0)) {
1413 kfree_skb(skb);
1414 return ERR_PTR(err);
1415 }
1416 return skb;
1417}
1418
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001419struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001420{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001421 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001422 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001423 struct sk_buff *skb;
1424 int err, count, hlen = L2CAP_HDR_SIZE;
1425 struct l2cap_hdr *lh;
1426
1427 BT_DBG("sk %p len %d", sk, (int)len);
1428
1429 count = min_t(unsigned int, (conn->mtu - hlen), len);
1430 skb = bt_skb_send_alloc(sk, count + hlen,
1431 msg->msg_flags & MSG_DONTWAIT, &err);
1432 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001433 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001434
1435 /* Create L2CAP header */
1436 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001437 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001438 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1439
1440 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1441 if (unlikely(err < 0)) {
1442 kfree_skb(skb);
1443 return ERR_PTR(err);
1444 }
1445 return skb;
1446}
1447
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001448struct 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 -03001449{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001450 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001451 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001452 struct sk_buff *skb;
1453 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1454 struct l2cap_hdr *lh;
1455
1456 BT_DBG("sk %p len %d", sk, (int)len);
1457
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001458 if (!conn)
1459 return ERR_PTR(-ENOTCONN);
1460
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001461 if (sdulen)
1462 hlen += 2;
1463
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001464 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001465 hlen += 2;
1466
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001467 count = min_t(unsigned int, (conn->mtu - hlen), len);
1468 skb = bt_skb_send_alloc(sk, count + hlen,
1469 msg->msg_flags & MSG_DONTWAIT, &err);
1470 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001471 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001472
1473 /* Create L2CAP header */
1474 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001475 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001476 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1477 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001478 if (sdulen)
1479 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001480
1481 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1482 if (unlikely(err < 0)) {
1483 kfree_skb(skb);
1484 return ERR_PTR(err);
1485 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001486
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001487 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001488 put_unaligned_le16(0, skb_put(skb, 2));
1489
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001490 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001491 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492}
1493
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001494int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001495{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001496 struct sk_buff *skb;
1497 struct sk_buff_head sar_queue;
1498 u16 control;
1499 size_t size = 0;
1500
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001501 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001502 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001503 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001504 if (IS_ERR(skb))
1505 return PTR_ERR(skb);
1506
1507 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001508 len -= chan->remote_mps;
1509 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001510
1511 while (len > 0) {
1512 size_t buflen;
1513
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001514 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001515 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001516 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001517 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001518 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001519 buflen = len;
1520 }
1521
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001522 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001523 if (IS_ERR(skb)) {
1524 skb_queue_purge(&sar_queue);
1525 return PTR_ERR(skb);
1526 }
1527
1528 __skb_queue_tail(&sar_queue, skb);
1529 len -= buflen;
1530 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001531 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001532 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1533 if (chan->tx_send_head == NULL)
1534 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001535
1536 return size;
1537}
1538
Gustavo F. Padovandcb1cc32011-04-28 18:50:17 -03001539int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1540{
1541 struct sock *sk = chan->sk;
1542 struct sk_buff *skb;
1543 u16 control;
1544 int err;
1545
1546 /* Connectionless channel */
1547 if (sk->sk_type == SOCK_DGRAM) {
1548 skb = l2cap_create_connless_pdu(chan, msg, len);
1549 if (IS_ERR(skb))
1550 return PTR_ERR(skb);
1551
1552 l2cap_do_send(chan, skb);
1553 return len;
1554 }
1555
1556 switch (chan->mode) {
1557 case L2CAP_MODE_BASIC:
1558 /* Check outgoing MTU */
1559 if (len > chan->omtu)
1560 return -EMSGSIZE;
1561
1562 /* Create a basic PDU */
1563 skb = l2cap_create_basic_pdu(chan, msg, len);
1564 if (IS_ERR(skb))
1565 return PTR_ERR(skb);
1566
1567 l2cap_do_send(chan, skb);
1568 err = len;
1569 break;
1570
1571 case L2CAP_MODE_ERTM:
1572 case L2CAP_MODE_STREAMING:
1573 /* Entire SDU fits into one PDU */
1574 if (len <= chan->remote_mps) {
1575 control = L2CAP_SDU_UNSEGMENTED;
1576 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1577 0);
1578 if (IS_ERR(skb))
1579 return PTR_ERR(skb);
1580
1581 __skb_queue_tail(&chan->tx_q, skb);
1582
1583 if (chan->tx_send_head == NULL)
1584 chan->tx_send_head = skb;
1585
1586 } else {
1587 /* Segment SDU into multiples PDUs */
1588 err = l2cap_sar_segment_sdu(chan, msg, len);
1589 if (err < 0)
1590 return err;
1591 }
1592
1593 if (chan->mode == L2CAP_MODE_STREAMING) {
1594 l2cap_streaming_send(chan);
1595 err = len;
1596 break;
1597 }
1598
1599 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
1600 (chan->conn_state & L2CAP_CONN_WAIT_F)) {
1601 err = len;
1602 break;
1603 }
1604
1605 err = l2cap_ertm_send(chan);
1606 if (err >= 0)
1607 err = len;
1608
1609 break;
1610
1611 default:
1612 BT_DBG("bad state %1.1x", chan->mode);
1613 err = -EBADFD;
1614 }
1615
1616 return err;
1617}
1618
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619static void l2cap_chan_ready(struct sock *sk)
1620{
1621 struct sock *parent = bt_sk(sk)->parent;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001622 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623
1624 BT_DBG("sk %p, parent %p", sk, parent);
1625
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001626 chan->conf_state = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 l2cap_sock_clear_timer(sk);
1628
1629 if (!parent) {
1630 /* Outgoing channel.
1631 * Wake up socket sleeping on connect.
1632 */
1633 sk->sk_state = BT_CONNECTED;
1634 sk->sk_state_change(sk);
1635 } else {
1636 /* Incoming channel.
1637 * Wake up socket sleeping on accept.
1638 */
1639 parent->sk_data_ready(parent, 0);
1640 }
1641}
1642
1643/* Copy frame to all raw sockets on that connection */
1644static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1645{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001647 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648
1649 BT_DBG("conn %p", conn);
1650
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001651 read_lock(&conn->chan_lock);
1652 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001653 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 if (sk->sk_type != SOCK_RAW)
1655 continue;
1656
1657 /* Don't send frame to the socket it came from */
1658 if (skb->sk == sk)
1659 continue;
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001660 nskb = skb_clone(skb, GFP_ATOMIC);
1661 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 continue;
1663
1664 if (sock_queue_rcv_skb(sk, nskb))
1665 kfree_skb(nskb);
1666 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001667 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668}
1669
1670/* ---- L2CAP signalling commands ---- */
1671static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1672 u8 code, u8 ident, u16 dlen, void *data)
1673{
1674 struct sk_buff *skb, **frag;
1675 struct l2cap_cmd_hdr *cmd;
1676 struct l2cap_hdr *lh;
1677 int len, count;
1678
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03001679 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1680 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681
1682 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1683 count = min_t(unsigned int, conn->mtu, len);
1684
1685 skb = bt_skb_alloc(count, GFP_ATOMIC);
1686 if (!skb)
1687 return NULL;
1688
1689 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001690 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001691
1692 if (conn->hcon->type == LE_LINK)
1693 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1694 else
1695 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696
1697 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1698 cmd->code = code;
1699 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001700 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701
1702 if (dlen) {
1703 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1704 memcpy(skb_put(skb, count), data, count);
1705 data += count;
1706 }
1707
1708 len -= skb->len;
1709
1710 /* Continuation fragments (no L2CAP header) */
1711 frag = &skb_shinfo(skb)->frag_list;
1712 while (len) {
1713 count = min_t(unsigned int, conn->mtu, len);
1714
1715 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1716 if (!*frag)
1717 goto fail;
1718
1719 memcpy(skb_put(*frag, count), data, count);
1720
1721 len -= count;
1722 data += count;
1723
1724 frag = &(*frag)->next;
1725 }
1726
1727 return skb;
1728
1729fail:
1730 kfree_skb(skb);
1731 return NULL;
1732}
1733
1734static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1735{
1736 struct l2cap_conf_opt *opt = *ptr;
1737 int len;
1738
1739 len = L2CAP_CONF_OPT_SIZE + opt->len;
1740 *ptr += len;
1741
1742 *type = opt->type;
1743 *olen = opt->len;
1744
1745 switch (opt->len) {
1746 case 1:
1747 *val = *((u8 *) opt->val);
1748 break;
1749
1750 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001751 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 break;
1753
1754 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001755 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 break;
1757
1758 default:
1759 *val = (unsigned long) opt->val;
1760 break;
1761 }
1762
1763 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1764 return len;
1765}
1766
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1768{
1769 struct l2cap_conf_opt *opt = *ptr;
1770
1771 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1772
1773 opt->type = type;
1774 opt->len = len;
1775
1776 switch (len) {
1777 case 1:
1778 *((u8 *) opt->val) = val;
1779 break;
1780
1781 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001782 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 break;
1784
1785 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001786 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787 break;
1788
1789 default:
1790 memcpy(opt->val, (void *) val, len);
1791 break;
1792 }
1793
1794 *ptr += L2CAP_CONF_OPT_SIZE + len;
1795}
1796
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001797static void l2cap_ack_timeout(unsigned long arg)
1798{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001799 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001800
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001801 bh_lock_sock(chan->sk);
1802 l2cap_send_ack(chan);
1803 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001804}
1805
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001806static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001807{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001808 struct sock *sk = chan->sk;
1809
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001810 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001811 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001812 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001813 chan->num_acked = 0;
1814 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001815
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001816 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1817 (unsigned long) chan);
1818 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1819 (unsigned long) chan);
1820 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001821
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001822 skb_queue_head_init(&chan->srej_q);
1823 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001824
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001825 INIT_LIST_HEAD(&chan->srej_l);
1826
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001827 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001828
1829 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001830}
1831
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001832static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1833{
1834 switch (mode) {
1835 case L2CAP_MODE_STREAMING:
1836 case L2CAP_MODE_ERTM:
1837 if (l2cap_mode_supported(mode, remote_feat_mask))
1838 return mode;
1839 /* fall through */
1840 default:
1841 return L2CAP_MODE_BASIC;
1842 }
1843}
1844
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001845static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001848 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 void *ptr = req->data;
1850
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001851 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001853 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001854 goto done;
1855
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001856 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001857 case L2CAP_MODE_STREAMING:
1858 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001859 if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001860 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001861
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001862 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001863 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001864 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001865 break;
1866 }
1867
1868done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001869 if (chan->imtu != L2CAP_DEFAULT_MTU)
1870 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan79906812011-01-24 16:01:43 -02001871
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001872 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001873 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001874 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1875 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001876 break;
1877
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001878 rfc.mode = L2CAP_MODE_BASIC;
1879 rfc.txwin_size = 0;
1880 rfc.max_transmit = 0;
1881 rfc.retrans_timeout = 0;
1882 rfc.monitor_timeout = 0;
1883 rfc.max_pdu_size = 0;
1884
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001885 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1886 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001887 break;
1888
1889 case L2CAP_MODE_ERTM:
1890 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001891 rfc.txwin_size = chan->tx_win;
1892 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001893 rfc.retrans_timeout = 0;
1894 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001895 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001896 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1897 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001898
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001899 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1900 (unsigned long) &rfc);
1901
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001902 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001903 break;
1904
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001905 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001906 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001907 chan->fcs = L2CAP_FCS_NONE;
1908 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001909 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001910 break;
1911
1912 case L2CAP_MODE_STREAMING:
1913 rfc.mode = L2CAP_MODE_STREAMING;
1914 rfc.txwin_size = 0;
1915 rfc.max_transmit = 0;
1916 rfc.retrans_timeout = 0;
1917 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001918 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001919 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1920 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001921
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001922 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1923 (unsigned long) &rfc);
1924
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001925 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001926 break;
1927
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001928 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001929 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001930 chan->fcs = L2CAP_FCS_NONE;
1931 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001932 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001933 break;
1934 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001936 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001937 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
1939 return ptr - data;
1940}
1941
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001942static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001944 struct l2cap_conf_rsp *rsp = data;
1945 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001946 void *req = chan->conf_req;
1947 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001948 int type, hint, olen;
1949 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001950 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001951 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001952 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001954 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001955
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001956 while (len >= L2CAP_CONF_OPT_SIZE) {
1957 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001959 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001960 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001961
1962 switch (type) {
1963 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001964 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001965 break;
1966
1967 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001968 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001969 break;
1970
1971 case L2CAP_CONF_QOS:
1972 break;
1973
Marcel Holtmann6464f352007-10-20 13:39:51 +02001974 case L2CAP_CONF_RFC:
1975 if (olen == sizeof(rfc))
1976 memcpy(&rfc, (void *) val, olen);
1977 break;
1978
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001979 case L2CAP_CONF_FCS:
1980 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001981 chan->conf_state |= L2CAP_CONF_NO_FCS_RECV;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001982
1983 break;
1984
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001985 default:
1986 if (hint)
1987 break;
1988
1989 result = L2CAP_CONF_UNKNOWN;
1990 *((u8 *) ptr++) = type;
1991 break;
1992 }
1993 }
1994
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001995 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001996 goto done;
1997
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001998 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001999 case L2CAP_MODE_STREAMING:
2000 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002001 if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002002 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002003 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002004 break;
2005 }
2006
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002007 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002008 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002009
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002010 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002011 }
2012
2013done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002014 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002015 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002016 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002017
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002018 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002019 return -ECONNREFUSED;
2020
2021 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2022 sizeof(rfc), (unsigned long) &rfc);
2023 }
2024
2025
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002026 if (result == L2CAP_CONF_SUCCESS) {
2027 /* Configure output options and let the other side know
2028 * which ones we don't like. */
2029
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002030 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2031 result = L2CAP_CONF_UNACCEPT;
2032 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002033 chan->omtu = mtu;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002034 chan->conf_state |= L2CAP_CONF_MTU_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002035 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002036 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002037
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002038 switch (rfc.mode) {
2039 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002040 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002041 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002042 break;
2043
2044 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002045 chan->remote_tx_win = rfc.txwin_size;
2046 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002047
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002048 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2049 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002050
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002051 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002052
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002053 rfc.retrans_timeout =
2054 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2055 rfc.monitor_timeout =
2056 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002057
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002058 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002059
2060 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2061 sizeof(rfc), (unsigned long) &rfc);
2062
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002063 break;
2064
2065 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002066 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2067 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002068
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002069 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002070
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002071 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002072
2073 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2074 sizeof(rfc), (unsigned long) &rfc);
2075
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002076 break;
2077
2078 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002079 result = L2CAP_CONF_UNACCEPT;
2080
2081 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002082 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002083 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002084
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002085 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002086 chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002087 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002088 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002089 rsp->result = cpu_to_le16(result);
2090 rsp->flags = cpu_to_le16(0x0000);
2091
2092 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093}
2094
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002095static 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 -03002096{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002097 struct l2cap_conf_req *req = data;
2098 void *ptr = req->data;
2099 int type, olen;
2100 unsigned long val;
2101 struct l2cap_conf_rfc rfc;
2102
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002103 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002104
2105 while (len >= L2CAP_CONF_OPT_SIZE) {
2106 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2107
2108 switch (type) {
2109 case L2CAP_CONF_MTU:
2110 if (val < L2CAP_DEFAULT_MIN_MTU) {
2111 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002112 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002113 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002114 chan->imtu = val;
2115 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002116 break;
2117
2118 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002119 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002120 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002121 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002122 break;
2123
2124 case L2CAP_CONF_RFC:
2125 if (olen == sizeof(rfc))
2126 memcpy(&rfc, (void *)val, olen);
2127
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002128 if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002129 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002130 return -ECONNREFUSED;
2131
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002132 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002133
2134 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2135 sizeof(rfc), (unsigned long) &rfc);
2136 break;
2137 }
2138 }
2139
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002140 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002141 return -ECONNREFUSED;
2142
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002143 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002144
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002145 if (*result == L2CAP_CONF_SUCCESS) {
2146 switch (rfc.mode) {
2147 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002148 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2149 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2150 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002151 break;
2152 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002153 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002154 }
2155 }
2156
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002157 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002158 req->flags = cpu_to_le16(0x0000);
2159
2160 return ptr - data;
2161}
2162
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002163static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164{
2165 struct l2cap_conf_rsp *rsp = data;
2166 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002168 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002170 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002171 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002172 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173
2174 return ptr - data;
2175}
2176
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002177void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002178{
2179 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002180 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002181 u8 buf[128];
2182
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002183 rsp.scid = cpu_to_le16(chan->dcid);
2184 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002185 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2186 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2187 l2cap_send_cmd(conn, chan->ident,
2188 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2189
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002190 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002191 return;
2192
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002193 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002194 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2195 l2cap_build_conf_req(chan, buf), buf);
2196 chan->num_conf_req++;
2197}
2198
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002199static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002200{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002201 int type, olen;
2202 unsigned long val;
2203 struct l2cap_conf_rfc rfc;
2204
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002205 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002206
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002207 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002208 return;
2209
2210 while (len >= L2CAP_CONF_OPT_SIZE) {
2211 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2212
2213 switch (type) {
2214 case L2CAP_CONF_RFC:
2215 if (olen == sizeof(rfc))
2216 memcpy(&rfc, (void *)val, olen);
2217 goto done;
2218 }
2219 }
2220
2221done:
2222 switch (rfc.mode) {
2223 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002224 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2225 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2226 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002227 break;
2228 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002229 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002230 }
2231}
2232
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002233static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2234{
2235 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2236
2237 if (rej->reason != 0x0000)
2238 return 0;
2239
2240 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2241 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002242 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002243
2244 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002245 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002246
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002247 l2cap_conn_start(conn);
2248 }
2249
2250 return 0;
2251}
2252
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2254{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2256 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002257 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002258 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002259 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260
2261 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002262 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263
2264 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2265
2266 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002267 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2268 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269 result = L2CAP_CR_BAD_PSM;
2270 goto sendresp;
2271 }
2272
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002273 parent = pchan->sk;
2274
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002275 bh_lock_sock(parent);
2276
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002277 /* Check if the ACL is secure enough (if not SDP) */
2278 if (psm != cpu_to_le16(0x0001) &&
2279 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002280 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002281 result = L2CAP_CR_SEC_BLOCK;
2282 goto response;
2283 }
2284
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 result = L2CAP_CR_NO_MEM;
2286
2287 /* Check for backlog size */
2288 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002289 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290 goto response;
2291 }
2292
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002293 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 if (!sk)
2295 goto response;
2296
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002297 chan = l2cap_chan_create(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002298 if (!chan) {
2299 l2cap_sock_kill(sk);
2300 goto response;
2301 }
2302
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03002303 l2cap_pi(sk)->chan = chan;
2304
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002305 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306
2307 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002308 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2309 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 sock_set_flag(sk, SOCK_ZAPPED);
2311 l2cap_sock_kill(sk);
2312 goto response;
2313 }
2314
2315 hci_conn_hold(conn->hcon);
2316
2317 l2cap_sock_init(sk, parent);
2318 bacpy(&bt_sk(sk)->src, conn->src);
2319 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002320 chan->psm = psm;
2321 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002323 bt_accept_enqueue(parent, sk);
2324
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002325 __l2cap_chan_add(conn, chan);
2326
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002327 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328
2329 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2330
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002331 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332
Marcel Holtmann984947d2009-02-06 23:35:19 +01002333 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002334 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002335 if (bt_sk(sk)->defer_setup) {
2336 sk->sk_state = BT_CONNECT2;
2337 result = L2CAP_CR_PEND;
2338 status = L2CAP_CS_AUTHOR_PEND;
2339 parent->sk_data_ready(parent, 0);
2340 } else {
2341 sk->sk_state = BT_CONFIG;
2342 result = L2CAP_CR_SUCCESS;
2343 status = L2CAP_CS_NO_INFO;
2344 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002345 } else {
2346 sk->sk_state = BT_CONNECT2;
2347 result = L2CAP_CR_PEND;
2348 status = L2CAP_CS_AUTHEN_PEND;
2349 }
2350 } else {
2351 sk->sk_state = BT_CONNECT2;
2352 result = L2CAP_CR_PEND;
2353 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 }
2355
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002356 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357
2358response:
2359 bh_unlock_sock(parent);
2360
2361sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002362 rsp.scid = cpu_to_le16(scid);
2363 rsp.dcid = cpu_to_le16(dcid);
2364 rsp.result = cpu_to_le16(result);
2365 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002367
2368 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2369 struct l2cap_info_req info;
2370 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2371
2372 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2373 conn->info_ident = l2cap_get_ident(conn);
2374
2375 mod_timer(&conn->info_timer, jiffies +
2376 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2377
2378 l2cap_send_cmd(conn, conn->info_ident,
2379 L2CAP_INFO_REQ, sizeof(info), &info);
2380 }
2381
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002382 if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002383 result == L2CAP_CR_SUCCESS) {
2384 u8 buf[128];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002385 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002386 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002387 l2cap_build_conf_req(chan, buf), buf);
2388 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002389 }
2390
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 return 0;
2392}
2393
2394static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2395{
2396 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2397 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002398 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 struct sock *sk;
2400 u8 req[128];
2401
2402 scid = __le16_to_cpu(rsp->scid);
2403 dcid = __le16_to_cpu(rsp->dcid);
2404 result = __le16_to_cpu(rsp->result);
2405 status = __le16_to_cpu(rsp->status);
2406
2407 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2408
2409 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002410 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002411 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002412 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002414 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002415 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002416 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 }
2418
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002419 sk = chan->sk;
2420
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 switch (result) {
2422 case L2CAP_CR_SUCCESS:
2423 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002424 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002425 chan->dcid = dcid;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002426 chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002427
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002428 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002429 break;
2430
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002431 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002432
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002434 l2cap_build_conf_req(chan, req), req);
2435 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 break;
2437
2438 case L2CAP_CR_PEND:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002439 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440 break;
2441
2442 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002443 /* don't delete l2cap channel if sk is owned by user */
2444 if (sock_owned_by_user(sk)) {
2445 sk->sk_state = BT_DISCONN;
2446 l2cap_sock_clear_timer(sk);
2447 l2cap_sock_set_timer(sk, HZ / 5);
2448 break;
2449 }
2450
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002451 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 break;
2453 }
2454
2455 bh_unlock_sock(sk);
2456 return 0;
2457}
2458
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002459static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002460{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002461 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
2462
Mat Martineau8c462b62010-08-24 15:35:42 -07002463 /* FCS is enabled only in ERTM or streaming mode, if one or both
2464 * sides request it.
2465 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002466 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002467 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002468 else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002469 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002470}
2471
Al Viro88219a02007-07-29 00:17:25 -07002472static 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 -07002473{
2474 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2475 u16 dcid, flags;
2476 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002477 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002479 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480
2481 dcid = __le16_to_cpu(req->dcid);
2482 flags = __le16_to_cpu(req->flags);
2483
2484 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2485
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002486 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002487 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 return -ENOENT;
2489
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002490 sk = chan->sk;
2491
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002492 if (sk->sk_state != BT_CONFIG) {
2493 struct l2cap_cmd_rej rej;
2494
2495 rej.reason = cpu_to_le16(0x0002);
2496 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2497 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002498 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002499 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002500
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002501 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002502 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002503 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002504 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002505 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002506 L2CAP_CONF_REJECT, flags), rsp);
2507 goto unlock;
2508 }
2509
2510 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002511 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2512 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513
2514 if (flags & 0x0001) {
2515 /* Incomplete config. Send empty response. */
2516 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002517 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002518 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519 goto unlock;
2520 }
2521
2522 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002523 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002524 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002525 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002527 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002529 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002530 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002531
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002532 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002533 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002534
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002535 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002536 goto unlock;
2537
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002538 if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002539 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002540
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002542
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002543 chan->next_tx_seq = 0;
2544 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002545 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002546 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002547 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002548
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002550 goto unlock;
2551 }
2552
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002553 if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002554 u8 buf[64];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002555 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002557 l2cap_build_conf_req(chan, buf), buf);
2558 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559 }
2560
2561unlock:
2562 bh_unlock_sock(sk);
2563 return 0;
2564}
2565
2566static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2567{
2568 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2569 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002570 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002572 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573
2574 scid = __le16_to_cpu(rsp->scid);
2575 flags = __le16_to_cpu(rsp->flags);
2576 result = __le16_to_cpu(rsp->result);
2577
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03002578 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2579 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002581 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002582 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583 return 0;
2584
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002585 sk = chan->sk;
2586
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 switch (result) {
2588 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002589 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590 break;
2591
2592 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002593 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002594 char req[64];
2595
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002596 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002597 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002598 goto done;
2599 }
2600
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002601 /* throw out any old stored conf requests */
2602 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002603 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2604 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002605 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002606 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002607 goto done;
2608 }
2609
2610 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2611 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002612 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002613 if (result != L2CAP_CONF_SUCCESS)
2614 goto done;
2615 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 }
2617
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002618 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002619 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002621 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 goto done;
2623 }
2624
2625 if (flags & 0x01)
2626 goto done;
2627
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002628 chan->conf_state |= L2CAP_CONF_INPUT_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002630 if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002631 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002632
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002634 chan->next_tx_seq = 0;
2635 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002636 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002637 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002638 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002639
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 l2cap_chan_ready(sk);
2641 }
2642
2643done:
2644 bh_unlock_sock(sk);
2645 return 0;
2646}
2647
2648static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2649{
2650 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2651 struct l2cap_disconn_rsp rsp;
2652 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002653 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654 struct sock *sk;
2655
2656 scid = __le16_to_cpu(req->scid);
2657 dcid = __le16_to_cpu(req->dcid);
2658
2659 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2660
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002661 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002662 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663 return 0;
2664
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002665 sk = chan->sk;
2666
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002667 rsp.dcid = cpu_to_le16(chan->scid);
2668 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2670
2671 sk->sk_shutdown = SHUTDOWN_MASK;
2672
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002673 /* don't delete l2cap channel if sk is owned by user */
2674 if (sock_owned_by_user(sk)) {
2675 sk->sk_state = BT_DISCONN;
2676 l2cap_sock_clear_timer(sk);
2677 l2cap_sock_set_timer(sk, HZ / 5);
2678 bh_unlock_sock(sk);
2679 return 0;
2680 }
2681
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002682 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683 bh_unlock_sock(sk);
2684
2685 l2cap_sock_kill(sk);
2686 return 0;
2687}
2688
2689static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2690{
2691 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2692 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002693 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694 struct sock *sk;
2695
2696 scid = __le16_to_cpu(rsp->scid);
2697 dcid = __le16_to_cpu(rsp->dcid);
2698
2699 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2700
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002701 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002702 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 return 0;
2704
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002705 sk = chan->sk;
2706
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002707 /* don't delete l2cap channel if sk is owned by user */
2708 if (sock_owned_by_user(sk)) {
2709 sk->sk_state = BT_DISCONN;
2710 l2cap_sock_clear_timer(sk);
2711 l2cap_sock_set_timer(sk, HZ / 5);
2712 bh_unlock_sock(sk);
2713 return 0;
2714 }
2715
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002716 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717 bh_unlock_sock(sk);
2718
2719 l2cap_sock_kill(sk);
2720 return 0;
2721}
2722
2723static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2724{
2725 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 u16 type;
2727
2728 type = __le16_to_cpu(req->type);
2729
2730 BT_DBG("type 0x%4.4x", type);
2731
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002732 if (type == L2CAP_IT_FEAT_MASK) {
2733 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002734 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002735 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2736 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2737 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002738 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002739 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2740 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002741 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002742 l2cap_send_cmd(conn, cmd->ident,
2743 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002744 } else if (type == L2CAP_IT_FIXED_CHAN) {
2745 u8 buf[12];
2746 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2747 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2748 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2749 memcpy(buf + 4, l2cap_fixed_chan, 8);
2750 l2cap_send_cmd(conn, cmd->ident,
2751 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002752 } else {
2753 struct l2cap_info_rsp rsp;
2754 rsp.type = cpu_to_le16(type);
2755 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2756 l2cap_send_cmd(conn, cmd->ident,
2757 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2758 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759
2760 return 0;
2761}
2762
2763static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2764{
2765 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2766 u16 type, result;
2767
2768 type = __le16_to_cpu(rsp->type);
2769 result = __le16_to_cpu(rsp->result);
2770
2771 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2772
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002773 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2774 if (cmd->ident != conn->info_ident ||
2775 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2776 return 0;
2777
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002778 del_timer(&conn->info_timer);
2779
Ville Tervoadb08ed2010-08-04 09:43:33 +03002780 if (result != L2CAP_IR_SUCCESS) {
2781 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2782 conn->info_ident = 0;
2783
2784 l2cap_conn_start(conn);
2785
2786 return 0;
2787 }
2788
Marcel Holtmann984947d2009-02-06 23:35:19 +01002789 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002790 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002791
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002792 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002793 struct l2cap_info_req req;
2794 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2795
2796 conn->info_ident = l2cap_get_ident(conn);
2797
2798 l2cap_send_cmd(conn, conn->info_ident,
2799 L2CAP_INFO_REQ, sizeof(req), &req);
2800 } else {
2801 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2802 conn->info_ident = 0;
2803
2804 l2cap_conn_start(conn);
2805 }
2806 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002807 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002808 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002809
2810 l2cap_conn_start(conn);
2811 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002812
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813 return 0;
2814}
2815
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002816static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002817 u16 to_multiplier)
2818{
2819 u16 max_latency;
2820
2821 if (min > max || min < 6 || max > 3200)
2822 return -EINVAL;
2823
2824 if (to_multiplier < 10 || to_multiplier > 3200)
2825 return -EINVAL;
2826
2827 if (max >= to_multiplier * 8)
2828 return -EINVAL;
2829
2830 max_latency = (to_multiplier * 8 / max) - 1;
2831 if (latency > 499 || latency > max_latency)
2832 return -EINVAL;
2833
2834 return 0;
2835}
2836
2837static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2838 struct l2cap_cmd_hdr *cmd, u8 *data)
2839{
2840 struct hci_conn *hcon = conn->hcon;
2841 struct l2cap_conn_param_update_req *req;
2842 struct l2cap_conn_param_update_rsp rsp;
2843 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002844 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002845
2846 if (!(hcon->link_mode & HCI_LM_MASTER))
2847 return -EINVAL;
2848
2849 cmd_len = __le16_to_cpu(cmd->len);
2850 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2851 return -EPROTO;
2852
2853 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002854 min = __le16_to_cpu(req->min);
2855 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002856 latency = __le16_to_cpu(req->latency);
2857 to_multiplier = __le16_to_cpu(req->to_multiplier);
2858
2859 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2860 min, max, latency, to_multiplier);
2861
2862 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002863
2864 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2865 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002866 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2867 else
2868 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2869
2870 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2871 sizeof(rsp), &rsp);
2872
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002873 if (!err)
2874 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2875
Claudio Takahaside731152011-02-11 19:28:55 -02002876 return 0;
2877}
2878
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002879static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2880 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2881{
2882 int err = 0;
2883
2884 switch (cmd->code) {
2885 case L2CAP_COMMAND_REJ:
2886 l2cap_command_rej(conn, cmd, data);
2887 break;
2888
2889 case L2CAP_CONN_REQ:
2890 err = l2cap_connect_req(conn, cmd, data);
2891 break;
2892
2893 case L2CAP_CONN_RSP:
2894 err = l2cap_connect_rsp(conn, cmd, data);
2895 break;
2896
2897 case L2CAP_CONF_REQ:
2898 err = l2cap_config_req(conn, cmd, cmd_len, data);
2899 break;
2900
2901 case L2CAP_CONF_RSP:
2902 err = l2cap_config_rsp(conn, cmd, data);
2903 break;
2904
2905 case L2CAP_DISCONN_REQ:
2906 err = l2cap_disconnect_req(conn, cmd, data);
2907 break;
2908
2909 case L2CAP_DISCONN_RSP:
2910 err = l2cap_disconnect_rsp(conn, cmd, data);
2911 break;
2912
2913 case L2CAP_ECHO_REQ:
2914 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2915 break;
2916
2917 case L2CAP_ECHO_RSP:
2918 break;
2919
2920 case L2CAP_INFO_REQ:
2921 err = l2cap_information_req(conn, cmd, data);
2922 break;
2923
2924 case L2CAP_INFO_RSP:
2925 err = l2cap_information_rsp(conn, cmd, data);
2926 break;
2927
2928 default:
2929 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2930 err = -EINVAL;
2931 break;
2932 }
2933
2934 return err;
2935}
2936
2937static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2938 struct l2cap_cmd_hdr *cmd, u8 *data)
2939{
2940 switch (cmd->code) {
2941 case L2CAP_COMMAND_REJ:
2942 return 0;
2943
2944 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002945 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002946
2947 case L2CAP_CONN_PARAM_UPDATE_RSP:
2948 return 0;
2949
2950 default:
2951 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2952 return -EINVAL;
2953 }
2954}
2955
2956static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2957 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002958{
2959 u8 *data = skb->data;
2960 int len = skb->len;
2961 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002962 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963
2964 l2cap_raw_recv(conn, skb);
2965
2966 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002967 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2969 data += L2CAP_CMD_HDR_SIZE;
2970 len -= L2CAP_CMD_HDR_SIZE;
2971
Al Viro88219a02007-07-29 00:17:25 -07002972 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973
Al Viro88219a02007-07-29 00:17:25 -07002974 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 -07002975
Al Viro88219a02007-07-29 00:17:25 -07002976 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 BT_DBG("corrupted command");
2978 break;
2979 }
2980
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002981 if (conn->hcon->type == LE_LINK)
2982 err = l2cap_le_sig_cmd(conn, &cmd, data);
2983 else
2984 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985
2986 if (err) {
2987 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002988
2989 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990
2991 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002992 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2994 }
2995
Al Viro88219a02007-07-29 00:17:25 -07002996 data += cmd_len;
2997 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998 }
2999
3000 kfree_skb(skb);
3001}
3002
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003003static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003004{
3005 u16 our_fcs, rcv_fcs;
3006 int hdr_size = L2CAP_HDR_SIZE + 2;
3007
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003008 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003009 skb_trim(skb, skb->len - 2);
3010 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3011 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3012
3013 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003014 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003015 }
3016 return 0;
3017}
3018
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003019static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003020{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003021 u16 control = 0;
3022
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003023 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003024
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003025 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003026
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003027 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003028 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003029 l2cap_send_sframe(chan, control);
3030 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003031 }
3032
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003033 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
3034 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003035
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003036 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003037
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003038 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003039 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003040 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003041 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003042 }
3043}
3044
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003045static 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 -03003046{
3047 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003048 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003049
3050 bt_cb(skb)->tx_seq = tx_seq;
3051 bt_cb(skb)->sar = sar;
3052
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003053 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003054 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003055 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003056 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003057 }
3058
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003059 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003060 if (tx_seq_offset < 0)
3061 tx_seq_offset += 64;
3062
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003063 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003064 if (bt_cb(next_skb)->tx_seq == tx_seq)
3065 return -EINVAL;
3066
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003067 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003068 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003069 if (next_tx_seq_offset < 0)
3070 next_tx_seq_offset += 64;
3071
3072 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003073 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003074 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003075 }
3076
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003077 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003078 break;
3079
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003080 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003081
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003082 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003083
3084 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003085}
3086
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003087static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003088{
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003089 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003090 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003091
3092 switch (control & L2CAP_CTRL_SAR) {
3093 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003094 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003095 goto drop;
3096
Ruiyi Zhang54f61512011-05-13 13:07:52 +08003097 return sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003098
3099 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003100 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003101 goto drop;
3102
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003103 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003104
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003105 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003106 goto disconnect;
3107
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003108 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3109 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003110 return -ENOMEM;
3111
3112 /* pull sdu_len bytes only after alloc, because of Local Busy
3113 * condition we have to be sure that this will be executed
3114 * only once, i.e., when alloc does not fail */
3115 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003116
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003117 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003118
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003119 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003120 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003121 break;
3122
3123 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003124 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003125 goto disconnect;
3126
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003127 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003128 goto disconnect;
3129
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003130 chan->partial_sdu_len += skb->len;
3131 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003132 goto drop;
3133
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003134 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003135
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003136 break;
3137
3138 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003139 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003140 goto disconnect;
3141
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003142 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003143 goto disconnect;
3144
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003145 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003146 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003147
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003148 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003149 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003150
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003151 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003152 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003153
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003154 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003155 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003156
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003157 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003158 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003159 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003160 return -ENOMEM;
3161 }
3162
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003163 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003164 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003165 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003166 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003167 return err;
3168 }
3169
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003170 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
3171 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003172
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003173 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003174 break;
3175 }
3176
3177 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003178 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003179
3180drop:
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003181 kfree_skb(chan->sdu);
3182 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003183
3184disconnect:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003185 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003186 kfree_skb(skb);
3187 return 0;
3188}
3189
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003190static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003191{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003192 struct sk_buff *skb;
3193 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003194 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003195
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003196 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003197 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003198 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003199 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003200 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003201 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003202 }
3203
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003204 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003205 }
3206
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003207 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003208 goto done;
3209
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003210 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003211 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003212 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003213 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003214
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003215 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003216 __mod_monitor_timer();
3217
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003218 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003219
3220done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003221 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3222 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003223
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003224 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003225
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003226 return 0;
3227}
3228
3229static void l2cap_busy_work(struct work_struct *work)
3230{
3231 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003232 struct l2cap_chan *chan =
3233 container_of(work, struct l2cap_chan, busy_work);
3234 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003235 int n_tries = 0, timeo = HZ/5, err;
3236 struct sk_buff *skb;
3237
3238 lock_sock(sk);
3239
3240 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003241 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003242 set_current_state(TASK_INTERRUPTIBLE);
3243
3244 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3245 err = -EBUSY;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003246 l2cap_send_disconn_req(chan->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003247 break;
3248 }
3249
3250 if (!timeo)
3251 timeo = HZ/5;
3252
3253 if (signal_pending(current)) {
3254 err = sock_intr_errno(timeo);
3255 break;
3256 }
3257
3258 release_sock(sk);
3259 timeo = schedule_timeout(timeo);
3260 lock_sock(sk);
3261
3262 err = sock_error(sk);
3263 if (err)
3264 break;
3265
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003266 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003267 break;
3268 }
3269
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003270 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003271 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003272
3273 release_sock(sk);
3274}
3275
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003276static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003277{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003278 int sctrl, err;
3279
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003280 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003281 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003282 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003283 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003284
3285
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003286 }
3287
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003288 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003289 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003290 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003291 return err;
3292 }
3293
3294 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003295 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003296
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003297 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003298 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003299 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003300
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003301 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003302 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003303 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003304
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003305 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003306
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003307 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003308
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003309 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003310
3311 return err;
3312}
3313
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003314static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003315{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003316 struct sk_buff *_skb;
3317 int err = -EINVAL;
3318
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003319 /*
3320 * TODO: We have to notify the userland if some data is lost with the
3321 * Streaming Mode.
3322 */
3323
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003324 switch (control & L2CAP_CTRL_SAR) {
3325 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003326 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003327 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003328 break;
3329 }
3330
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003331 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003332 if (!err)
3333 return 0;
3334
3335 break;
3336
3337 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003338 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003339 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003340 break;
3341 }
3342
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003343 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003344 skb_pull(skb, 2);
3345
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003346 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003347 err = -EMSGSIZE;
3348 break;
3349 }
3350
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003351 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3352 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003353 err = -ENOMEM;
3354 break;
3355 }
3356
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003357 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003358
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003359 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003360 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003361 err = 0;
3362 break;
3363
3364 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003365 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003366 break;
3367
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003368 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003369
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003370 chan->partial_sdu_len += skb->len;
3371 if (chan->partial_sdu_len > chan->sdu_len)
3372 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003373 else
3374 err = 0;
3375
3376 break;
3377
3378 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003379 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003380 break;
3381
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003382 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003383
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003384 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003385 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003386
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003387 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003388 goto drop;
3389
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003390 if (chan->partial_sdu_len == chan->sdu_len) {
3391 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003392 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003393 if (err < 0)
3394 kfree_skb(_skb);
3395 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003396 err = 0;
3397
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003398drop:
Gustavo F. Padovan6f61fd42011-03-25 20:09:37 -03003399 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003400 break;
3401 }
3402
3403 kfree_skb(skb);
3404 return err;
3405}
3406
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003407static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003408{
3409 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003410 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003411
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003412 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003413 if (bt_cb(skb)->tx_seq != tx_seq)
3414 break;
3415
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003416 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003417 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003418 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003419 chan->buffer_seq_srej =
3420 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003421 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003422 }
3423}
3424
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003425static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003426{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003427 struct srej_list *l, *tmp;
3428 u16 control;
3429
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003430 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003431 if (l->tx_seq == tx_seq) {
3432 list_del(&l->list);
3433 kfree(l);
3434 return;
3435 }
3436 control = L2CAP_SUPER_SELECT_REJECT;
3437 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003438 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003439 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003440 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003441 }
3442}
3443
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003444static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003445{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003446 struct srej_list *new;
3447 u16 control;
3448
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003449 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003450 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003451 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003452 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003453
3454 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003455 new->tx_seq = chan->expected_tx_seq;
3456 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003457 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003458 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003459 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003460}
3461
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003462static 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 -03003463{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003464 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003465 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003466 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003467 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003468 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003469 int err = 0;
3470
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003471 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3472 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003473
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003474 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003475 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003476 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003477 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003478 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003479 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003480 }
3481
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003482 chan->expected_ack_seq = req_seq;
3483 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003484
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003485 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003486 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003487
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003488 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003489 if (tx_seq_offset < 0)
3490 tx_seq_offset += 64;
3491
3492 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003493 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003494 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003495 goto drop;
3496 }
3497
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003498 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003499 goto drop;
3500
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003501 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003502 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003503
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003504 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003505 struct srej_list, list);
3506 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003507 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003508 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003509
3510 list_del(&first->list);
3511 kfree(first);
3512
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003513 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003514 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003515 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3516 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003517 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003518 }
3519 } else {
3520 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003521
3522 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003523 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003524 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003525
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003526 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003527 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003528 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003529 return 0;
3530 }
3531 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003532 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003533 }
3534 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003535 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003536 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003537 if (expected_tx_seq_offset < 0)
3538 expected_tx_seq_offset += 64;
3539
3540 /* duplicated tx_seq */
3541 if (tx_seq_offset < expected_tx_seq_offset)
3542 goto drop;
3543
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003544 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003545
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003546 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003547
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003548 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003549 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003550
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003551 __skb_queue_head_init(&chan->srej_q);
3552 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003553 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003554
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003555 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003556
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003557 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003558
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003559 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003560 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003561 return 0;
3562
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003563expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003564 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003565
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003566 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003567 bt_cb(skb)->tx_seq = tx_seq;
3568 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003569 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003570 return 0;
3571 }
3572
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003573 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003574 if (err < 0)
3575 return 0;
3576
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003577 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003578 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3579 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003580 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003581 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003582 }
3583
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003584 __mod_ack_timer();
3585
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003586 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3587 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003588 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003589
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003590 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003591
3592drop:
3593 kfree_skb(skb);
3594 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003595}
3596
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003597static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003598{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003599 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003600 rx_control);
3601
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003602 chan->expected_ack_seq = __get_reqseq(rx_control);
3603 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003604
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003605 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003606 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3607 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3608 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003609 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003610 __mod_retrans_timer();
3611
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003612 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3613 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003614 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003615 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003616 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003617
3618 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003619 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003620
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003621 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3622 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003623 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003624 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003625
3626 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003627 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003628 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003629 __mod_retrans_timer();
3630
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003631 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3632 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3633 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003634 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003635 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003636 }
3637}
3638
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003639static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003640{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003641 u8 tx_seq = __get_reqseq(rx_control);
3642
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003643 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003644
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003645 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003646
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003647 chan->expected_ack_seq = tx_seq;
3648 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003649
3650 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003651 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3652 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003653 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003654 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003655 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003656 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003657
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003658 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3659 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003660 }
3661}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003662static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003663{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003664 u8 tx_seq = __get_reqseq(rx_control);
3665
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003666 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003667
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003668 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003669
3670 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003671 chan->expected_ack_seq = tx_seq;
3672 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003673
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003674 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3675 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003676
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003677 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003678
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003679 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003680 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003681 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003682 }
3683 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003684 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003685 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003686 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003687 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003688 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003689 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003690 l2cap_retransmit_one_frame(chan, tx_seq);
3691 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003692 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003693 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003694 }
3695 }
3696}
3697
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003698static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003699{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003700 u8 tx_seq = __get_reqseq(rx_control);
3701
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003702 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003703
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003704 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003705 chan->expected_ack_seq = tx_seq;
3706 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003707
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003708 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003709 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003710
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003711 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003712 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003713 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003714 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003715 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003716 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003717
3718 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003719 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003720 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003721 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003722}
3723
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003724static 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 -03003725{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003726 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003727
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003728 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003729 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003730 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003731 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003732 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003733 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003734 }
3735
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003736 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3737 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003738 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003739 break;
3740
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003741 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003742 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003743 break;
3744
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003745 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003746 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003747 break;
3748
3749 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003750 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003751 break;
3752 }
3753
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003754 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003755 return 0;
3756}
3757
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003758static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3759{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003760 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003761 u16 control;
3762 u8 req_seq;
3763 int len, next_tx_seq_offset, req_seq_offset;
3764
3765 control = get_unaligned_le16(skb->data);
3766 skb_pull(skb, 2);
3767 len = skb->len;
3768
3769 /*
3770 * We can just drop the corrupted I-frame here.
3771 * Receiver will miss it and start proper recovery
3772 * procedures and ask retransmission.
3773 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003774 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003775 goto drop;
3776
3777 if (__is_sar_start(control) && __is_iframe(control))
3778 len -= 2;
3779
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003780 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003781 len -= 2;
3782
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003783 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003784 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003785 goto drop;
3786 }
3787
3788 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003789 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003790 if (req_seq_offset < 0)
3791 req_seq_offset += 64;
3792
3793 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003794 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003795 if (next_tx_seq_offset < 0)
3796 next_tx_seq_offset += 64;
3797
3798 /* check for invalid req-seq */
3799 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003800 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003801 goto drop;
3802 }
3803
3804 if (__is_iframe(control)) {
3805 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003806 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003807 goto drop;
3808 }
3809
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003810 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003811 } else {
3812 if (len != 0) {
3813 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003814 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003815 goto drop;
3816 }
3817
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003818 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003819 }
3820
3821 return 0;
3822
3823drop:
3824 kfree_skb(skb);
3825 return 0;
3826}
3827
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3829{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003830 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003831 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003832 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003833 u8 tx_seq;
3834 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003836 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003837 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838 BT_DBG("unknown cid 0x%4.4x", cid);
3839 goto drop;
3840 }
3841
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003842 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003843
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003844 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845
3846 if (sk->sk_state != BT_CONNECTED)
3847 goto drop;
3848
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003849 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003850 case L2CAP_MODE_BASIC:
3851 /* If socket recv buffers overflows we drop data here
3852 * which is *bad* because L2CAP has to be reliable.
3853 * But we don't have any other choice. L2CAP doesn't
3854 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003855
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003856 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003857 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003859 if (!sock_queue_rcv_skb(sk, skb))
3860 goto done;
3861 break;
3862
3863 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003864 if (!sock_owned_by_user(sk)) {
3865 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003866 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003867 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003868 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003869 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003870
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003871 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003872
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003873 case L2CAP_MODE_STREAMING:
3874 control = get_unaligned_le16(skb->data);
3875 skb_pull(skb, 2);
3876 len = skb->len;
3877
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003878 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003879 goto drop;
3880
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003881 if (__is_sar_start(control))
3882 len -= 2;
3883
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003884 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003885 len -= 2;
3886
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003887 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003888 goto drop;
3889
3890 tx_seq = __get_txseq(control);
3891
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003892 if (chan->expected_tx_seq == tx_seq)
3893 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003894 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003895 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003896
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003897 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003898
3899 goto done;
3900
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003901 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003902 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003903 break;
3904 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905
3906drop:
3907 kfree_skb(skb);
3908
3909done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003910 if (sk)
3911 bh_unlock_sock(sk);
3912
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913 return 0;
3914}
3915
Al Viro8e036fc2007-07-29 00:16:36 -07003916static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003918 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003919 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003921 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3922 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923 goto drop;
3924
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003925 sk = chan->sk;
3926
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003927 bh_lock_sock(sk);
3928
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929 BT_DBG("sk %p, len %d", sk, skb->len);
3930
3931 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3932 goto drop;
3933
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003934 if (l2cap_pi(sk)->chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003935 goto drop;
3936
3937 if (!sock_queue_rcv_skb(sk, skb))
3938 goto done;
3939
3940drop:
3941 kfree_skb(skb);
3942
3943done:
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03003944 if (sk)
3945 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 return 0;
3947}
3948
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003949static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3950{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003951 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003952 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003953
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003954 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3955 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003956 goto drop;
3957
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003958 sk = chan->sk;
3959
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003960 bh_lock_sock(sk);
3961
3962 BT_DBG("sk %p, len %d", sk, skb->len);
3963
3964 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3965 goto drop;
3966
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003967 if (l2cap_pi(sk)->chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003968 goto drop;
3969
3970 if (!sock_queue_rcv_skb(sk, skb))
3971 goto done;
3972
3973drop:
3974 kfree_skb(skb);
3975
3976done:
3977 if (sk)
3978 bh_unlock_sock(sk);
3979 return 0;
3980}
3981
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3983{
3984 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003985 u16 cid, len;
3986 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987
3988 skb_pull(skb, L2CAP_HDR_SIZE);
3989 cid = __le16_to_cpu(lh->cid);
3990 len = __le16_to_cpu(lh->len);
3991
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003992 if (len != skb->len) {
3993 kfree_skb(skb);
3994 return;
3995 }
3996
Linus Torvalds1da177e2005-04-16 15:20:36 -07003997 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3998
3999 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004000 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004001 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002 l2cap_sig_channel(conn, skb);
4003 break;
4004
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004005 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004006 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007 skb_pull(skb, 2);
4008 l2cap_conless_channel(conn, psm, skb);
4009 break;
4010
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004011 case L2CAP_CID_LE_DATA:
4012 l2cap_att_channel(conn, cid, skb);
4013 break;
4014
Linus Torvalds1da177e2005-04-16 15:20:36 -07004015 default:
4016 l2cap_data_channel(conn, cid, skb);
4017 break;
4018 }
4019}
4020
4021/* ---- L2CAP interface with lower layer (HCI) ---- */
4022
4023static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4024{
4025 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004026 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027
4028 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004029 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004030
4031 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4032
4033 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004034 read_lock(&chan_list_lock);
4035 list_for_each_entry(c, &chan_list, global_l) {
4036 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004037
Linus Torvalds1da177e2005-04-16 15:20:36 -07004038 if (sk->sk_state != BT_LISTEN)
4039 continue;
4040
4041 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004042 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004043 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004044 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004046 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4047 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004048 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004049 lm2 |= HCI_LM_MASTER;
4050 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004052 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053
4054 return exact ? lm1 : lm2;
4055}
4056
4057static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4058{
Marcel Holtmann01394182006-07-03 10:02:46 +02004059 struct l2cap_conn *conn;
4060
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4062
Ville Tervoacd7d372011-02-10 22:38:49 -03004063 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004064 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065
4066 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067 conn = l2cap_conn_add(hcon, status);
4068 if (conn)
4069 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004070 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071 l2cap_conn_del(hcon, bt_err(status));
4072
4073 return 0;
4074}
4075
Marcel Holtmann2950f212009-02-12 14:02:50 +01004076static int l2cap_disconn_ind(struct hci_conn *hcon)
4077{
4078 struct l2cap_conn *conn = hcon->l2cap_data;
4079
4080 BT_DBG("hcon %p", hcon);
4081
4082 if (hcon->type != ACL_LINK || !conn)
4083 return 0x13;
4084
4085 return conn->disc_reason;
4086}
4087
4088static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089{
4090 BT_DBG("hcon %p reason %d", hcon, reason);
4091
Ville Tervoacd7d372011-02-10 22:38:49 -03004092 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004093 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094
4095 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004096
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097 return 0;
4098}
4099
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004100static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004101{
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004102 struct sock *sk = chan->sk;
4103
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03004104 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004105 return;
4106
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004107 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004108 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004109 l2cap_sock_clear_timer(sk);
4110 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004111 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan6e9e43f2011-04-28 17:55:53 -03004112 __l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004113 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004114 if (chan->sec_level == BT_SECURITY_MEDIUM)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004115 l2cap_sock_clear_timer(sk);
4116 }
4117}
4118
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004119static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004121 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004122 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123
Marcel Holtmann01394182006-07-03 10:02:46 +02004124 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004126
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127 BT_DBG("conn %p", conn);
4128
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004129 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004131 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004132 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004133
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134 bh_lock_sock(sk);
4135
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03004136 if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004137 bh_unlock_sock(sk);
4138 continue;
4139 }
4140
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004141 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004142 sk->sk_state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004143 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004144 bh_unlock_sock(sk);
4145 continue;
4146 }
4147
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004148 if (sk->sk_state == BT_CONNECT) {
4149 if (!status) {
4150 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004151 req.scid = cpu_to_le16(chan->scid);
4152 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004153
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004154 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03004155 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004156
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004157 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004158 L2CAP_CONN_REQ, sizeof(req), &req);
4159 } else {
4160 l2cap_sock_clear_timer(sk);
4161 l2cap_sock_set_timer(sk, HZ / 10);
4162 }
4163 } else if (sk->sk_state == BT_CONNECT2) {
4164 struct l2cap_conn_rsp rsp;
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004165 __u16 res, stat;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004166
4167 if (!status) {
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004168 if (bt_sk(sk)->defer_setup) {
4169 struct sock *parent = bt_sk(sk)->parent;
4170 res = L2CAP_CR_PEND;
4171 stat = L2CAP_CS_AUTHOR_PEND;
4172 parent->sk_data_ready(parent, 0);
4173 } else {
4174 sk->sk_state = BT_CONFIG;
4175 res = L2CAP_CR_SUCCESS;
4176 stat = L2CAP_CS_NO_INFO;
4177 }
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004178 } else {
4179 sk->sk_state = BT_DISCONN;
4180 l2cap_sock_set_timer(sk, HZ / 10);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004181 res = L2CAP_CR_SEC_BLOCK;
4182 stat = L2CAP_CS_NO_INFO;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004183 }
4184
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004185 rsp.scid = cpu_to_le16(chan->dcid);
4186 rsp.dcid = cpu_to_le16(chan->scid);
Johan Hedbergdf3c3932011-06-14 12:48:19 +03004187 rsp.result = cpu_to_le16(res);
4188 rsp.status = cpu_to_le16(stat);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004189 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4190 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191 }
4192
Linus Torvalds1da177e2005-04-16 15:20:36 -07004193 bh_unlock_sock(sk);
4194 }
4195
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004196 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004197
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198 return 0;
4199}
4200
4201static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4202{
4203 struct l2cap_conn *conn = hcon->l2cap_data;
4204
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004205 if (!conn)
4206 conn = l2cap_conn_add(hcon, 0);
4207
4208 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209 goto drop;
4210
4211 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4212
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004213 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004215 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004216 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217 int len;
4218
4219 if (conn->rx_len) {
4220 BT_ERR("Unexpected start frame (len %d)", skb->len);
4221 kfree_skb(conn->rx_skb);
4222 conn->rx_skb = NULL;
4223 conn->rx_len = 0;
4224 l2cap_conn_unreliable(conn, ECOMM);
4225 }
4226
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004227 /* Start fragment always begin with Basic L2CAP header */
4228 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229 BT_ERR("Frame is too short (len %d)", skb->len);
4230 l2cap_conn_unreliable(conn, ECOMM);
4231 goto drop;
4232 }
4233
4234 hdr = (struct l2cap_hdr *) skb->data;
4235 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004236 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004237
4238 if (len == skb->len) {
4239 /* Complete frame received */
4240 l2cap_recv_frame(conn, skb);
4241 return 0;
4242 }
4243
4244 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4245
4246 if (skb->len > len) {
4247 BT_ERR("Frame is too long (len %d, expected len %d)",
4248 skb->len, len);
4249 l2cap_conn_unreliable(conn, ECOMM);
4250 goto drop;
4251 }
4252
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004253 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004254
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004255 if (chan && chan->sk) {
4256 struct sock *sk = chan->sk;
4257
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004258 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004259 BT_ERR("Frame exceeding recv MTU (len %d, "
4260 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004261 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004262 bh_unlock_sock(sk);
4263 l2cap_conn_unreliable(conn, ECOMM);
4264 goto drop;
4265 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004266 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004267 }
4268
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b302009-04-20 01:31:08 -03004270 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4271 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272 goto drop;
4273
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004274 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004275 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276 conn->rx_len = len - skb->len;
4277 } else {
4278 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4279
4280 if (!conn->rx_len) {
4281 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4282 l2cap_conn_unreliable(conn, ECOMM);
4283 goto drop;
4284 }
4285
4286 if (skb->len > conn->rx_len) {
4287 BT_ERR("Fragment is too long (len %d, expected %d)",
4288 skb->len, conn->rx_len);
4289 kfree_skb(conn->rx_skb);
4290 conn->rx_skb = NULL;
4291 conn->rx_len = 0;
4292 l2cap_conn_unreliable(conn, ECOMM);
4293 goto drop;
4294 }
4295
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004296 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004297 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004298 conn->rx_len -= skb->len;
4299
4300 if (!conn->rx_len) {
4301 /* Complete frame received */
4302 l2cap_recv_frame(conn, conn->rx_skb);
4303 conn->rx_skb = NULL;
4304 }
4305 }
4306
4307drop:
4308 kfree_skb(skb);
4309 return 0;
4310}
4311
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004312static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004313{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004314 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004315
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004316 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004318 list_for_each_entry(c, &chan_list, global_l) {
4319 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004320
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004321 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 +01004322 batostr(&bt_sk(sk)->src),
4323 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004324 sk->sk_state, __le16_to_cpu(c->psm),
4325 c->scid, c->dcid, c->imtu, c->omtu,
4326 c->sec_level, c->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004327 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004328
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004329 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004330
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004331 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332}
4333
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004334static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4335{
4336 return single_open(file, l2cap_debugfs_show, inode->i_private);
4337}
4338
4339static const struct file_operations l2cap_debugfs_fops = {
4340 .open = l2cap_debugfs_open,
4341 .read = seq_read,
4342 .llseek = seq_lseek,
4343 .release = single_release,
4344};
4345
4346static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347
Linus Torvalds1da177e2005-04-16 15:20:36 -07004348static struct hci_proto l2cap_hci_proto = {
4349 .name = "L2CAP",
4350 .id = HCI_PROTO_L2CAP,
4351 .connect_ind = l2cap_connect_ind,
4352 .connect_cfm = l2cap_connect_cfm,
4353 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004354 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004355 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004356 .recv_acldata = l2cap_recv_acldata
4357};
4358
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004359int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004360{
4361 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004362
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004363 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004364 if (err < 0)
4365 return err;
4366
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004367 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004368 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004369 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004370 goto error;
4371 }
4372
4373 err = hci_register_proto(&l2cap_hci_proto);
4374 if (err < 0) {
4375 BT_ERR("L2CAP protocol registration failed");
4376 bt_sock_unregister(BTPROTO_L2CAP);
4377 goto error;
4378 }
4379
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004380 if (bt_debugfs) {
4381 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4382 bt_debugfs, NULL, &l2cap_debugfs_fops);
4383 if (!l2cap_debugfs)
4384 BT_ERR("Failed to create L2CAP debug file");
4385 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004386
Linus Torvalds1da177e2005-04-16 15:20:36 -07004387 return 0;
4388
4389error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004390 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004391 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392 return err;
4393}
4394
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004395void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004397 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004399 flush_workqueue(_busy_wq);
4400 destroy_workqueue(_busy_wq);
4401
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4403 BT_ERR("L2CAP protocol unregistration failed");
4404
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004405 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406}
4407
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004408module_param(disable_ertm, bool, 0644);
4409MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");