blob: 14c760c8ffe798e1f3441c4c9d1902a6fb1c2115 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
7 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation;
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
16 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090017 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090022 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
23 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 SOFTWARE IS DISCLAIMED.
25*/
26
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020027/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30
31#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080032#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
34#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/poll.h>
38#include <linux/fcntl.h>
39#include <linux/init.h>
40#include <linux/interrupt.h>
41#include <linux/socket.h>
42#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080044#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010045#include <linux/debugfs.h>
46#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030047#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030048#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/sock.h>
50
51#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
57
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020058int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020059
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070060static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010061static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030063static struct workqueue_struct *_busy_wq;
64
Gustavo F. Padovan23691d72011-04-27 18:26:32 -030065LIST_HEAD(chan_list);
66DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030068static void l2cap_busy_work(struct work_struct *work);
69
Linus Torvalds1da177e2005-04-16 15:20:36 -070070static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
71 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030072static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
73 void *data);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030074static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030075static void l2cap_send_disconn_req(struct l2cap_conn *conn,
76 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030078static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
79
Marcel Holtmann01394182006-07-03 10:02:46 +020080/* ---- L2CAP channels ---- */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030081static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020082{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030083 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030084
85 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030086 if (c->dcid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030087 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020088 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030089 return NULL;
90
Marcel Holtmann01394182006-07-03 10:02:46 +020091}
92
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030093static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020094{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030095 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030096
97 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030098 if (c->scid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030099 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200100 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300101 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200102}
103
104/* Find channel with given SCID.
105 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300106static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200107{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300108 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300109
110 read_lock(&conn->chan_lock);
111 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300112 if (c)
113 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300114 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300115 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200116}
117
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300118static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200119{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300120 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300121
122 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300123 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300124 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200125 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300126 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200127}
128
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300129static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200130{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300131 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300132
133 read_lock(&conn->chan_lock);
134 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300135 if (c)
136 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300137 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300138 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200139}
140
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300141static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300142{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300143 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300144
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300145 list_for_each_entry(c, &chan_list, global_l) {
146 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300147 goto found;
148 }
149
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300150 c = NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300151found:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300152 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300153}
154
155int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
156{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300157 int err;
158
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300159 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300160
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300161 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300162 err = -EADDRINUSE;
163 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300164 }
165
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300166 if (psm) {
167 chan->psm = psm;
168 chan->sport = psm;
169 err = 0;
170 } else {
171 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300172
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300173 err = -EINVAL;
174 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300175 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300176 chan->psm = cpu_to_le16(p);
177 chan->sport = cpu_to_le16(p);
178 err = 0;
179 break;
180 }
181 }
182
183done:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300184 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300185 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300186}
187
188int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
189{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300190 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300191
192 chan->scid = scid;
193
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300194 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300195
196 return 0;
197}
198
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300199static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200200{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300201 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200202
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300203 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300204 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200205 return cid;
206 }
207
208 return 0;
209}
210
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300211struct l2cap_chan *l2cap_chan_create(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200212{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300213 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200214
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300215 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
216 if (!chan)
217 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200218
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300219 chan->sk = sk;
220
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300221 write_lock_bh(&chan_list_lock);
222 list_add(&chan->global_l, &chan_list);
223 write_unlock_bh(&chan_list_lock);
224
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300225 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200226}
227
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300228void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300229{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300230 write_lock_bh(&chan_list_lock);
231 list_del(&chan->global_l);
232 write_unlock_bh(&chan_list_lock);
233
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300234 kfree(chan);
235}
236
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300237static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200238{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300239 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200240
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300241 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300242 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200243
Marcel Holtmann2950f212009-02-12 14:02:50 +0100244 conn->disc_reason = 0x13;
245
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300246 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200247
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300248 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Ville Tervob62f3282011-02-10 22:38:50 -0300249 if (conn->hcon->type == LE_LINK) {
250 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300251 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300252 chan->scid = L2CAP_CID_LE_DATA;
253 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300254 } else {
255 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300256 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300257 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300258 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200259 } else if (sk->sk_type == SOCK_DGRAM) {
260 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300261 chan->scid = L2CAP_CID_CONN_LESS;
262 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300263 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200264 } else {
265 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300266 chan->scid = L2CAP_CID_SIGNALING;
267 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300268 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200269 }
270
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300271 sock_hold(sk);
272
273 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200274}
275
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900276/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200277 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300278static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200279{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300280 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300281 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200282 struct sock *parent = bt_sk(sk)->parent;
283
284 l2cap_sock_clear_timer(sk);
285
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300286 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200287
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900288 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300289 /* Delete from channel list */
290 write_lock_bh(&conn->chan_lock);
291 list_del(&chan->list);
292 write_unlock_bh(&conn->chan_lock);
293 __sock_put(sk);
294
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300295 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200296 hci_conn_put(conn->hcon);
297 }
298
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200299 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200300 sock_set_flag(sk, SOCK_ZAPPED);
301
302 if (err)
303 sk->sk_err = err;
304
305 if (parent) {
306 bt_accept_unlink(sk);
307 parent->sk_data_ready(parent, 0);
308 } else
309 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300310
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300311 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE &&
312 chan->conf_state & L2CAP_CONF_INPUT_DONE))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300313 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300314
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300315 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300316
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300317 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300318 struct srej_list *l, *tmp;
319
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300320 del_timer(&chan->retrans_timer);
321 del_timer(&chan->monitor_timer);
322 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300323
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300324 skb_queue_purge(&chan->srej_q);
325 skb_queue_purge(&chan->busy_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300326
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300327 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300328 list_del(&l->list);
329 kfree(l);
330 }
331 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200332}
333
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300334/* Must be called on unlocked socket. */
335static void l2cap_chan_close(struct sock *sk)
336{
337 l2cap_sock_clear_timer(sk);
338 lock_sock(sk);
339 __l2cap_chan_close(l2cap_pi(sk)->chan, ECONNRESET);
340 release_sock(sk);
341 l2cap_sock_kill(sk);
342}
343
344static void l2cap_chan_cleanup_listen(struct sock *parent)
345{
346 struct sock *sk;
347
348 BT_DBG("parent %p", parent);
349
350 /* Close not yet accepted channels */
351 while ((sk = bt_accept_dequeue(parent, NULL)))
352 l2cap_chan_close(sk);
353
354 parent->sk_state = BT_CLOSED;
355 sock_set_flag(parent, SOCK_ZAPPED);
356}
357
358void __l2cap_chan_close(struct l2cap_chan *chan, int reason)
359{
360 struct l2cap_conn *conn = chan->conn;
361 struct sock *sk = chan->sk;
362
363 BT_DBG("chan %p state %d socket %p", chan, sk->sk_state, sk->sk_socket);
364
365 switch (sk->sk_state) {
366 case BT_LISTEN:
367 l2cap_chan_cleanup_listen(sk);
368 break;
369
370 case BT_CONNECTED:
371 case BT_CONFIG:
372 if ((sk->sk_type == SOCK_SEQPACKET ||
373 sk->sk_type == SOCK_STREAM) &&
374 conn->hcon->type == ACL_LINK) {
375 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
376 l2cap_send_disconn_req(conn, chan, reason);
377 } else
378 l2cap_chan_del(chan, reason);
379 break;
380
381 case BT_CONNECT2:
382 if ((sk->sk_type == SOCK_SEQPACKET ||
383 sk->sk_type == SOCK_STREAM) &&
384 conn->hcon->type == ACL_LINK) {
385 struct l2cap_conn_rsp rsp;
386 __u16 result;
387
388 if (bt_sk(sk)->defer_setup)
389 result = L2CAP_CR_SEC_BLOCK;
390 else
391 result = L2CAP_CR_BAD_PSM;
392
393 rsp.scid = cpu_to_le16(chan->dcid);
394 rsp.dcid = cpu_to_le16(chan->scid);
395 rsp.result = cpu_to_le16(result);
396 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
397 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
398 sizeof(rsp), &rsp);
399 }
400
401 l2cap_chan_del(chan, reason);
402 break;
403
404 case BT_CONNECT:
405 case BT_DISCONN:
406 l2cap_chan_del(chan, reason);
407 break;
408
409 default:
410 sock_set_flag(sk, SOCK_ZAPPED);
411 break;
412 }
413}
414
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300415static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530416{
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300417 struct sock *sk = chan->sk;
418
Johan Hedberg8556edd32011-01-19 12:06:50 +0530419 if (sk->sk_type == SOCK_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300420 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530421 case BT_SECURITY_HIGH:
422 return HCI_AT_DEDICATED_BONDING_MITM;
423 case BT_SECURITY_MEDIUM:
424 return HCI_AT_DEDICATED_BONDING;
425 default:
426 return HCI_AT_NO_BONDING;
427 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300428 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300429 if (chan->sec_level == BT_SECURITY_LOW)
430 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530431
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300432 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530433 return HCI_AT_NO_BONDING_MITM;
434 else
435 return HCI_AT_NO_BONDING;
436 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300437 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530438 case BT_SECURITY_HIGH:
439 return HCI_AT_GENERAL_BONDING_MITM;
440 case BT_SECURITY_MEDIUM:
441 return HCI_AT_GENERAL_BONDING;
442 default:
443 return HCI_AT_NO_BONDING;
444 }
445 }
446}
447
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200448/* Service level security */
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300449static inline int l2cap_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200450{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300451 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100452 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200453
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300454 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100455
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300456 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200457}
458
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200459u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200460{
461 u8 id;
462
463 /* Get next available identificator.
464 * 1 - 128 are used by kernel.
465 * 129 - 199 are reserved.
466 * 200 - 254 are used by utilities like l2ping, etc.
467 */
468
469 spin_lock_bh(&conn->lock);
470
471 if (++conn->tx_ident > 128)
472 conn->tx_ident = 1;
473
474 id = conn->tx_ident;
475
476 spin_unlock_bh(&conn->lock);
477
478 return id;
479}
480
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300481static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200482{
483 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200484 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200485
486 BT_DBG("code 0x%2.2x", code);
487
488 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300489 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200490
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200491 if (lmp_no_flush_capable(conn->hcon->hdev))
492 flags = ACL_START_NO_FLUSH;
493 else
494 flags = ACL_START;
495
496 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200497}
498
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300499static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300500{
501 struct sk_buff *skb;
502 struct l2cap_hdr *lh;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300503 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300504 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300505 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300506 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200507 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300508
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300509 if (sk->sk_state != BT_CONNECTED)
510 return;
511
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300512 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300513 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300514
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300515 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300516
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300517 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300518 control |= L2CAP_CTRL_FRAME_TYPE;
519
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300520 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300521 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300522 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300523 }
524
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300525 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300526 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300527 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300528 }
529
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300530 skb = bt_skb_alloc(count, GFP_ATOMIC);
531 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300532 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300533
534 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300535 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300536 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300537 put_unaligned_le16(control, skb_put(skb, 2));
538
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300539 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300540 u16 fcs = crc16(0, (u8 *)lh, count - 2);
541 put_unaligned_le16(fcs, skb_put(skb, 2));
542 }
543
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200544 if (lmp_no_flush_capable(conn->hcon->hdev))
545 flags = ACL_START_NO_FLUSH;
546 else
547 flags = ACL_START;
548
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300549 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300550}
551
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300552static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300553{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300554 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300555 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300556 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300557 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300558 control |= L2CAP_SUPER_RCV_READY;
559
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300560 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300561
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300562 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300563}
564
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300565static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300566{
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300567 return !(chan->conf_state & L2CAP_CONF_CONNECT_PEND);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300568}
569
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300570static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200571{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300572 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200573
574 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100575 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
576 return;
577
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300578 if (l2cap_check_security(chan) &&
579 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200580 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300581 req.scid = cpu_to_le16(chan->scid);
582 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200583
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300584 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300585 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200586
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300587 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
588 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200589 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200590 } else {
591 struct l2cap_info_req req;
592 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
593
594 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
595 conn->info_ident = l2cap_get_ident(conn);
596
597 mod_timer(&conn->info_timer, jiffies +
598 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
599
600 l2cap_send_cmd(conn, conn->info_ident,
601 L2CAP_INFO_REQ, sizeof(req), &req);
602 }
603}
604
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300605static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
606{
607 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300608 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300609 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
610
611 switch (mode) {
612 case L2CAP_MODE_ERTM:
613 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
614 case L2CAP_MODE_STREAMING:
615 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
616 default:
617 return 0x00;
618 }
619}
620
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300621static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300622{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300623 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300624 struct l2cap_disconn_req req;
625
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300626 if (!conn)
627 return;
628
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300629 sk = chan->sk;
630
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300631 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300632 del_timer(&chan->retrans_timer);
633 del_timer(&chan->monitor_timer);
634 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300635 }
636
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300637 req.dcid = cpu_to_le16(chan->dcid);
638 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300639 l2cap_send_cmd(conn, l2cap_get_ident(conn),
640 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300641
642 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300643 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300644}
645
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200647static void l2cap_conn_start(struct l2cap_conn *conn)
648{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300649 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200650
651 BT_DBG("conn %p", conn);
652
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300653 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200654
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300655 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300656 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300657
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200658 bh_lock_sock(sk);
659
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300660 if (sk->sk_type != SOCK_SEQPACKET &&
661 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200662 bh_unlock_sock(sk);
663 continue;
664 }
665
666 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300667 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300668
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300669 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300670 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300671 bh_unlock_sock(sk);
672 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200673 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300674
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300675 if (!l2cap_mode_supported(chan->mode,
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300676 conn->feat_mask)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300677 && chan->conf_state &
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300678 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300679 /* __l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300680 * so release the lock */
681 read_unlock_bh(&conn->chan_lock);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300682 __l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300683 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300684 bh_unlock_sock(sk);
685 continue;
686 }
687
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300688 req.scid = cpu_to_le16(chan->scid);
689 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300690
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300691 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300692 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300693
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300694 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
695 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300696
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200697 } else if (sk->sk_state == BT_CONNECT2) {
698 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300699 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300700 rsp.scid = cpu_to_le16(chan->dcid);
701 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200702
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300703 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100704 if (bt_sk(sk)->defer_setup) {
705 struct sock *parent = bt_sk(sk)->parent;
706 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
707 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
708 parent->sk_data_ready(parent, 0);
709
710 } else {
711 sk->sk_state = BT_CONFIG;
712 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
713 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
714 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200715 } else {
716 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
717 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
718 }
719
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300720 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
721 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300722
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300723 if (chan->conf_state & L2CAP_CONF_REQ_SENT ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300724 rsp.result != L2CAP_CR_SUCCESS) {
725 bh_unlock_sock(sk);
726 continue;
727 }
728
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300729 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300730 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300731 l2cap_build_conf_req(chan, buf), buf);
732 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200733 }
734
735 bh_unlock_sock(sk);
736 }
737
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300738 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200739}
740
Ville Tervob62f3282011-02-10 22:38:50 -0300741/* Find socket with cid and source bdaddr.
742 * Returns closest match, locked.
743 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300744static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300745{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300746 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300747
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300748 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300749
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300750 list_for_each_entry(c, &chan_list, global_l) {
751 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300752
Ville Tervob62f3282011-02-10 22:38:50 -0300753 if (state && sk->sk_state != state)
754 continue;
755
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300756 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300757 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300758 if (!bacmp(&bt_sk(sk)->src, src)) {
759 read_unlock(&chan_list_lock);
760 return c;
761 }
Ville Tervob62f3282011-02-10 22:38:50 -0300762
763 /* Closest match */
764 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300765 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300766 }
767 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300768
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300769 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300770
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300771 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300772}
773
774static void l2cap_le_conn_ready(struct l2cap_conn *conn)
775{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300776 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300777 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300778
779 BT_DBG("");
780
781 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300782 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300783 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300784 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300785 return;
786
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300787 parent = pchan->sk;
788
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300789 bh_lock_sock(parent);
790
Ville Tervob62f3282011-02-10 22:38:50 -0300791 /* Check for backlog size */
792 if (sk_acceptq_is_full(parent)) {
793 BT_DBG("backlog full %d", parent->sk_ack_backlog);
794 goto clean;
795 }
796
797 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
798 if (!sk)
799 goto clean;
800
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300801 chan = l2cap_chan_create(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300802 if (!chan) {
803 l2cap_sock_kill(sk);
804 goto clean;
805 }
806
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300807 l2cap_pi(sk)->chan = chan;
808
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300809 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300810
811 hci_conn_hold(conn->hcon);
812
813 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300814
Ville Tervob62f3282011-02-10 22:38:50 -0300815 bacpy(&bt_sk(sk)->src, conn->src);
816 bacpy(&bt_sk(sk)->dst, conn->dst);
817
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300818 bt_accept_enqueue(parent, sk);
819
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300820 __l2cap_chan_add(conn, chan);
821
Ville Tervob62f3282011-02-10 22:38:50 -0300822 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
823
824 sk->sk_state = BT_CONNECTED;
825 parent->sk_data_ready(parent, 0);
826
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300827 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300828
829clean:
830 bh_unlock_sock(parent);
831}
832
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200833static void l2cap_conn_ready(struct l2cap_conn *conn)
834{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300835 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200836
837 BT_DBG("conn %p", conn);
838
Ville Tervob62f3282011-02-10 22:38:50 -0300839 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
840 l2cap_le_conn_ready(conn);
841
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300842 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200843
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300844 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300845 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300846
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200847 bh_lock_sock(sk);
848
Ville Tervoacd7d372011-02-10 22:38:49 -0300849 if (conn->hcon->type == LE_LINK) {
850 l2cap_sock_clear_timer(sk);
851 sk->sk_state = BT_CONNECTED;
852 sk->sk_state_change(sk);
853 }
854
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300855 if (sk->sk_type != SOCK_SEQPACKET &&
856 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200857 l2cap_sock_clear_timer(sk);
858 sk->sk_state = BT_CONNECTED;
859 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200860 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300861 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200862
863 bh_unlock_sock(sk);
864 }
865
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300866 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200867}
868
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200869/* Notify sockets that we cannot guaranty reliability anymore */
870static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
871{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300872 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200873
874 BT_DBG("conn %p", conn);
875
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300876 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200877
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300878 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300879 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300880
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300881 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200882 sk->sk_err = err;
883 }
884
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300885 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200886}
887
888static void l2cap_info_timeout(unsigned long arg)
889{
890 struct l2cap_conn *conn = (void *) arg;
891
Marcel Holtmann984947d2009-02-06 23:35:19 +0100892 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100893 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100894
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200895 l2cap_conn_start(conn);
896}
897
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
899{
Marcel Holtmann01394182006-07-03 10:02:46 +0200900 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901
Marcel Holtmann01394182006-07-03 10:02:46 +0200902 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 return conn;
904
Marcel Holtmann01394182006-07-03 10:02:46 +0200905 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
906 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908
909 hcon->l2cap_data = conn;
910 conn->hcon = hcon;
911
Marcel Holtmann01394182006-07-03 10:02:46 +0200912 BT_DBG("hcon %p conn %p", hcon, conn);
913
Ville Tervoacd7d372011-02-10 22:38:49 -0300914 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
915 conn->mtu = hcon->hdev->le_mtu;
916 else
917 conn->mtu = hcon->hdev->acl_mtu;
918
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 conn->src = &hcon->hdev->bdaddr;
920 conn->dst = &hcon->dst;
921
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200922 conn->feat_mask = 0;
923
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300925 rwlock_init(&conn->chan_lock);
926
927 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928
Ville Tervob62f3282011-02-10 22:38:50 -0300929 if (hcon->type != LE_LINK)
930 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000931 (unsigned long) conn);
932
Marcel Holtmann2950f212009-02-12 14:02:50 +0100933 conn->disc_reason = 0x13;
934
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 return conn;
936}
937
Marcel Holtmann01394182006-07-03 10:02:46 +0200938static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939{
Marcel Holtmann01394182006-07-03 10:02:46 +0200940 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300941 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 struct sock *sk;
943
Marcel Holtmann01394182006-07-03 10:02:46 +0200944 if (!conn)
945 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946
947 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
948
Wei Yongjun7585b972009-02-25 18:29:52 +0800949 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950
951 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300952 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300953 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300955 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 bh_unlock_sock(sk);
957 l2cap_sock_kill(sk);
958 }
959
Dave Young8e8440f2008-03-03 12:18:55 -0800960 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
961 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800962
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 hcon->l2cap_data = NULL;
964 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965}
966
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300967static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300969 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300970 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300971 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972}
973
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975
976/* Find socket with psm and source bdaddr.
977 * Returns closest match.
978 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300979static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300981 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300983 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000984
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300985 list_for_each_entry(c, &chan_list, global_l) {
986 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300987
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 if (state && sk->sk_state != state)
989 continue;
990
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300991 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300993 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +0200994 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300995 return c;
996 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997
998 /* Closest match */
999 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001000 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 }
1002 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001004 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001005
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001006 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007}
1008
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001009int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001011 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 bdaddr_t *src = &bt_sk(sk)->src;
1013 bdaddr_t *dst = &bt_sk(sk)->dst;
1014 struct l2cap_conn *conn;
1015 struct hci_conn *hcon;
1016 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001017 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001018 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001020 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001021 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001023 hdev = hci_get_route(dst, src);
1024 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 return -EHOSTUNREACH;
1026
1027 hci_dev_lock_bh(hdev);
1028
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001029 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001030
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001031 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001032 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001033 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001034 else
1035 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001036 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001037
Ville Tervo30e76272011-02-22 16:10:53 -03001038 if (IS_ERR(hcon)) {
1039 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001041 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042
1043 conn = l2cap_conn_add(hcon, 0);
1044 if (!conn) {
1045 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001046 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 goto done;
1048 }
1049
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 /* Update source addr of the socket */
1051 bacpy(src, conn->src);
1052
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001053 l2cap_chan_add(conn, chan);
1054
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 sk->sk_state = BT_CONNECT;
1056 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
1057
1058 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001059 if (sk->sk_type != SOCK_SEQPACKET &&
1060 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 l2cap_sock_clear_timer(sk);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001062 if (l2cap_check_security(chan))
Johan Hedbergd00ef242011-01-19 12:06:51 +05301063 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001064 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001065 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 }
1067
Ville Tervo30e76272011-02-22 16:10:53 -03001068 err = 0;
1069
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070done:
1071 hci_dev_unlock_bh(hdev);
1072 hci_dev_put(hdev);
1073 return err;
1074}
1075
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001076int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001077{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001078 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001079 DECLARE_WAITQUEUE(wait, current);
1080 int err = 0;
1081 int timeo = HZ/5;
1082
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001083 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001084 while ((chan->unacked_frames > 0 && chan->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001085 set_current_state(TASK_INTERRUPTIBLE);
1086
1087 if (!timeo)
1088 timeo = HZ/5;
1089
1090 if (signal_pending(current)) {
1091 err = sock_intr_errno(timeo);
1092 break;
1093 }
1094
1095 release_sock(sk);
1096 timeo = schedule_timeout(timeo);
1097 lock_sock(sk);
1098
1099 err = sock_error(sk);
1100 if (err)
1101 break;
1102 }
1103 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001104 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001105 return err;
1106}
1107
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001108static void l2cap_monitor_timeout(unsigned long arg)
1109{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001110 struct l2cap_chan *chan = (void *) arg;
1111 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001112
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001113 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001114
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001115 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001116 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001117 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001118 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001119 return;
1120 }
1121
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001122 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001123 __mod_monitor_timer();
1124
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001125 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001126 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001127}
1128
1129static void l2cap_retrans_timeout(unsigned long arg)
1130{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001131 struct l2cap_chan *chan = (void *) arg;
1132 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001133
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001134 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001135
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001136 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001137 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001138 __mod_monitor_timer();
1139
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001140 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001141
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001142 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001143 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001144}
1145
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001146static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001147{
1148 struct sk_buff *skb;
1149
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001150 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001151 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001152 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001153 break;
1154
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001155 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001156 kfree_skb(skb);
1157
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001158 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001159 }
1160
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001161 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001162 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001163}
1164
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001165void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001166{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001167 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001168 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001169
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001170 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001171
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001172 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001173 flags = ACL_START_NO_FLUSH;
1174 else
1175 flags = ACL_START;
1176
1177 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001178}
1179
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001180void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001181{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001182 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001183 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001184
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001185 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001186 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001187 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001188 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001189
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001190 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001191 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1192 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001193 }
1194
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001195 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001196
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001197 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001198 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001199}
1200
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001201static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001202{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001203 struct sk_buff *skb, *tx_skb;
1204 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001205
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001206 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001207 if (!skb)
1208 return;
1209
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001210 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001211 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001212 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001213
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001214 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001215 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001216
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001217 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001218
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001219 if (chan->remote_max_tx &&
1220 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001221 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001222 return;
1223 }
1224
1225 tx_skb = skb_clone(skb, GFP_ATOMIC);
1226 bt_cb(skb)->retries++;
1227 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001228 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001229
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001230 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001231 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001232 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001233 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001234
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001235 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001236 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001237
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001238 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1239
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001240 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001241 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1242 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1243 }
1244
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001245 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001246}
1247
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001248int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001249{
1250 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001251 struct sock *sk = chan->sk;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001252 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001253 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001254
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001255 if (sk->sk_state != BT_CONNECTED)
1256 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001257
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001258 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001259
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001260 if (chan->remote_max_tx &&
1261 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001262 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001263 break;
1264 }
1265
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001266 tx_skb = skb_clone(skb, GFP_ATOMIC);
1267
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001268 bt_cb(skb)->retries++;
1269
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001270 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001271 control &= L2CAP_CTRL_SAR;
1272
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001273 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001274 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001275 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001276 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001277 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1278 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001279 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1280
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001281
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001282 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001283 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1284 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1285 }
1286
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001287 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001288
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001289 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001290
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001291 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1292 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001293
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301294 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001295 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301296
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001297 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001298
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001299 if (skb_queue_is_last(&chan->tx_q, skb))
1300 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001301 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001302 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001303
1304 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001305 }
1306
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001307 return nsent;
1308}
1309
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001310static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001311{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001312 int ret;
1313
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001314 if (!skb_queue_empty(&chan->tx_q))
1315 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001316
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001317 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001318 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001319 return ret;
1320}
1321
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001322static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001323{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001324 u16 control = 0;
1325
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001326 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001327
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001328 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001329 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001330 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1331 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001332 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001333 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001334
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001335 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001336 return;
1337
1338 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001339 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001340}
1341
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001342static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001343{
1344 struct srej_list *tail;
1345 u16 control;
1346
1347 control = L2CAP_SUPER_SELECT_REJECT;
1348 control |= L2CAP_CTRL_FINAL;
1349
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001350 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001351 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1352
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001353 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001354}
1355
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001356static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001358 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001359 struct sk_buff **frag;
1360 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001362 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001363 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364
1365 sent += count;
1366 len -= count;
1367
1368 /* Continuation fragments (no L2CAP header) */
1369 frag = &skb_shinfo(skb)->frag_list;
1370 while (len) {
1371 count = min_t(unsigned int, conn->mtu, len);
1372
1373 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1374 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001375 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001376 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1377 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378
1379 sent += count;
1380 len -= count;
1381
1382 frag = &(*frag)->next;
1383 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384
1385 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001386}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001388struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001389{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001390 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001391 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001392 struct sk_buff *skb;
1393 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1394 struct l2cap_hdr *lh;
1395
1396 BT_DBG("sk %p len %d", sk, (int)len);
1397
1398 count = min_t(unsigned int, (conn->mtu - hlen), len);
1399 skb = bt_skb_send_alloc(sk, count + hlen,
1400 msg->msg_flags & MSG_DONTWAIT, &err);
1401 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001402 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001403
1404 /* Create L2CAP header */
1405 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001406 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001407 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001408 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001409
1410 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1411 if (unlikely(err < 0)) {
1412 kfree_skb(skb);
1413 return ERR_PTR(err);
1414 }
1415 return skb;
1416}
1417
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001418struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001419{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001420 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001421 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001422 struct sk_buff *skb;
1423 int err, count, hlen = L2CAP_HDR_SIZE;
1424 struct l2cap_hdr *lh;
1425
1426 BT_DBG("sk %p len %d", sk, (int)len);
1427
1428 count = min_t(unsigned int, (conn->mtu - hlen), len);
1429 skb = bt_skb_send_alloc(sk, count + hlen,
1430 msg->msg_flags & MSG_DONTWAIT, &err);
1431 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001432 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001433
1434 /* Create L2CAP header */
1435 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001436 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001437 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1438
1439 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1440 if (unlikely(err < 0)) {
1441 kfree_skb(skb);
1442 return ERR_PTR(err);
1443 }
1444 return skb;
1445}
1446
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001447struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001448{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001449 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001450 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001451 struct sk_buff *skb;
1452 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1453 struct l2cap_hdr *lh;
1454
1455 BT_DBG("sk %p len %d", sk, (int)len);
1456
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001457 if (!conn)
1458 return ERR_PTR(-ENOTCONN);
1459
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001460 if (sdulen)
1461 hlen += 2;
1462
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001463 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001464 hlen += 2;
1465
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001466 count = min_t(unsigned int, (conn->mtu - hlen), len);
1467 skb = bt_skb_send_alloc(sk, count + hlen,
1468 msg->msg_flags & MSG_DONTWAIT, &err);
1469 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001470 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001471
1472 /* Create L2CAP header */
1473 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001474 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001475 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1476 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001477 if (sdulen)
1478 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001479
1480 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1481 if (unlikely(err < 0)) {
1482 kfree_skb(skb);
1483 return ERR_PTR(err);
1484 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001485
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001486 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001487 put_unaligned_le16(0, skb_put(skb, 2));
1488
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001489 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001490 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491}
1492
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001493int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001494{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001495 struct sk_buff *skb;
1496 struct sk_buff_head sar_queue;
1497 u16 control;
1498 size_t size = 0;
1499
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001500 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001501 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001502 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001503 if (IS_ERR(skb))
1504 return PTR_ERR(skb);
1505
1506 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001507 len -= chan->remote_mps;
1508 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001509
1510 while (len > 0) {
1511 size_t buflen;
1512
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001513 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001514 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001515 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001516 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001517 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001518 buflen = len;
1519 }
1520
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001521 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001522 if (IS_ERR(skb)) {
1523 skb_queue_purge(&sar_queue);
1524 return PTR_ERR(skb);
1525 }
1526
1527 __skb_queue_tail(&sar_queue, skb);
1528 len -= buflen;
1529 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001530 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001531 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1532 if (chan->tx_send_head == NULL)
1533 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001534
1535 return size;
1536}
1537
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538static void l2cap_chan_ready(struct sock *sk)
1539{
1540 struct sock *parent = bt_sk(sk)->parent;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001541 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542
1543 BT_DBG("sk %p, parent %p", sk, parent);
1544
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001545 chan->conf_state = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 l2cap_sock_clear_timer(sk);
1547
1548 if (!parent) {
1549 /* Outgoing channel.
1550 * Wake up socket sleeping on connect.
1551 */
1552 sk->sk_state = BT_CONNECTED;
1553 sk->sk_state_change(sk);
1554 } else {
1555 /* Incoming channel.
1556 * Wake up socket sleeping on accept.
1557 */
1558 parent->sk_data_ready(parent, 0);
1559 }
1560}
1561
1562/* Copy frame to all raw sockets on that connection */
1563static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1564{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001566 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567
1568 BT_DBG("conn %p", conn);
1569
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001570 read_lock(&conn->chan_lock);
1571 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001572 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 if (sk->sk_type != SOCK_RAW)
1574 continue;
1575
1576 /* Don't send frame to the socket it came from */
1577 if (skb->sk == sk)
1578 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001579 nskb = skb_clone(skb, GFP_ATOMIC);
1580 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 continue;
1582
1583 if (sock_queue_rcv_skb(sk, nskb))
1584 kfree_skb(nskb);
1585 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001586 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587}
1588
1589/* ---- L2CAP signalling commands ---- */
1590static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1591 u8 code, u8 ident, u16 dlen, void *data)
1592{
1593 struct sk_buff *skb, **frag;
1594 struct l2cap_cmd_hdr *cmd;
1595 struct l2cap_hdr *lh;
1596 int len, count;
1597
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001598 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1599 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600
1601 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1602 count = min_t(unsigned int, conn->mtu, len);
1603
1604 skb = bt_skb_alloc(count, GFP_ATOMIC);
1605 if (!skb)
1606 return NULL;
1607
1608 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001609 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001610
1611 if (conn->hcon->type == LE_LINK)
1612 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1613 else
1614 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615
1616 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1617 cmd->code = code;
1618 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001619 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620
1621 if (dlen) {
1622 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1623 memcpy(skb_put(skb, count), data, count);
1624 data += count;
1625 }
1626
1627 len -= skb->len;
1628
1629 /* Continuation fragments (no L2CAP header) */
1630 frag = &skb_shinfo(skb)->frag_list;
1631 while (len) {
1632 count = min_t(unsigned int, conn->mtu, len);
1633
1634 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1635 if (!*frag)
1636 goto fail;
1637
1638 memcpy(skb_put(*frag, count), data, count);
1639
1640 len -= count;
1641 data += count;
1642
1643 frag = &(*frag)->next;
1644 }
1645
1646 return skb;
1647
1648fail:
1649 kfree_skb(skb);
1650 return NULL;
1651}
1652
1653static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1654{
1655 struct l2cap_conf_opt *opt = *ptr;
1656 int len;
1657
1658 len = L2CAP_CONF_OPT_SIZE + opt->len;
1659 *ptr += len;
1660
1661 *type = opt->type;
1662 *olen = opt->len;
1663
1664 switch (opt->len) {
1665 case 1:
1666 *val = *((u8 *) opt->val);
1667 break;
1668
1669 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001670 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 break;
1672
1673 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001674 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675 break;
1676
1677 default:
1678 *val = (unsigned long) opt->val;
1679 break;
1680 }
1681
1682 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1683 return len;
1684}
1685
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1687{
1688 struct l2cap_conf_opt *opt = *ptr;
1689
1690 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1691
1692 opt->type = type;
1693 opt->len = len;
1694
1695 switch (len) {
1696 case 1:
1697 *((u8 *) opt->val) = val;
1698 break;
1699
1700 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001701 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 break;
1703
1704 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001705 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 break;
1707
1708 default:
1709 memcpy(opt->val, (void *) val, len);
1710 break;
1711 }
1712
1713 *ptr += L2CAP_CONF_OPT_SIZE + len;
1714}
1715
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001716static void l2cap_ack_timeout(unsigned long arg)
1717{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001718 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001719
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001720 bh_lock_sock(chan->sk);
1721 l2cap_send_ack(chan);
1722 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001723}
1724
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001725static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001726{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001727 struct sock *sk = chan->sk;
1728
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001729 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001730 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001731 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001732 chan->num_acked = 0;
1733 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001734
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001735 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1736 (unsigned long) chan);
1737 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1738 (unsigned long) chan);
1739 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001740
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001741 skb_queue_head_init(&chan->srej_q);
1742 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001743
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001744 INIT_LIST_HEAD(&chan->srej_l);
1745
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001746 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001747
1748 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001749}
1750
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001751static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1752{
1753 switch (mode) {
1754 case L2CAP_MODE_STREAMING:
1755 case L2CAP_MODE_ERTM:
1756 if (l2cap_mode_supported(mode, remote_feat_mask))
1757 return mode;
1758 /* fall through */
1759 default:
1760 return L2CAP_MODE_BASIC;
1761 }
1762}
1763
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001764static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001767 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 void *ptr = req->data;
1769
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001770 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001772 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001773 goto done;
1774
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001775 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001776 case L2CAP_MODE_STREAMING:
1777 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001778 if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001779 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001780
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001781 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001782 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001783 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001784 break;
1785 }
1786
1787done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001788 if (chan->imtu != L2CAP_DEFAULT_MTU)
1789 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001790
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001791 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001792 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001793 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1794 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001795 break;
1796
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001797 rfc.mode = L2CAP_MODE_BASIC;
1798 rfc.txwin_size = 0;
1799 rfc.max_transmit = 0;
1800 rfc.retrans_timeout = 0;
1801 rfc.monitor_timeout = 0;
1802 rfc.max_pdu_size = 0;
1803
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001804 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1805 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001806 break;
1807
1808 case L2CAP_MODE_ERTM:
1809 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001810 rfc.txwin_size = chan->tx_win;
1811 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001812 rfc.retrans_timeout = 0;
1813 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001814 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001815 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1816 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001817
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001818 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1819 (unsigned long) &rfc);
1820
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001821 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001822 break;
1823
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001824 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001825 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001826 chan->fcs = L2CAP_FCS_NONE;
1827 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001828 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001829 break;
1830
1831 case L2CAP_MODE_STREAMING:
1832 rfc.mode = L2CAP_MODE_STREAMING;
1833 rfc.txwin_size = 0;
1834 rfc.max_transmit = 0;
1835 rfc.retrans_timeout = 0;
1836 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001837 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001838 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1839 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001840
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001841 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1842 (unsigned long) &rfc);
1843
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001844 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001845 break;
1846
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001847 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001848 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001849 chan->fcs = L2CAP_FCS_NONE;
1850 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001851 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001852 break;
1853 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001855 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001856 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857
1858 return ptr - data;
1859}
1860
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001861static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001863 struct l2cap_conf_rsp *rsp = data;
1864 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001865 void *req = chan->conf_req;
1866 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001867 int type, hint, olen;
1868 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001869 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001870 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001871 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001873 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001874
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001875 while (len >= L2CAP_CONF_OPT_SIZE) {
1876 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001878 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001879 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001880
1881 switch (type) {
1882 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001883 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001884 break;
1885
1886 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001887 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001888 break;
1889
1890 case L2CAP_CONF_QOS:
1891 break;
1892
Marcel Holtmann6464f352007-10-20 13:39:51 +02001893 case L2CAP_CONF_RFC:
1894 if (olen == sizeof(rfc))
1895 memcpy(&rfc, (void *) val, olen);
1896 break;
1897
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001898 case L2CAP_CONF_FCS:
1899 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001900 chan->conf_state |= L2CAP_CONF_NO_FCS_RECV;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001901
1902 break;
1903
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001904 default:
1905 if (hint)
1906 break;
1907
1908 result = L2CAP_CONF_UNKNOWN;
1909 *((u8 *) ptr++) = type;
1910 break;
1911 }
1912 }
1913
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001914 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001915 goto done;
1916
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001917 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001918 case L2CAP_MODE_STREAMING:
1919 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001920 if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001921 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001922 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001923 break;
1924 }
1925
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001926 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001927 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001928
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001929 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001930 }
1931
1932done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001933 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001934 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001935 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001936
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001937 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001938 return -ECONNREFUSED;
1939
1940 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1941 sizeof(rfc), (unsigned long) &rfc);
1942 }
1943
1944
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001945 if (result == L2CAP_CONF_SUCCESS) {
1946 /* Configure output options and let the other side know
1947 * which ones we don't like. */
1948
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001949 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1950 result = L2CAP_CONF_UNACCEPT;
1951 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001952 chan->omtu = mtu;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001953 chan->conf_state |= L2CAP_CONF_MTU_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001954 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001955 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001956
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001957 switch (rfc.mode) {
1958 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001959 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001960 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001961 break;
1962
1963 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001964 chan->remote_tx_win = rfc.txwin_size;
1965 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001966
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001967 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
1968 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001969
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001970 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001971
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001972 rfc.retrans_timeout =
1973 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1974 rfc.monitor_timeout =
1975 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001976
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001977 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001978
1979 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1980 sizeof(rfc), (unsigned long) &rfc);
1981
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001982 break;
1983
1984 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001985 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
1986 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001987
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001988 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001989
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001990 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001991
1992 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1993 sizeof(rfc), (unsigned long) &rfc);
1994
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001995 break;
1996
1997 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001998 result = L2CAP_CONF_UNACCEPT;
1999
2000 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002001 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002002 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002003
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002004 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002005 chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002006 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002007 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002008 rsp->result = cpu_to_le16(result);
2009 rsp->flags = cpu_to_le16(0x0000);
2010
2011 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012}
2013
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002014static 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 -03002015{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002016 struct l2cap_conf_req *req = data;
2017 void *ptr = req->data;
2018 int type, olen;
2019 unsigned long val;
2020 struct l2cap_conf_rfc rfc;
2021
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002022 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002023
2024 while (len >= L2CAP_CONF_OPT_SIZE) {
2025 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2026
2027 switch (type) {
2028 case L2CAP_CONF_MTU:
2029 if (val < L2CAP_DEFAULT_MIN_MTU) {
2030 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002031 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002032 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002033 chan->imtu = val;
2034 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002035 break;
2036
2037 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002038 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002039 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002040 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002041 break;
2042
2043 case L2CAP_CONF_RFC:
2044 if (olen == sizeof(rfc))
2045 memcpy(&rfc, (void *)val, olen);
2046
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002047 if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002048 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002049 return -ECONNREFUSED;
2050
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002051 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002052
2053 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2054 sizeof(rfc), (unsigned long) &rfc);
2055 break;
2056 }
2057 }
2058
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002059 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002060 return -ECONNREFUSED;
2061
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002062 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002063
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002064 if (*result == L2CAP_CONF_SUCCESS) {
2065 switch (rfc.mode) {
2066 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002067 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2068 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2069 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002070 break;
2071 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002072 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002073 }
2074 }
2075
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002076 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002077 req->flags = cpu_to_le16(0x0000);
2078
2079 return ptr - data;
2080}
2081
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002082static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083{
2084 struct l2cap_conf_rsp *rsp = data;
2085 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002087 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002089 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002090 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002091 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092
2093 return ptr - data;
2094}
2095
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002096void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002097{
2098 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002099 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002100 u8 buf[128];
2101
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002102 rsp.scid = cpu_to_le16(chan->dcid);
2103 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002104 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2105 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2106 l2cap_send_cmd(conn, chan->ident,
2107 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2108
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002109 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002110 return;
2111
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002112 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002113 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2114 l2cap_build_conf_req(chan, buf), buf);
2115 chan->num_conf_req++;
2116}
2117
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002118static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002119{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002120 int type, olen;
2121 unsigned long val;
2122 struct l2cap_conf_rfc rfc;
2123
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002124 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002125
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002126 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002127 return;
2128
2129 while (len >= L2CAP_CONF_OPT_SIZE) {
2130 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2131
2132 switch (type) {
2133 case L2CAP_CONF_RFC:
2134 if (olen == sizeof(rfc))
2135 memcpy(&rfc, (void *)val, olen);
2136 goto done;
2137 }
2138 }
2139
2140done:
2141 switch (rfc.mode) {
2142 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002143 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2144 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2145 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002146 break;
2147 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002148 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002149 }
2150}
2151
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002152static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2153{
2154 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2155
2156 if (rej->reason != 0x0000)
2157 return 0;
2158
2159 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2160 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002161 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002162
2163 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002164 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002165
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002166 l2cap_conn_start(conn);
2167 }
2168
2169 return 0;
2170}
2171
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2173{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2175 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002176 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002177 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002178 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179
2180 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002181 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182
2183 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2184
2185 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002186 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2187 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 result = L2CAP_CR_BAD_PSM;
2189 goto sendresp;
2190 }
2191
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002192 parent = pchan->sk;
2193
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002194 bh_lock_sock(parent);
2195
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002196 /* Check if the ACL is secure enough (if not SDP) */
2197 if (psm != cpu_to_le16(0x0001) &&
2198 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002199 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002200 result = L2CAP_CR_SEC_BLOCK;
2201 goto response;
2202 }
2203
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 result = L2CAP_CR_NO_MEM;
2205
2206 /* Check for backlog size */
2207 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002208 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 goto response;
2210 }
2211
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002212 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 if (!sk)
2214 goto response;
2215
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002216 chan = l2cap_chan_create(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002217 if (!chan) {
2218 l2cap_sock_kill(sk);
2219 goto response;
2220 }
2221
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03002222 l2cap_pi(sk)->chan = chan;
2223
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002224 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225
2226 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002227 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2228 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 sock_set_flag(sk, SOCK_ZAPPED);
2230 l2cap_sock_kill(sk);
2231 goto response;
2232 }
2233
2234 hci_conn_hold(conn->hcon);
2235
2236 l2cap_sock_init(sk, parent);
2237 bacpy(&bt_sk(sk)->src, conn->src);
2238 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002239 chan->psm = psm;
2240 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002242 bt_accept_enqueue(parent, sk);
2243
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002244 __l2cap_chan_add(conn, chan);
2245
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002246 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247
2248 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2249
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002250 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251
Marcel Holtmann984947d2009-02-06 23:35:19 +01002252 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002253 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002254 if (bt_sk(sk)->defer_setup) {
2255 sk->sk_state = BT_CONNECT2;
2256 result = L2CAP_CR_PEND;
2257 status = L2CAP_CS_AUTHOR_PEND;
2258 parent->sk_data_ready(parent, 0);
2259 } else {
2260 sk->sk_state = BT_CONFIG;
2261 result = L2CAP_CR_SUCCESS;
2262 status = L2CAP_CS_NO_INFO;
2263 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002264 } else {
2265 sk->sk_state = BT_CONNECT2;
2266 result = L2CAP_CR_PEND;
2267 status = L2CAP_CS_AUTHEN_PEND;
2268 }
2269 } else {
2270 sk->sk_state = BT_CONNECT2;
2271 result = L2CAP_CR_PEND;
2272 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 }
2274
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002275 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276
2277response:
2278 bh_unlock_sock(parent);
2279
2280sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002281 rsp.scid = cpu_to_le16(scid);
2282 rsp.dcid = cpu_to_le16(dcid);
2283 rsp.result = cpu_to_le16(result);
2284 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002286
2287 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2288 struct l2cap_info_req info;
2289 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2290
2291 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2292 conn->info_ident = l2cap_get_ident(conn);
2293
2294 mod_timer(&conn->info_timer, jiffies +
2295 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2296
2297 l2cap_send_cmd(conn, conn->info_ident,
2298 L2CAP_INFO_REQ, sizeof(info), &info);
2299 }
2300
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002301 if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002302 result == L2CAP_CR_SUCCESS) {
2303 u8 buf[128];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002304 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002305 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002306 l2cap_build_conf_req(chan, buf), buf);
2307 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002308 }
2309
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 return 0;
2311}
2312
2313static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2314{
2315 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2316 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002317 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 struct sock *sk;
2319 u8 req[128];
2320
2321 scid = __le16_to_cpu(rsp->scid);
2322 dcid = __le16_to_cpu(rsp->dcid);
2323 result = __le16_to_cpu(rsp->result);
2324 status = __le16_to_cpu(rsp->status);
2325
2326 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2327
2328 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002329 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002330 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002331 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002333 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002334 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002335 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336 }
2337
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002338 sk = chan->sk;
2339
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 switch (result) {
2341 case L2CAP_CR_SUCCESS:
2342 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002343 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002344 chan->dcid = dcid;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002345 chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002346
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002347 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002348 break;
2349
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002350 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002351
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002353 l2cap_build_conf_req(chan, req), req);
2354 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355 break;
2356
2357 case L2CAP_CR_PEND:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002358 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 break;
2360
2361 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002362 /* don't delete l2cap channel if sk is owned by user */
2363 if (sock_owned_by_user(sk)) {
2364 sk->sk_state = BT_DISCONN;
2365 l2cap_sock_clear_timer(sk);
2366 l2cap_sock_set_timer(sk, HZ / 5);
2367 break;
2368 }
2369
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002370 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371 break;
2372 }
2373
2374 bh_unlock_sock(sk);
2375 return 0;
2376}
2377
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002378static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002379{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002380 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
2381
Mat Martineau8c462b62010-08-24 15:35:42 -07002382 /* FCS is enabled only in ERTM or streaming mode, if one or both
2383 * sides request it.
2384 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002385 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002386 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002387 else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002388 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002389}
2390
Al Viro88219a02007-07-29 00:17:25 -07002391static 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 -07002392{
2393 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2394 u16 dcid, flags;
2395 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002396 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002398 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399
2400 dcid = __le16_to_cpu(req->dcid);
2401 flags = __le16_to_cpu(req->flags);
2402
2403 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2404
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002405 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002406 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407 return -ENOENT;
2408
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002409 sk = chan->sk;
2410
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002411 if (sk->sk_state != BT_CONFIG) {
2412 struct l2cap_cmd_rej rej;
2413
2414 rej.reason = cpu_to_le16(0x0002);
2415 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2416 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002417 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002418 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002419
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002420 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002421 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002422 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002423 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002424 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002425 L2CAP_CONF_REJECT, flags), rsp);
2426 goto unlock;
2427 }
2428
2429 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002430 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2431 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432
2433 if (flags & 0x0001) {
2434 /* Incomplete config. Send empty response. */
2435 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002436 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002437 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438 goto unlock;
2439 }
2440
2441 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002442 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002443 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002444 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002446 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002448 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002449 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002450
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002451 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002452 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002453
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002454 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002455 goto unlock;
2456
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002457 if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002458 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002459
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002461
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002462 chan->next_tx_seq = 0;
2463 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002464 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002465 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002466 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002467
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002469 goto unlock;
2470 }
2471
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002472 if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002473 u8 buf[64];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002474 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002476 l2cap_build_conf_req(chan, buf), buf);
2477 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 }
2479
2480unlock:
2481 bh_unlock_sock(sk);
2482 return 0;
2483}
2484
2485static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2486{
2487 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2488 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002489 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002491 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492
2493 scid = __le16_to_cpu(rsp->scid);
2494 flags = __le16_to_cpu(rsp->flags);
2495 result = __le16_to_cpu(rsp->result);
2496
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002497 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2498 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002500 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002501 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502 return 0;
2503
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002504 sk = chan->sk;
2505
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506 switch (result) {
2507 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002508 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509 break;
2510
2511 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002512 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002513 char req[64];
2514
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002515 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002516 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002517 goto done;
2518 }
2519
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002520 /* throw out any old stored conf requests */
2521 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002522 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2523 req, &result);
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);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002526 goto done;
2527 }
2528
2529 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2530 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002531 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002532 if (result != L2CAP_CONF_SUCCESS)
2533 goto done;
2534 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535 }
2536
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002537 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002538 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002540 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541 goto done;
2542 }
2543
2544 if (flags & 0x01)
2545 goto done;
2546
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002547 chan->conf_state |= L2CAP_CONF_INPUT_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002549 if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002550 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002551
Linus Torvalds1da177e2005-04-16 15:20:36 -07002552 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002553 chan->next_tx_seq = 0;
2554 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002555 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002556 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002557 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002558
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559 l2cap_chan_ready(sk);
2560 }
2561
2562done:
2563 bh_unlock_sock(sk);
2564 return 0;
2565}
2566
2567static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2568{
2569 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2570 struct l2cap_disconn_rsp rsp;
2571 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002572 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573 struct sock *sk;
2574
2575 scid = __le16_to_cpu(req->scid);
2576 dcid = __le16_to_cpu(req->dcid);
2577
2578 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2579
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002580 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002581 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582 return 0;
2583
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002584 sk = chan->sk;
2585
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002586 rsp.dcid = cpu_to_le16(chan->scid);
2587 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2589
2590 sk->sk_shutdown = SHUTDOWN_MASK;
2591
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002592 /* don't delete l2cap channel if sk is owned by user */
2593 if (sock_owned_by_user(sk)) {
2594 sk->sk_state = BT_DISCONN;
2595 l2cap_sock_clear_timer(sk);
2596 l2cap_sock_set_timer(sk, HZ / 5);
2597 bh_unlock_sock(sk);
2598 return 0;
2599 }
2600
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002601 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602 bh_unlock_sock(sk);
2603
2604 l2cap_sock_kill(sk);
2605 return 0;
2606}
2607
2608static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2609{
2610 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2611 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002612 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 struct sock *sk;
2614
2615 scid = __le16_to_cpu(rsp->scid);
2616 dcid = __le16_to_cpu(rsp->dcid);
2617
2618 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2619
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002620 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002621 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 return 0;
2623
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002624 sk = chan->sk;
2625
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002626 /* don't delete l2cap channel if sk is owned by user */
2627 if (sock_owned_by_user(sk)) {
2628 sk->sk_state = BT_DISCONN;
2629 l2cap_sock_clear_timer(sk);
2630 l2cap_sock_set_timer(sk, HZ / 5);
2631 bh_unlock_sock(sk);
2632 return 0;
2633 }
2634
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002635 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 bh_unlock_sock(sk);
2637
2638 l2cap_sock_kill(sk);
2639 return 0;
2640}
2641
2642static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2643{
2644 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645 u16 type;
2646
2647 type = __le16_to_cpu(req->type);
2648
2649 BT_DBG("type 0x%4.4x", type);
2650
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002651 if (type == L2CAP_IT_FEAT_MASK) {
2652 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002653 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002654 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2655 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2656 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002657 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002658 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2659 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002660 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002661 l2cap_send_cmd(conn, cmd->ident,
2662 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002663 } else if (type == L2CAP_IT_FIXED_CHAN) {
2664 u8 buf[12];
2665 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2666 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2667 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2668 memcpy(buf + 4, l2cap_fixed_chan, 8);
2669 l2cap_send_cmd(conn, cmd->ident,
2670 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002671 } else {
2672 struct l2cap_info_rsp rsp;
2673 rsp.type = cpu_to_le16(type);
2674 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2675 l2cap_send_cmd(conn, cmd->ident,
2676 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2677 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678
2679 return 0;
2680}
2681
2682static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2683{
2684 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2685 u16 type, result;
2686
2687 type = __le16_to_cpu(rsp->type);
2688 result = __le16_to_cpu(rsp->result);
2689
2690 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2691
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002692 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2693 if (cmd->ident != conn->info_ident ||
2694 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2695 return 0;
2696
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002697 del_timer(&conn->info_timer);
2698
Ville Tervoadb08ed2010-08-04 09:43:33 +03002699 if (result != L2CAP_IR_SUCCESS) {
2700 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2701 conn->info_ident = 0;
2702
2703 l2cap_conn_start(conn);
2704
2705 return 0;
2706 }
2707
Marcel Holtmann984947d2009-02-06 23:35:19 +01002708 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002709 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002710
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002711 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002712 struct l2cap_info_req req;
2713 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2714
2715 conn->info_ident = l2cap_get_ident(conn);
2716
2717 l2cap_send_cmd(conn, conn->info_ident,
2718 L2CAP_INFO_REQ, sizeof(req), &req);
2719 } else {
2720 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2721 conn->info_ident = 0;
2722
2723 l2cap_conn_start(conn);
2724 }
2725 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002726 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002727 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002728
2729 l2cap_conn_start(conn);
2730 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002731
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732 return 0;
2733}
2734
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002735static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002736 u16 to_multiplier)
2737{
2738 u16 max_latency;
2739
2740 if (min > max || min < 6 || max > 3200)
2741 return -EINVAL;
2742
2743 if (to_multiplier < 10 || to_multiplier > 3200)
2744 return -EINVAL;
2745
2746 if (max >= to_multiplier * 8)
2747 return -EINVAL;
2748
2749 max_latency = (to_multiplier * 8 / max) - 1;
2750 if (latency > 499 || latency > max_latency)
2751 return -EINVAL;
2752
2753 return 0;
2754}
2755
2756static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2757 struct l2cap_cmd_hdr *cmd, u8 *data)
2758{
2759 struct hci_conn *hcon = conn->hcon;
2760 struct l2cap_conn_param_update_req *req;
2761 struct l2cap_conn_param_update_rsp rsp;
2762 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002763 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002764
2765 if (!(hcon->link_mode & HCI_LM_MASTER))
2766 return -EINVAL;
2767
2768 cmd_len = __le16_to_cpu(cmd->len);
2769 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2770 return -EPROTO;
2771
2772 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002773 min = __le16_to_cpu(req->min);
2774 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002775 latency = __le16_to_cpu(req->latency);
2776 to_multiplier = __le16_to_cpu(req->to_multiplier);
2777
2778 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2779 min, max, latency, to_multiplier);
2780
2781 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002782
2783 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2784 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002785 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2786 else
2787 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2788
2789 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2790 sizeof(rsp), &rsp);
2791
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002792 if (!err)
2793 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2794
Claudio Takahaside731152011-02-11 19:28:55 -02002795 return 0;
2796}
2797
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002798static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2799 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2800{
2801 int err = 0;
2802
2803 switch (cmd->code) {
2804 case L2CAP_COMMAND_REJ:
2805 l2cap_command_rej(conn, cmd, data);
2806 break;
2807
2808 case L2CAP_CONN_REQ:
2809 err = l2cap_connect_req(conn, cmd, data);
2810 break;
2811
2812 case L2CAP_CONN_RSP:
2813 err = l2cap_connect_rsp(conn, cmd, data);
2814 break;
2815
2816 case L2CAP_CONF_REQ:
2817 err = l2cap_config_req(conn, cmd, cmd_len, data);
2818 break;
2819
2820 case L2CAP_CONF_RSP:
2821 err = l2cap_config_rsp(conn, cmd, data);
2822 break;
2823
2824 case L2CAP_DISCONN_REQ:
2825 err = l2cap_disconnect_req(conn, cmd, data);
2826 break;
2827
2828 case L2CAP_DISCONN_RSP:
2829 err = l2cap_disconnect_rsp(conn, cmd, data);
2830 break;
2831
2832 case L2CAP_ECHO_REQ:
2833 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2834 break;
2835
2836 case L2CAP_ECHO_RSP:
2837 break;
2838
2839 case L2CAP_INFO_REQ:
2840 err = l2cap_information_req(conn, cmd, data);
2841 break;
2842
2843 case L2CAP_INFO_RSP:
2844 err = l2cap_information_rsp(conn, cmd, data);
2845 break;
2846
2847 default:
2848 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2849 err = -EINVAL;
2850 break;
2851 }
2852
2853 return err;
2854}
2855
2856static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2857 struct l2cap_cmd_hdr *cmd, u8 *data)
2858{
2859 switch (cmd->code) {
2860 case L2CAP_COMMAND_REJ:
2861 return 0;
2862
2863 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002864 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002865
2866 case L2CAP_CONN_PARAM_UPDATE_RSP:
2867 return 0;
2868
2869 default:
2870 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2871 return -EINVAL;
2872 }
2873}
2874
2875static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2876 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002877{
2878 u8 *data = skb->data;
2879 int len = skb->len;
2880 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002881 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002882
2883 l2cap_raw_recv(conn, skb);
2884
2885 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002886 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2888 data += L2CAP_CMD_HDR_SIZE;
2889 len -= L2CAP_CMD_HDR_SIZE;
2890
Al Viro88219a02007-07-29 00:17:25 -07002891 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892
Al Viro88219a02007-07-29 00:17:25 -07002893 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 -07002894
Al Viro88219a02007-07-29 00:17:25 -07002895 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896 BT_DBG("corrupted command");
2897 break;
2898 }
2899
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002900 if (conn->hcon->type == LE_LINK)
2901 err = l2cap_le_sig_cmd(conn, &cmd, data);
2902 else
2903 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002904
2905 if (err) {
2906 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002907
2908 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002909
2910 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002911 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2913 }
2914
Al Viro88219a02007-07-29 00:17:25 -07002915 data += cmd_len;
2916 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917 }
2918
2919 kfree_skb(skb);
2920}
2921
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002922static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002923{
2924 u16 our_fcs, rcv_fcs;
2925 int hdr_size = L2CAP_HDR_SIZE + 2;
2926
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002927 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002928 skb_trim(skb, skb->len - 2);
2929 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2930 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2931
2932 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002933 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002934 }
2935 return 0;
2936}
2937
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002938static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002939{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002940 u16 control = 0;
2941
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002942 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002943
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002944 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002945
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002946 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002947 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002948 l2cap_send_sframe(chan, control);
2949 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002950 }
2951
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002952 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2953 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002954
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002955 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002956
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002957 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002958 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002959 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002960 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002961 }
2962}
2963
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002964static 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 -03002965{
2966 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002967 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002968
2969 bt_cb(skb)->tx_seq = tx_seq;
2970 bt_cb(skb)->sar = sar;
2971
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002972 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002973 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002974 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002975 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002976 }
2977
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002978 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002979 if (tx_seq_offset < 0)
2980 tx_seq_offset += 64;
2981
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002982 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002983 if (bt_cb(next_skb)->tx_seq == tx_seq)
2984 return -EINVAL;
2985
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002986 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002987 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002988 if (next_tx_seq_offset < 0)
2989 next_tx_seq_offset += 64;
2990
2991 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002992 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002993 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002994 }
2995
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002996 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002997 break;
2998
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002999 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003000
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003001 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003002
3003 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003004}
3005
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003006static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003007{
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003008 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003009 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003010
3011 switch (control & L2CAP_CTRL_SAR) {
3012 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003013 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003014 goto drop;
3015
Ruiyi Zhang224f8af2011-05-13 13:07:52 +08003016 return sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003017
3018 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003019 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003020 goto drop;
3021
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003022 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003023
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003024 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003025 goto disconnect;
3026
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003027 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3028 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003029 return -ENOMEM;
3030
3031 /* pull sdu_len bytes only after alloc, because of Local Busy
3032 * condition we have to be sure that this will be executed
3033 * only once, i.e., when alloc does not fail */
3034 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003035
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003036 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003037
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003038 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003039 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003040 break;
3041
3042 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003043 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003044 goto disconnect;
3045
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003046 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003047 goto disconnect;
3048
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003049 chan->partial_sdu_len += skb->len;
3050 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003051 goto drop;
3052
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003053 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003054
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003055 break;
3056
3057 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003058 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003059 goto disconnect;
3060
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003061 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003062 goto disconnect;
3063
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003064 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003065 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003066
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003067 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003068 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003069
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003070 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003071 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003072
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003073 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003074 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003075
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003076 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003077 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003078 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003079 return -ENOMEM;
3080 }
3081
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003082 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003083 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003084 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003085 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003086 return err;
3087 }
3088
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003089 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
3090 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003091
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003092 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003093 break;
3094 }
3095
3096 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003097 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003098
3099drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003100 kfree_skb(chan->sdu);
3101 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003102
3103disconnect:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003104 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003105 kfree_skb(skb);
3106 return 0;
3107}
3108
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003109static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003110{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003111 struct sk_buff *skb;
3112 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003113 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003114
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003115 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003116 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003117 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003118 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003119 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003120 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003121 }
3122
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003123 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003124 }
3125
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003126 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003127 goto done;
3128
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003129 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003130 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003131 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003132 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003133
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003134 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003135 __mod_monitor_timer();
3136
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003137 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003138
3139done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003140 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3141 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003142
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003143 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003144
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003145 return 0;
3146}
3147
3148static void l2cap_busy_work(struct work_struct *work)
3149{
3150 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003151 struct l2cap_chan *chan =
3152 container_of(work, struct l2cap_chan, busy_work);
3153 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003154 int n_tries = 0, timeo = HZ/5, err;
3155 struct sk_buff *skb;
3156
3157 lock_sock(sk);
3158
3159 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003160 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003161 set_current_state(TASK_INTERRUPTIBLE);
3162
3163 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3164 err = -EBUSY;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003165 l2cap_send_disconn_req(chan->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003166 break;
3167 }
3168
3169 if (!timeo)
3170 timeo = HZ/5;
3171
3172 if (signal_pending(current)) {
3173 err = sock_intr_errno(timeo);
3174 break;
3175 }
3176
3177 release_sock(sk);
3178 timeo = schedule_timeout(timeo);
3179 lock_sock(sk);
3180
3181 err = sock_error(sk);
3182 if (err)
3183 break;
3184
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003185 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003186 break;
3187 }
3188
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003189 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003190 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003191
3192 release_sock(sk);
3193}
3194
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003195static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003196{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003197 int sctrl, err;
3198
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003199 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003200 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003201 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003202 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003203
3204
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003205 }
3206
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003207 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003208 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003209 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003210 return err;
3211 }
3212
3213 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003214 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003215
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003216 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003217 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003218 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003219
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003220 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003221 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003222 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003223
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003224 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003225
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003226 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003227
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003228 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003229
3230 return err;
3231}
3232
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003233static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003234{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003235 struct sk_buff *_skb;
3236 int err = -EINVAL;
3237
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003238 /*
3239 * TODO: We have to notify the userland if some data is lost with the
3240 * Streaming Mode.
3241 */
3242
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003243 switch (control & L2CAP_CTRL_SAR) {
3244 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003245 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003246 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003247 break;
3248 }
3249
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003250 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003251 if (!err)
3252 return 0;
3253
3254 break;
3255
3256 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003257 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003258 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003259 break;
3260 }
3261
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003262 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003263 skb_pull(skb, 2);
3264
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003265 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003266 err = -EMSGSIZE;
3267 break;
3268 }
3269
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003270 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3271 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003272 err = -ENOMEM;
3273 break;
3274 }
3275
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003276 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003277
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003278 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003279 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003280 err = 0;
3281 break;
3282
3283 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003284 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003285 break;
3286
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003287 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003288
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003289 chan->partial_sdu_len += skb->len;
3290 if (chan->partial_sdu_len > chan->sdu_len)
3291 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003292 else
3293 err = 0;
3294
3295 break;
3296
3297 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003298 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003299 break;
3300
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003301 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003302
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003303 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003304 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003305
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003306 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003307 goto drop;
3308
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003309 if (chan->partial_sdu_len == chan->sdu_len) {
3310 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003311 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003312 if (err < 0)
3313 kfree_skb(_skb);
3314 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003315 err = 0;
3316
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003317drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003318 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003319 break;
3320 }
3321
3322 kfree_skb(skb);
3323 return err;
3324}
3325
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003326static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003327{
3328 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003329 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003330
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003331 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003332 if (bt_cb(skb)->tx_seq != tx_seq)
3333 break;
3334
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003335 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003336 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003337 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003338 chan->buffer_seq_srej =
3339 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003340 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003341 }
3342}
3343
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003344static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003345{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003346 struct srej_list *l, *tmp;
3347 u16 control;
3348
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003349 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003350 if (l->tx_seq == tx_seq) {
3351 list_del(&l->list);
3352 kfree(l);
3353 return;
3354 }
3355 control = L2CAP_SUPER_SELECT_REJECT;
3356 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003357 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003358 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003359 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003360 }
3361}
3362
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003363static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003364{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003365 struct srej_list *new;
3366 u16 control;
3367
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003368 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003369 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003370 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003371 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003372
3373 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003374 new->tx_seq = chan->expected_tx_seq;
3375 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003376 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003377 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003378 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003379}
3380
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003381static 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 -03003382{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003383 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003384 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003385 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003386 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003387 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003388 int err = 0;
3389
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003390 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3391 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003392
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003393 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003394 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003395 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003396 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003397 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003398 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003399 }
3400
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003401 chan->expected_ack_seq = req_seq;
3402 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003403
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003404 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003405 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003406
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003407 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003408 if (tx_seq_offset < 0)
3409 tx_seq_offset += 64;
3410
3411 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003412 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003413 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003414 goto drop;
3415 }
3416
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003417 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003418 goto drop;
3419
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003420 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003421 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003422
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003423 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003424 struct srej_list, list);
3425 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003426 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003427 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003428
3429 list_del(&first->list);
3430 kfree(first);
3431
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003432 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003433 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003434 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3435 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003436 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003437 }
3438 } else {
3439 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003440
3441 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003442 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003443 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003444
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003445 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003446 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003447 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003448 return 0;
3449 }
3450 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003451 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003452 }
3453 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003454 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003455 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003456 if (expected_tx_seq_offset < 0)
3457 expected_tx_seq_offset += 64;
3458
3459 /* duplicated tx_seq */
3460 if (tx_seq_offset < expected_tx_seq_offset)
3461 goto drop;
3462
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003463 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003464
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003465 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003466
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003467 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003468 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003469
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003470 __skb_queue_head_init(&chan->srej_q);
3471 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003472 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003473
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003474 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003475
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003476 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003477
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003478 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003479 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003480 return 0;
3481
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003482expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003483 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003484
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003485 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003486 bt_cb(skb)->tx_seq = tx_seq;
3487 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003488 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003489 return 0;
3490 }
3491
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003492 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003493 if (err < 0)
3494 return 0;
3495
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003496 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003497 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3498 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003499 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003500 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003501 }
3502
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003503 __mod_ack_timer();
3504
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003505 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3506 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003507 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003508
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003509 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003510
3511drop:
3512 kfree_skb(skb);
3513 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003514}
3515
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003516static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003517{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003518 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003519 rx_control);
3520
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003521 chan->expected_ack_seq = __get_reqseq(rx_control);
3522 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003523
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003524 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003525 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3526 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3527 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003528 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003529 __mod_retrans_timer();
3530
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003531 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3532 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003533 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003534 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003535 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003536
3537 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003538 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003539
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003540 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3541 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003542 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003543 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003544
3545 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003546 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003547 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003548 __mod_retrans_timer();
3549
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003550 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3551 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3552 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003553 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003554 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003555 }
3556}
3557
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003558static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003559{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003560 u8 tx_seq = __get_reqseq(rx_control);
3561
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003562 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003563
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003564 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003565
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003566 chan->expected_ack_seq = tx_seq;
3567 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003568
3569 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003570 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3571 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003572 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003573 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003574 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003575 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003576
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003577 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3578 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003579 }
3580}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003581static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003582{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003583 u8 tx_seq = __get_reqseq(rx_control);
3584
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003585 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003586
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003587 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003588
3589 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003590 chan->expected_ack_seq = tx_seq;
3591 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003592
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003593 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3594 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003595
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003596 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003597
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003598 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003599 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003600 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003601 }
3602 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003603 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003604 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003605 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003606 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003607 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003608 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003609 l2cap_retransmit_one_frame(chan, tx_seq);
3610 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003611 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003612 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003613 }
3614 }
3615}
3616
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003617static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003618{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003619 u8 tx_seq = __get_reqseq(rx_control);
3620
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003621 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003622
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003623 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003624 chan->expected_ack_seq = tx_seq;
3625 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003626
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003627 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003628 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003629
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003630 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003631 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003632 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003633 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003634 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003635 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003636
3637 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003638 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003639 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003640 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003641}
3642
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003643static 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 -03003644{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003645 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003646
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003647 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003648 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003649 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003650 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003651 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003652 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003653 }
3654
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003655 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3656 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003657 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003658 break;
3659
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003660 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003661 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003662 break;
3663
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003664 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003665 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003666 break;
3667
3668 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003669 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003670 break;
3671 }
3672
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003673 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003674 return 0;
3675}
3676
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003677static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3678{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003679 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003680 u16 control;
3681 u8 req_seq;
3682 int len, next_tx_seq_offset, req_seq_offset;
3683
3684 control = get_unaligned_le16(skb->data);
3685 skb_pull(skb, 2);
3686 len = skb->len;
3687
3688 /*
3689 * We can just drop the corrupted I-frame here.
3690 * Receiver will miss it and start proper recovery
3691 * procedures and ask retransmission.
3692 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003693 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003694 goto drop;
3695
3696 if (__is_sar_start(control) && __is_iframe(control))
3697 len -= 2;
3698
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003699 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003700 len -= 2;
3701
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003702 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003703 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003704 goto drop;
3705 }
3706
3707 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003708 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003709 if (req_seq_offset < 0)
3710 req_seq_offset += 64;
3711
3712 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003713 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003714 if (next_tx_seq_offset < 0)
3715 next_tx_seq_offset += 64;
3716
3717 /* check for invalid req-seq */
3718 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003719 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003720 goto drop;
3721 }
3722
3723 if (__is_iframe(control)) {
3724 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003725 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003726 goto drop;
3727 }
3728
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003729 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003730 } else {
3731 if (len != 0) {
3732 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003733 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003734 goto drop;
3735 }
3736
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003737 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003738 }
3739
3740 return 0;
3741
3742drop:
3743 kfree_skb(skb);
3744 return 0;
3745}
3746
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3748{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003749 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003750 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003751 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003752 u8 tx_seq;
3753 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003754
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003755 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003756 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003757 BT_DBG("unknown cid 0x%4.4x", cid);
3758 goto drop;
3759 }
3760
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003761 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003762
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003763 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764
3765 if (sk->sk_state != BT_CONNECTED)
3766 goto drop;
3767
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003768 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003769 case L2CAP_MODE_BASIC:
3770 /* If socket recv buffers overflows we drop data here
3771 * which is *bad* because L2CAP has to be reliable.
3772 * But we don't have any other choice. L2CAP doesn't
3773 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003774
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003775 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003776 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003778 if (!sock_queue_rcv_skb(sk, skb))
3779 goto done;
3780 break;
3781
3782 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003783 if (!sock_owned_by_user(sk)) {
3784 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003785 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003786 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003787 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003788 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003789
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003790 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003791
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003792 case L2CAP_MODE_STREAMING:
3793 control = get_unaligned_le16(skb->data);
3794 skb_pull(skb, 2);
3795 len = skb->len;
3796
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003797 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003798 goto drop;
3799
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003800 if (__is_sar_start(control))
3801 len -= 2;
3802
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003803 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003804 len -= 2;
3805
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003806 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003807 goto drop;
3808
3809 tx_seq = __get_txseq(control);
3810
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003811 if (chan->expected_tx_seq == tx_seq)
3812 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003813 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003814 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003815
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003816 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003817
3818 goto done;
3819
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003820 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003821 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003822 break;
3823 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824
3825drop:
3826 kfree_skb(skb);
3827
3828done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003829 if (sk)
3830 bh_unlock_sock(sk);
3831
Linus Torvalds1da177e2005-04-16 15:20:36 -07003832 return 0;
3833}
3834
Al Viro8e036fc2007-07-29 00:16:36 -07003835static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003837 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003838 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003840 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3841 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842 goto drop;
3843
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003844 sk = chan->sk;
3845
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003846 bh_lock_sock(sk);
3847
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848 BT_DBG("sk %p, len %d", sk, skb->len);
3849
3850 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3851 goto drop;
3852
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003853 if (l2cap_pi(sk)->chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854 goto drop;
3855
3856 if (!sock_queue_rcv_skb(sk, skb))
3857 goto done;
3858
3859drop:
3860 kfree_skb(skb);
3861
3862done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003863 if (sk)
3864 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865 return 0;
3866}
3867
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003868static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3869{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003870 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003871 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003872
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003873 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3874 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003875 goto drop;
3876
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003877 sk = chan->sk;
3878
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003879 bh_lock_sock(sk);
3880
3881 BT_DBG("sk %p, len %d", sk, skb->len);
3882
3883 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3884 goto drop;
3885
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003886 if (l2cap_pi(sk)->chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003887 goto drop;
3888
3889 if (!sock_queue_rcv_skb(sk, skb))
3890 goto done;
3891
3892drop:
3893 kfree_skb(skb);
3894
3895done:
3896 if (sk)
3897 bh_unlock_sock(sk);
3898 return 0;
3899}
3900
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3902{
3903 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003904 u16 cid, len;
3905 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003906
3907 skb_pull(skb, L2CAP_HDR_SIZE);
3908 cid = __le16_to_cpu(lh->cid);
3909 len = __le16_to_cpu(lh->len);
3910
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003911 if (len != skb->len) {
3912 kfree_skb(skb);
3913 return;
3914 }
3915
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3917
3918 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003919 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003920 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921 l2cap_sig_channel(conn, skb);
3922 break;
3923
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003924 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003925 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926 skb_pull(skb, 2);
3927 l2cap_conless_channel(conn, psm, skb);
3928 break;
3929
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003930 case L2CAP_CID_LE_DATA:
3931 l2cap_att_channel(conn, cid, skb);
3932 break;
3933
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934 default:
3935 l2cap_data_channel(conn, cid, skb);
3936 break;
3937 }
3938}
3939
3940/* ---- L2CAP interface with lower layer (HCI) ---- */
3941
3942static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3943{
3944 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003945 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946
3947 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003948 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949
3950 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3951
3952 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003953 read_lock(&chan_list_lock);
3954 list_for_each_entry(c, &chan_list, global_l) {
3955 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003956
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957 if (sk->sk_state != BT_LISTEN)
3958 continue;
3959
3960 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003961 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003962 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003963 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003965 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3966 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003967 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003968 lm2 |= HCI_LM_MASTER;
3969 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003971 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972
3973 return exact ? lm1 : lm2;
3974}
3975
3976static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3977{
Marcel Holtmann01394182006-07-03 10:02:46 +02003978 struct l2cap_conn *conn;
3979
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3981
Ville Tervoacd7d372011-02-10 22:38:49 -03003982 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003983 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984
3985 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986 conn = l2cap_conn_add(hcon, status);
3987 if (conn)
3988 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003989 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990 l2cap_conn_del(hcon, bt_err(status));
3991
3992 return 0;
3993}
3994
Marcel Holtmann2950f212009-02-12 14:02:50 +01003995static int l2cap_disconn_ind(struct hci_conn *hcon)
3996{
3997 struct l2cap_conn *conn = hcon->l2cap_data;
3998
3999 BT_DBG("hcon %p", hcon);
4000
4001 if (hcon->type != ACL_LINK || !conn)
4002 return 0x13;
4003
4004 return conn->disc_reason;
4005}
4006
4007static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008{
4009 BT_DBG("hcon %p reason %d", hcon, reason);
4010
Ville Tervoacd7d372011-02-10 22:38:49 -03004011 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004012 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013
4014 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004015
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016 return 0;
4017}
4018
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004019static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004020{
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004021 struct sock *sk = chan->sk;
4022
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03004023 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004024 return;
4025
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004026 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004027 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004028 l2cap_sock_clear_timer(sk);
4029 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004030 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -03004031 __l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004032 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004033 if (chan->sec_level == BT_SECURITY_MEDIUM)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004034 l2cap_sock_clear_timer(sk);
4035 }
4036}
4037
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004038static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004040 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004041 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042
Marcel Holtmann01394182006-07-03 10:02:46 +02004043 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004045
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046 BT_DBG("conn %p", conn);
4047
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004048 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004050 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004051 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004052
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053 bh_lock_sock(sk);
4054
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03004055 if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004056 bh_unlock_sock(sk);
4057 continue;
4058 }
4059
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004060 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004061 sk->sk_state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004062 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004063 bh_unlock_sock(sk);
4064 continue;
4065 }
4066
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004067 if (sk->sk_state == BT_CONNECT) {
4068 if (!status) {
4069 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004070 req.scid = cpu_to_le16(chan->scid);
4071 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004072
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004073 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03004074 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004075
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004076 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004077 L2CAP_CONN_REQ, sizeof(req), &req);
4078 } else {
4079 l2cap_sock_clear_timer(sk);
4080 l2cap_sock_set_timer(sk, HZ / 10);
4081 }
4082 } else if (sk->sk_state == BT_CONNECT2) {
4083 struct l2cap_conn_rsp rsp;
4084 __u16 result;
4085
4086 if (!status) {
4087 sk->sk_state = BT_CONFIG;
4088 result = L2CAP_CR_SUCCESS;
4089 } else {
4090 sk->sk_state = BT_DISCONN;
4091 l2cap_sock_set_timer(sk, HZ / 10);
4092 result = L2CAP_CR_SEC_BLOCK;
4093 }
4094
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004095 rsp.scid = cpu_to_le16(chan->dcid);
4096 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004097 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02004098 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004099 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4100 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101 }
4102
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103 bh_unlock_sock(sk);
4104 }
4105
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004106 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004107
Linus Torvalds1da177e2005-04-16 15:20:36 -07004108 return 0;
4109}
4110
4111static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4112{
4113 struct l2cap_conn *conn = hcon->l2cap_data;
4114
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004115 if (!conn)
4116 conn = l2cap_conn_add(hcon, 0);
4117
4118 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119 goto drop;
4120
4121 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4122
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004123 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004125 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004126 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127 int len;
4128
4129 if (conn->rx_len) {
4130 BT_ERR("Unexpected start frame (len %d)", skb->len);
4131 kfree_skb(conn->rx_skb);
4132 conn->rx_skb = NULL;
4133 conn->rx_len = 0;
4134 l2cap_conn_unreliable(conn, ECOMM);
4135 }
4136
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004137 /* Start fragment always begin with Basic L2CAP header */
4138 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004139 BT_ERR("Frame is too short (len %d)", skb->len);
4140 l2cap_conn_unreliable(conn, ECOMM);
4141 goto drop;
4142 }
4143
4144 hdr = (struct l2cap_hdr *) skb->data;
4145 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004146 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147
4148 if (len == skb->len) {
4149 /* Complete frame received */
4150 l2cap_recv_frame(conn, skb);
4151 return 0;
4152 }
4153
4154 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4155
4156 if (skb->len > len) {
4157 BT_ERR("Frame is too long (len %d, expected len %d)",
4158 skb->len, len);
4159 l2cap_conn_unreliable(conn, ECOMM);
4160 goto drop;
4161 }
4162
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004163 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004164
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004165 if (chan && chan->sk) {
4166 struct sock *sk = chan->sk;
4167
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004168 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004169 BT_ERR("Frame exceeding recv MTU (len %d, "
4170 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004171 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004172 bh_unlock_sock(sk);
4173 l2cap_conn_unreliable(conn, ECOMM);
4174 goto drop;
4175 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004176 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004177 }
4178
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004180 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4181 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182 goto drop;
4183
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004184 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004185 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004186 conn->rx_len = len - skb->len;
4187 } else {
4188 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4189
4190 if (!conn->rx_len) {
4191 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4192 l2cap_conn_unreliable(conn, ECOMM);
4193 goto drop;
4194 }
4195
4196 if (skb->len > conn->rx_len) {
4197 BT_ERR("Fragment is too long (len %d, expected %d)",
4198 skb->len, conn->rx_len);
4199 kfree_skb(conn->rx_skb);
4200 conn->rx_skb = NULL;
4201 conn->rx_len = 0;
4202 l2cap_conn_unreliable(conn, ECOMM);
4203 goto drop;
4204 }
4205
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004206 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004207 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208 conn->rx_len -= skb->len;
4209
4210 if (!conn->rx_len) {
4211 /* Complete frame received */
4212 l2cap_recv_frame(conn, conn->rx_skb);
4213 conn->rx_skb = NULL;
4214 }
4215 }
4216
4217drop:
4218 kfree_skb(skb);
4219 return 0;
4220}
4221
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004222static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004223{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004224 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004226 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004228 list_for_each_entry(c, &chan_list, global_l) {
4229 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004231 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 +01004232 batostr(&bt_sk(sk)->src),
4233 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004234 sk->sk_state, __le16_to_cpu(c->psm),
4235 c->scid, c->dcid, c->imtu, c->omtu,
4236 c->sec_level, c->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004237 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004238
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004239 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004240
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004241 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242}
4243
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004244static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4245{
4246 return single_open(file, l2cap_debugfs_show, inode->i_private);
4247}
4248
4249static const struct file_operations l2cap_debugfs_fops = {
4250 .open = l2cap_debugfs_open,
4251 .read = seq_read,
4252 .llseek = seq_lseek,
4253 .release = single_release,
4254};
4255
4256static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257
Linus Torvalds1da177e2005-04-16 15:20:36 -07004258static struct hci_proto l2cap_hci_proto = {
4259 .name = "L2CAP",
4260 .id = HCI_PROTO_L2CAP,
4261 .connect_ind = l2cap_connect_ind,
4262 .connect_cfm = l2cap_connect_cfm,
4263 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004264 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004265 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266 .recv_acldata = l2cap_recv_acldata
4267};
4268
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004269int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004270{
4271 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004272
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004273 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274 if (err < 0)
4275 return err;
4276
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004277 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004278 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004279 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280 goto error;
4281 }
4282
4283 err = hci_register_proto(&l2cap_hci_proto);
4284 if (err < 0) {
4285 BT_ERR("L2CAP protocol registration failed");
4286 bt_sock_unregister(BTPROTO_L2CAP);
4287 goto error;
4288 }
4289
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004290 if (bt_debugfs) {
4291 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4292 bt_debugfs, NULL, &l2cap_debugfs_fops);
4293 if (!l2cap_debugfs)
4294 BT_ERR("Failed to create L2CAP debug file");
4295 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004296
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297 return 0;
4298
4299error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004300 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004301 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004302 return err;
4303}
4304
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004305void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004307 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004309 flush_workqueue(_busy_wq);
4310 destroy_workqueue(_busy_wq);
4311
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4313 BT_ERR("L2CAP protocol unregistration failed");
4314
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004315 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004316}
4317
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004318module_param(disable_ertm, bool, 0644);
4319MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");