blob: dff9d76fe790ebc18f7ade32a06ab138db54a36a [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
Johannes Bergb5ad8b72011-06-01 08:54:45 +020065static LIST_HEAD(chan_list);
66static DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
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. Padovanab078012011-05-02 18:25:01 -0300211static void l2cap_chan_set_timer(struct l2cap_chan *chan, long timeout)
212{
213 BT_DBG("chan %p state %d timeout %ld", chan->sk, chan->sk->sk_state,
214 timeout);
215 if (!mod_timer(&chan->chan_timer, jiffies + timeout))
216 sock_hold(chan->sk);
217}
218
Gustavo F. Padovan500698d2011-05-04 19:35:27 -0300219static void l2cap_chan_clear_timer(struct l2cap_chan *chan)
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300220{
221 BT_DBG("chan %p state %d", chan, chan->sk->sk_state);
222
223 if (timer_pending(&chan->chan_timer) && del_timer(&chan->chan_timer))
224 __sock_put(chan->sk);
225}
226
227static void l2cap_chan_timeout(unsigned long arg)
228{
229 struct l2cap_chan *chan = (struct l2cap_chan *) arg;
230 struct sock *sk = chan->sk;
231 int reason;
232
233 BT_DBG("chan %p state %d", chan, sk->sk_state);
234
235 bh_lock_sock(sk);
236
237 if (sock_owned_by_user(sk)) {
238 /* sk is owned by user. Try again later */
239 l2cap_chan_set_timer(chan, HZ / 5);
240 bh_unlock_sock(sk);
241 sock_put(sk);
242 return;
243 }
244
245 if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
246 reason = ECONNREFUSED;
247 else if (sk->sk_state == BT_CONNECT &&
248 chan->sec_level != BT_SECURITY_SDP)
249 reason = ECONNREFUSED;
250 else
251 reason = ETIMEDOUT;
252
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300253 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300254
255 bh_unlock_sock(sk);
256
257 l2cap_sock_kill(sk);
258 sock_put(sk);
259}
260
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300261struct l2cap_chan *l2cap_chan_create(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200262{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300263 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200264
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300265 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
266 if (!chan)
267 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200268
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300269 chan->sk = sk;
270
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300271 write_lock_bh(&chan_list_lock);
272 list_add(&chan->global_l, &chan_list);
273 write_unlock_bh(&chan_list_lock);
274
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300275 setup_timer(&chan->chan_timer, l2cap_chan_timeout, (unsigned long) chan);
276
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300277 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200278}
279
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300280void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300281{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300282 write_lock_bh(&chan_list_lock);
283 list_del(&chan->global_l);
284 write_unlock_bh(&chan_list_lock);
285
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300286 kfree(chan);
287}
288
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300289static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200290{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300291 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200292
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300293 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300294 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200295
Marcel Holtmann2950f212009-02-12 14:02:50 +0100296 conn->disc_reason = 0x13;
297
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300298 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200299
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300300 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
Ville Tervob62f3282011-02-10 22:38:50 -0300301 if (conn->hcon->type == LE_LINK) {
302 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300303 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300304 chan->scid = L2CAP_CID_LE_DATA;
305 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300306 } else {
307 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300308 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300309 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300310 }
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300311 } else if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200312 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300313 chan->scid = L2CAP_CID_CONN_LESS;
314 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300315 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200316 } else {
317 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300318 chan->scid = L2CAP_CID_SIGNALING;
319 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300320 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200321 }
322
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300323 sock_hold(sk);
324
325 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200326}
327
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900328/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200329 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300330static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200331{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300332 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300333 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200334 struct sock *parent = bt_sk(sk)->parent;
335
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300336 l2cap_chan_clear_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200337
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300338 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200339
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900340 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300341 /* Delete from channel list */
342 write_lock_bh(&conn->chan_lock);
343 list_del(&chan->list);
344 write_unlock_bh(&conn->chan_lock);
345 __sock_put(sk);
346
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300347 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200348 hci_conn_put(conn->hcon);
349 }
350
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200351 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200352 sock_set_flag(sk, SOCK_ZAPPED);
353
354 if (err)
355 sk->sk_err = err;
356
357 if (parent) {
358 bt_accept_unlink(sk);
359 parent->sk_data_ready(parent, 0);
360 } else
361 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300362
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300363 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE &&
364 chan->conf_state & L2CAP_CONF_INPUT_DONE))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300365 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300366
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300367 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300368
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300369 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300370 struct srej_list *l, *tmp;
371
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300372 del_timer(&chan->retrans_timer);
373 del_timer(&chan->monitor_timer);
374 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300375
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300376 skb_queue_purge(&chan->srej_q);
377 skb_queue_purge(&chan->busy_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300378
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300379 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300380 list_del(&l->list);
381 kfree(l);
382 }
383 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200384}
385
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300386static void l2cap_chan_cleanup_listen(struct sock *parent)
387{
388 struct sock *sk;
389
390 BT_DBG("parent %p", parent);
391
392 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300393 while ((sk = bt_accept_dequeue(parent, NULL))) {
394 l2cap_chan_clear_timer(l2cap_pi(sk)->chan);
395 lock_sock(sk);
396 l2cap_chan_close(l2cap_pi(sk)->chan, ECONNRESET);
397 release_sock(sk);
398 l2cap_sock_kill(sk);
399 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300400
401 parent->sk_state = BT_CLOSED;
402 sock_set_flag(parent, SOCK_ZAPPED);
403}
404
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300405void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300406{
407 struct l2cap_conn *conn = chan->conn;
408 struct sock *sk = chan->sk;
409
410 BT_DBG("chan %p state %d socket %p", chan, sk->sk_state, sk->sk_socket);
411
412 switch (sk->sk_state) {
413 case BT_LISTEN:
414 l2cap_chan_cleanup_listen(sk);
415 break;
416
417 case BT_CONNECTED:
418 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300419 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300420 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovan500698d2011-05-04 19:35:27 -0300421 l2cap_chan_clear_timer(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300422 l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300423 l2cap_send_disconn_req(conn, chan, reason);
424 } else
425 l2cap_chan_del(chan, reason);
426 break;
427
428 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300429 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300430 conn->hcon->type == ACL_LINK) {
431 struct l2cap_conn_rsp rsp;
432 __u16 result;
433
434 if (bt_sk(sk)->defer_setup)
435 result = L2CAP_CR_SEC_BLOCK;
436 else
437 result = L2CAP_CR_BAD_PSM;
Mat Martineaud8d69c52011-06-03 16:21:07 -0700438 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300439
440 rsp.scid = cpu_to_le16(chan->dcid);
441 rsp.dcid = cpu_to_le16(chan->scid);
442 rsp.result = cpu_to_le16(result);
443 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
444 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
445 sizeof(rsp), &rsp);
446 }
447
448 l2cap_chan_del(chan, reason);
449 break;
450
451 case BT_CONNECT:
452 case BT_DISCONN:
453 l2cap_chan_del(chan, reason);
454 break;
455
456 default:
457 sock_set_flag(sk, SOCK_ZAPPED);
458 break;
459 }
460}
461
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300462static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530463{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300464 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300465 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530466 case BT_SECURITY_HIGH:
467 return HCI_AT_DEDICATED_BONDING_MITM;
468 case BT_SECURITY_MEDIUM:
469 return HCI_AT_DEDICATED_BONDING;
470 default:
471 return HCI_AT_NO_BONDING;
472 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300473 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300474 if (chan->sec_level == BT_SECURITY_LOW)
475 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530476
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300477 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530478 return HCI_AT_NO_BONDING_MITM;
479 else
480 return HCI_AT_NO_BONDING;
481 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300482 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530483 case BT_SECURITY_HIGH:
484 return HCI_AT_GENERAL_BONDING_MITM;
485 case BT_SECURITY_MEDIUM:
486 return HCI_AT_GENERAL_BONDING;
487 default:
488 return HCI_AT_NO_BONDING;
489 }
490 }
491}
492
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200493/* Service level security */
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300494static inline int l2cap_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200495{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300496 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100497 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200498
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300499 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100500
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300501 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200502}
503
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200504static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200505{
506 u8 id;
507
508 /* Get next available identificator.
509 * 1 - 128 are used by kernel.
510 * 129 - 199 are reserved.
511 * 200 - 254 are used by utilities like l2ping, etc.
512 */
513
514 spin_lock_bh(&conn->lock);
515
516 if (++conn->tx_ident > 128)
517 conn->tx_ident = 1;
518
519 id = conn->tx_ident;
520
521 spin_unlock_bh(&conn->lock);
522
523 return id;
524}
525
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300526static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200527{
528 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200529 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200530
531 BT_DBG("code 0x%2.2x", code);
532
533 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300534 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200535
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200536 if (lmp_no_flush_capable(conn->hcon->hdev))
537 flags = ACL_START_NO_FLUSH;
538 else
539 flags = ACL_START;
540
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700541 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
542
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200543 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200544}
545
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300546static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300547{
548 struct sk_buff *skb;
549 struct l2cap_hdr *lh;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300550 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300551 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300552 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300553 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200554 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300555
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300556 if (sk->sk_state != BT_CONNECTED)
557 return;
558
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300559 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300560 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300561
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300562 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300563
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300564 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300565 control |= L2CAP_CTRL_FRAME_TYPE;
566
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300567 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300568 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300569 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300570 }
571
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300572 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300573 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300574 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300575 }
576
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300577 skb = bt_skb_alloc(count, GFP_ATOMIC);
578 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300579 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300580
581 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300582 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300583 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300584 put_unaligned_le16(control, skb_put(skb, 2));
585
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300586 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300587 u16 fcs = crc16(0, (u8 *)lh, count - 2);
588 put_unaligned_le16(fcs, skb_put(skb, 2));
589 }
590
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200591 if (lmp_no_flush_capable(conn->hcon->hdev))
592 flags = ACL_START_NO_FLUSH;
593 else
594 flags = ACL_START;
595
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700596 bt_cb(skb)->force_active = chan->force_active;
597
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300598 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300599}
600
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300601static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300602{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300603 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300604 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300605 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300606 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300607 control |= L2CAP_SUPER_RCV_READY;
608
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300609 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300610
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300611 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300612}
613
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300614static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300615{
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300616 return !(chan->conf_state & L2CAP_CONF_CONNECT_PEND);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300617}
618
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300619static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200620{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300621 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200622
623 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100624 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
625 return;
626
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300627 if (l2cap_check_security(chan) &&
628 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200629 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300630 req.scid = cpu_to_le16(chan->scid);
631 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200632
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300633 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300634 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200635
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300636 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
637 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200638 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200639 } else {
640 struct l2cap_info_req req;
641 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
642
643 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
644 conn->info_ident = l2cap_get_ident(conn);
645
646 mod_timer(&conn->info_timer, jiffies +
647 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
648
649 l2cap_send_cmd(conn, conn->info_ident,
650 L2CAP_INFO_REQ, sizeof(req), &req);
651 }
652}
653
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300654static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
655{
656 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300657 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300658 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
659
660 switch (mode) {
661 case L2CAP_MODE_ERTM:
662 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
663 case L2CAP_MODE_STREAMING:
664 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
665 default:
666 return 0x00;
667 }
668}
669
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300670static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300671{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300672 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300673 struct l2cap_disconn_req req;
674
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300675 if (!conn)
676 return;
677
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300678 sk = chan->sk;
679
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300680 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300681 del_timer(&chan->retrans_timer);
682 del_timer(&chan->monitor_timer);
683 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300684 }
685
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300686 req.dcid = cpu_to_le16(chan->dcid);
687 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300688 l2cap_send_cmd(conn, l2cap_get_ident(conn),
689 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300690
691 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300692 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300693}
694
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200696static void l2cap_conn_start(struct l2cap_conn *conn)
697{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300698 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200699
700 BT_DBG("conn %p", conn);
701
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300702 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200703
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300704 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300705 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300706
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200707 bh_lock_sock(sk);
708
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300709 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200710 bh_unlock_sock(sk);
711 continue;
712 }
713
714 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300715 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300716
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300717 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300718 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300719 bh_unlock_sock(sk);
720 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200721 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300722
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300723 if (!l2cap_mode_supported(chan->mode,
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300724 conn->feat_mask)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300725 && chan->conf_state &
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300726 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300727 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300728 * so release the lock */
729 read_unlock_bh(&conn->chan_lock);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300730 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300731 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300732 bh_unlock_sock(sk);
733 continue;
734 }
735
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300736 req.scid = cpu_to_le16(chan->scid);
737 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300738
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300739 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300740 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300741
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300742 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
743 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300744
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200745 } else if (sk->sk_state == BT_CONNECT2) {
746 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300747 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300748 rsp.scid = cpu_to_le16(chan->dcid);
749 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200750
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300751 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100752 if (bt_sk(sk)->defer_setup) {
753 struct sock *parent = bt_sk(sk)->parent;
754 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
755 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
756 parent->sk_data_ready(parent, 0);
757
758 } else {
759 sk->sk_state = BT_CONFIG;
760 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
761 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
762 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200763 } else {
764 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
765 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
766 }
767
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300768 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
769 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300770
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300771 if (chan->conf_state & L2CAP_CONF_REQ_SENT ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300772 rsp.result != L2CAP_CR_SUCCESS) {
773 bh_unlock_sock(sk);
774 continue;
775 }
776
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300777 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300778 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300779 l2cap_build_conf_req(chan, buf), buf);
780 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200781 }
782
783 bh_unlock_sock(sk);
784 }
785
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300786 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200787}
788
Ville Tervob62f3282011-02-10 22:38:50 -0300789/* Find socket with cid and source bdaddr.
790 * Returns closest match, locked.
791 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300792static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300793{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300794 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300795
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300796 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300797
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300798 list_for_each_entry(c, &chan_list, global_l) {
799 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300800
Ville Tervob62f3282011-02-10 22:38:50 -0300801 if (state && sk->sk_state != state)
802 continue;
803
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300804 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300805 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300806 if (!bacmp(&bt_sk(sk)->src, src)) {
807 read_unlock(&chan_list_lock);
808 return c;
809 }
Ville Tervob62f3282011-02-10 22:38:50 -0300810
811 /* Closest match */
812 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300813 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300814 }
815 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300816
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300817 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300818
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300819 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300820}
821
822static void l2cap_le_conn_ready(struct l2cap_conn *conn)
823{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300824 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300825 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300826
827 BT_DBG("");
828
829 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300830 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300831 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300832 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300833 return;
834
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300835 parent = pchan->sk;
836
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300837 bh_lock_sock(parent);
838
Ville Tervob62f3282011-02-10 22:38:50 -0300839 /* Check for backlog size */
840 if (sk_acceptq_is_full(parent)) {
841 BT_DBG("backlog full %d", parent->sk_ack_backlog);
842 goto clean;
843 }
844
845 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
846 if (!sk)
847 goto clean;
848
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300849 chan = l2cap_chan_create(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300850 if (!chan) {
851 l2cap_sock_kill(sk);
852 goto clean;
853 }
854
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300855 l2cap_pi(sk)->chan = chan;
856
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300857 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300858
859 hci_conn_hold(conn->hcon);
860
861 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300862
Ville Tervob62f3282011-02-10 22:38:50 -0300863 bacpy(&bt_sk(sk)->src, conn->src);
864 bacpy(&bt_sk(sk)->dst, conn->dst);
865
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300866 bt_accept_enqueue(parent, sk);
867
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300868 __l2cap_chan_add(conn, chan);
869
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300870 l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300871
872 sk->sk_state = BT_CONNECTED;
873 parent->sk_data_ready(parent, 0);
874
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300875 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300876
877clean:
878 bh_unlock_sock(parent);
879}
880
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200881static void l2cap_conn_ready(struct l2cap_conn *conn)
882{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300883 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200884
885 BT_DBG("conn %p", conn);
886
Ville Tervob62f3282011-02-10 22:38:50 -0300887 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
888 l2cap_le_conn_ready(conn);
889
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300890 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200891
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300892 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300893 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300894
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200895 bh_lock_sock(sk);
896
Ville Tervoacd7d372011-02-10 22:38:49 -0300897 if (conn->hcon->type == LE_LINK) {
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300898 l2cap_chan_clear_timer(chan);
Ville Tervoacd7d372011-02-10 22:38:49 -0300899 sk->sk_state = BT_CONNECTED;
900 sk->sk_state_change(sk);
901 }
902
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300903 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300904 l2cap_chan_clear_timer(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200905 sk->sk_state = BT_CONNECTED;
906 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200907 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300908 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200909
910 bh_unlock_sock(sk);
911 }
912
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300913 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200914}
915
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200916/* Notify sockets that we cannot guaranty reliability anymore */
917static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
918{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300919 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200920
921 BT_DBG("conn %p", conn);
922
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300923 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200924
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300925 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300926 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300927
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300928 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200929 sk->sk_err = err;
930 }
931
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300932 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200933}
934
935static void l2cap_info_timeout(unsigned long arg)
936{
937 struct l2cap_conn *conn = (void *) arg;
938
Marcel Holtmann984947d2009-02-06 23:35:19 +0100939 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100940 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100941
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200942 l2cap_conn_start(conn);
943}
944
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
946{
Marcel Holtmann01394182006-07-03 10:02:46 +0200947 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948
Marcel Holtmann01394182006-07-03 10:02:46 +0200949 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 return conn;
951
Marcel Holtmann01394182006-07-03 10:02:46 +0200952 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
953 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955
956 hcon->l2cap_data = conn;
957 conn->hcon = hcon;
958
Marcel Holtmann01394182006-07-03 10:02:46 +0200959 BT_DBG("hcon %p conn %p", hcon, conn);
960
Ville Tervoacd7d372011-02-10 22:38:49 -0300961 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
962 conn->mtu = hcon->hdev->le_mtu;
963 else
964 conn->mtu = hcon->hdev->acl_mtu;
965
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 conn->src = &hcon->hdev->bdaddr;
967 conn->dst = &hcon->dst;
968
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200969 conn->feat_mask = 0;
970
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300972 rwlock_init(&conn->chan_lock);
973
974 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975
Ville Tervob62f3282011-02-10 22:38:50 -0300976 if (hcon->type != LE_LINK)
977 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000978 (unsigned long) conn);
979
Marcel Holtmann2950f212009-02-12 14:02:50 +0100980 conn->disc_reason = 0x13;
981
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 return conn;
983}
984
Marcel Holtmann01394182006-07-03 10:02:46 +0200985static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986{
Marcel Holtmann01394182006-07-03 10:02:46 +0200987 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300988 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 struct sock *sk;
990
Marcel Holtmann01394182006-07-03 10:02:46 +0200991 if (!conn)
992 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993
994 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
995
Wei Yongjun7585b972009-02-25 18:29:52 +0800996 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997
998 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300999 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001000 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001002 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 bh_unlock_sock(sk);
1004 l2cap_sock_kill(sk);
1005 }
1006
Dave Young8e8440f2008-03-03 12:18:55 -08001007 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1008 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -08001009
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 hcon->l2cap_data = NULL;
1011 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012}
1013
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001014static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001016 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001017 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001018 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019}
1020
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022
1023/* Find socket with psm and source bdaddr.
1024 * Returns closest match.
1025 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001026static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001028 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001030 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001031
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001032 list_for_each_entry(c, &chan_list, global_l) {
1033 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001034
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 if (state && sk->sk_state != state)
1036 continue;
1037
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001038 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001040 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001041 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001042 return c;
1043 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044
1045 /* Closest match */
1046 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001047 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 }
1049 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001051 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001052
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001053 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054}
1055
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001056int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001058 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 bdaddr_t *src = &bt_sk(sk)->src;
1060 bdaddr_t *dst = &bt_sk(sk)->dst;
1061 struct l2cap_conn *conn;
1062 struct hci_conn *hcon;
1063 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001064 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001065 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001067 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001068 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001070 hdev = hci_get_route(dst, src);
1071 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 return -EHOSTUNREACH;
1073
1074 hci_dev_lock_bh(hdev);
1075
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001076 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001077
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001078 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001079 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001080 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001081 else
1082 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001083 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001084
Ville Tervo30e76272011-02-22 16:10:53 -03001085 if (IS_ERR(hcon)) {
1086 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001088 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
1090 conn = l2cap_conn_add(hcon, 0);
1091 if (!conn) {
1092 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001093 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 goto done;
1095 }
1096
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 /* Update source addr of the socket */
1098 bacpy(src, conn->src);
1099
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001100 l2cap_chan_add(conn, chan);
1101
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 sk->sk_state = BT_CONNECT;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03001103 l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104
1105 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001106 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanab078012011-05-02 18:25:01 -03001107 l2cap_chan_clear_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001108 if (l2cap_check_security(chan))
Johan Hedbergd00ef242011-01-19 12:06:51 +05301109 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001110 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001111 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 }
1113
Ville Tervo30e76272011-02-22 16:10:53 -03001114 err = 0;
1115
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116done:
1117 hci_dev_unlock_bh(hdev);
1118 hci_dev_put(hdev);
1119 return err;
1120}
1121
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001122int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001123{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001124 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001125 DECLARE_WAITQUEUE(wait, current);
1126 int err = 0;
1127 int timeo = HZ/5;
1128
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001129 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001130 while ((chan->unacked_frames > 0 && chan->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001131 set_current_state(TASK_INTERRUPTIBLE);
1132
1133 if (!timeo)
1134 timeo = HZ/5;
1135
1136 if (signal_pending(current)) {
1137 err = sock_intr_errno(timeo);
1138 break;
1139 }
1140
1141 release_sock(sk);
1142 timeo = schedule_timeout(timeo);
1143 lock_sock(sk);
1144
1145 err = sock_error(sk);
1146 if (err)
1147 break;
1148 }
1149 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001150 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001151 return err;
1152}
1153
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001154static void l2cap_monitor_timeout(unsigned long arg)
1155{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001156 struct l2cap_chan *chan = (void *) arg;
1157 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001158
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001159 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001160
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001161 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001162 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001163 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001164 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001165 return;
1166 }
1167
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001168 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001169 __mod_monitor_timer();
1170
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001171 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001172 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001173}
1174
1175static void l2cap_retrans_timeout(unsigned long arg)
1176{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001177 struct l2cap_chan *chan = (void *) arg;
1178 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001179
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001180 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001181
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001182 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001183 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001184 __mod_monitor_timer();
1185
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001186 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001187
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001188 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001189 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001190}
1191
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001192static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001193{
1194 struct sk_buff *skb;
1195
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001196 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001197 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001198 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001199 break;
1200
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001201 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001202 kfree_skb(skb);
1203
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001204 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001205 }
1206
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001207 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001208 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001209}
1210
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001211void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001212{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001213 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001214 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001215
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001216 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001217
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001218 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001219 flags = ACL_START_NO_FLUSH;
1220 else
1221 flags = ACL_START;
1222
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -07001223 bt_cb(skb)->force_active = chan->force_active;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001224 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001225}
1226
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001227void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001228{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001229 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001230 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001231
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001232 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001233 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001234 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001235 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001236
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001237 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001238 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1239 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001240 }
1241
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001242 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001243
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001244 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001245 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001246}
1247
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001248static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001249{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001250 struct sk_buff *skb, *tx_skb;
1251 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001252
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001253 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001254 if (!skb)
1255 return;
1256
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001257 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001258 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001259 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001260
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001261 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001262 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001263
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001264 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001265
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001266 if (chan->remote_max_tx &&
1267 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001268 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001269 return;
1270 }
1271
1272 tx_skb = skb_clone(skb, GFP_ATOMIC);
1273 bt_cb(skb)->retries++;
1274 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001275 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001276
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001277 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001278 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001279 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001280 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001281
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001282 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001283 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001284
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001285 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1286
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001287 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001288 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1289 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1290 }
1291
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001292 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001293}
1294
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001295int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001296{
1297 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001298 struct sock *sk = chan->sk;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001299 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001300 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001301
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001302 if (sk->sk_state != BT_CONNECTED)
1303 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001304
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001305 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001306
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001307 if (chan->remote_max_tx &&
1308 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001309 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001310 break;
1311 }
1312
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001313 tx_skb = skb_clone(skb, GFP_ATOMIC);
1314
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001315 bt_cb(skb)->retries++;
1316
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001317 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001318 control &= L2CAP_CTRL_SAR;
1319
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001320 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001321 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001322 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001323 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001324 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1325 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001326 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1327
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001328
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001329 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001330 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1331 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1332 }
1333
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001334 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001335
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001336 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001337
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001338 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1339 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001340
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301341 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001342 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301343
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001344 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001345
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001346 if (skb_queue_is_last(&chan->tx_q, skb))
1347 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001348 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001349 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001350
1351 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001352 }
1353
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001354 return nsent;
1355}
1356
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001357static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001358{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001359 int ret;
1360
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001361 if (!skb_queue_empty(&chan->tx_q))
1362 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001363
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001364 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001365 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001366 return ret;
1367}
1368
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001369static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001370{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001371 u16 control = 0;
1372
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001373 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001374
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001375 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001376 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001377 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1378 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001379 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001380 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001381
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001382 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001383 return;
1384
1385 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001386 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001387}
1388
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001389static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001390{
1391 struct srej_list *tail;
1392 u16 control;
1393
1394 control = L2CAP_SUPER_SELECT_REJECT;
1395 control |= L2CAP_CTRL_FINAL;
1396
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001397 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001398 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1399
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001400 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001401}
1402
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001403static 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 -07001404{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001405 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001406 struct sk_buff **frag;
1407 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001409 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001410 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411
1412 sent += count;
1413 len -= count;
1414
1415 /* Continuation fragments (no L2CAP header) */
1416 frag = &skb_shinfo(skb)->frag_list;
1417 while (len) {
1418 count = min_t(unsigned int, conn->mtu, len);
1419
1420 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1421 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001422 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001423 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1424 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425
1426 sent += count;
1427 len -= count;
1428
1429 frag = &(*frag)->next;
1430 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431
1432 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001433}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001435struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001436{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001437 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001438 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001439 struct sk_buff *skb;
1440 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1441 struct l2cap_hdr *lh;
1442
1443 BT_DBG("sk %p len %d", sk, (int)len);
1444
1445 count = min_t(unsigned int, (conn->mtu - hlen), len);
1446 skb = bt_skb_send_alloc(sk, count + hlen,
1447 msg->msg_flags & MSG_DONTWAIT, &err);
1448 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001449 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001450
1451 /* Create L2CAP header */
1452 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001453 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001454 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001455 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001456
1457 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1458 if (unlikely(err < 0)) {
1459 kfree_skb(skb);
1460 return ERR_PTR(err);
1461 }
1462 return skb;
1463}
1464
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001465struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001466{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001467 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001468 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001469 struct sk_buff *skb;
1470 int err, count, hlen = L2CAP_HDR_SIZE;
1471 struct l2cap_hdr *lh;
1472
1473 BT_DBG("sk %p len %d", sk, (int)len);
1474
1475 count = min_t(unsigned int, (conn->mtu - hlen), len);
1476 skb = bt_skb_send_alloc(sk, count + hlen,
1477 msg->msg_flags & MSG_DONTWAIT, &err);
1478 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001479 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001480
1481 /* Create L2CAP header */
1482 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001483 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001484 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1485
1486 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1487 if (unlikely(err < 0)) {
1488 kfree_skb(skb);
1489 return ERR_PTR(err);
1490 }
1491 return skb;
1492}
1493
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001494struct 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 -03001495{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001496 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001497 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001498 struct sk_buff *skb;
1499 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1500 struct l2cap_hdr *lh;
1501
1502 BT_DBG("sk %p len %d", sk, (int)len);
1503
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001504 if (!conn)
1505 return ERR_PTR(-ENOTCONN);
1506
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001507 if (sdulen)
1508 hlen += 2;
1509
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001510 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001511 hlen += 2;
1512
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001513 count = min_t(unsigned int, (conn->mtu - hlen), len);
1514 skb = bt_skb_send_alloc(sk, count + hlen,
1515 msg->msg_flags & MSG_DONTWAIT, &err);
1516 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001517 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001518
1519 /* Create L2CAP header */
1520 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001521 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001522 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1523 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001524 if (sdulen)
1525 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001526
1527 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1528 if (unlikely(err < 0)) {
1529 kfree_skb(skb);
1530 return ERR_PTR(err);
1531 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001532
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001533 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001534 put_unaligned_le16(0, skb_put(skb, 2));
1535
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001536 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001537 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538}
1539
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001540int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001541{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001542 struct sk_buff *skb;
1543 struct sk_buff_head sar_queue;
1544 u16 control;
1545 size_t size = 0;
1546
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001547 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001548 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001549 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001550 if (IS_ERR(skb))
1551 return PTR_ERR(skb);
1552
1553 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001554 len -= chan->remote_mps;
1555 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001556
1557 while (len > 0) {
1558 size_t buflen;
1559
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001560 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001561 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001562 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001563 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001564 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001565 buflen = len;
1566 }
1567
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001568 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001569 if (IS_ERR(skb)) {
1570 skb_queue_purge(&sar_queue);
1571 return PTR_ERR(skb);
1572 }
1573
1574 __skb_queue_tail(&sar_queue, skb);
1575 len -= buflen;
1576 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001577 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001578 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1579 if (chan->tx_send_head == NULL)
1580 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001581
1582 return size;
1583}
1584
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001585int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1586{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001587 struct sk_buff *skb;
1588 u16 control;
1589 int err;
1590
1591 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001592 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001593 skb = l2cap_create_connless_pdu(chan, msg, len);
1594 if (IS_ERR(skb))
1595 return PTR_ERR(skb);
1596
1597 l2cap_do_send(chan, skb);
1598 return len;
1599 }
1600
1601 switch (chan->mode) {
1602 case L2CAP_MODE_BASIC:
1603 /* Check outgoing MTU */
1604 if (len > chan->omtu)
1605 return -EMSGSIZE;
1606
1607 /* Create a basic PDU */
1608 skb = l2cap_create_basic_pdu(chan, msg, len);
1609 if (IS_ERR(skb))
1610 return PTR_ERR(skb);
1611
1612 l2cap_do_send(chan, skb);
1613 err = len;
1614 break;
1615
1616 case L2CAP_MODE_ERTM:
1617 case L2CAP_MODE_STREAMING:
1618 /* Entire SDU fits into one PDU */
1619 if (len <= chan->remote_mps) {
1620 control = L2CAP_SDU_UNSEGMENTED;
1621 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1622 0);
1623 if (IS_ERR(skb))
1624 return PTR_ERR(skb);
1625
1626 __skb_queue_tail(&chan->tx_q, skb);
1627
1628 if (chan->tx_send_head == NULL)
1629 chan->tx_send_head = skb;
1630
1631 } else {
1632 /* Segment SDU into multiples PDUs */
1633 err = l2cap_sar_segment_sdu(chan, msg, len);
1634 if (err < 0)
1635 return err;
1636 }
1637
1638 if (chan->mode == L2CAP_MODE_STREAMING) {
1639 l2cap_streaming_send(chan);
1640 err = len;
1641 break;
1642 }
1643
1644 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
1645 (chan->conn_state & L2CAP_CONN_WAIT_F)) {
1646 err = len;
1647 break;
1648 }
1649
1650 err = l2cap_ertm_send(chan);
1651 if (err >= 0)
1652 err = len;
1653
1654 break;
1655
1656 default:
1657 BT_DBG("bad state %1.1x", chan->mode);
1658 err = -EBADFD;
1659 }
1660
1661 return err;
1662}
1663
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664static void l2cap_chan_ready(struct sock *sk)
1665{
1666 struct sock *parent = bt_sk(sk)->parent;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001667 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668
1669 BT_DBG("sk %p, parent %p", sk, parent);
1670
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001671 chan->conf_state = 0;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03001672 l2cap_chan_clear_timer(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673
1674 if (!parent) {
1675 /* Outgoing channel.
1676 * Wake up socket sleeping on connect.
1677 */
1678 sk->sk_state = BT_CONNECTED;
1679 sk->sk_state_change(sk);
1680 } else {
1681 /* Incoming channel.
1682 * Wake up socket sleeping on accept.
1683 */
1684 parent->sk_data_ready(parent, 0);
1685 }
1686}
1687
1688/* Copy frame to all raw sockets on that connection */
1689static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1690{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001692 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693
1694 BT_DBG("conn %p", conn);
1695
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001696 read_lock(&conn->chan_lock);
1697 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001698 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001699 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 continue;
1701
1702 /* Don't send frame to the socket it came from */
1703 if (skb->sk == sk)
1704 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001705 nskb = skb_clone(skb, GFP_ATOMIC);
1706 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 continue;
1708
1709 if (sock_queue_rcv_skb(sk, nskb))
1710 kfree_skb(nskb);
1711 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001712 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713}
1714
1715/* ---- L2CAP signalling commands ---- */
1716static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1717 u8 code, u8 ident, u16 dlen, void *data)
1718{
1719 struct sk_buff *skb, **frag;
1720 struct l2cap_cmd_hdr *cmd;
1721 struct l2cap_hdr *lh;
1722 int len, count;
1723
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001724 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1725 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726
1727 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1728 count = min_t(unsigned int, conn->mtu, len);
1729
1730 skb = bt_skb_alloc(count, GFP_ATOMIC);
1731 if (!skb)
1732 return NULL;
1733
1734 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001735 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001736
1737 if (conn->hcon->type == LE_LINK)
1738 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1739 else
1740 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741
1742 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1743 cmd->code = code;
1744 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001745 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746
1747 if (dlen) {
1748 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1749 memcpy(skb_put(skb, count), data, count);
1750 data += count;
1751 }
1752
1753 len -= skb->len;
1754
1755 /* Continuation fragments (no L2CAP header) */
1756 frag = &skb_shinfo(skb)->frag_list;
1757 while (len) {
1758 count = min_t(unsigned int, conn->mtu, len);
1759
1760 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1761 if (!*frag)
1762 goto fail;
1763
1764 memcpy(skb_put(*frag, count), data, count);
1765
1766 len -= count;
1767 data += count;
1768
1769 frag = &(*frag)->next;
1770 }
1771
1772 return skb;
1773
1774fail:
1775 kfree_skb(skb);
1776 return NULL;
1777}
1778
1779static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1780{
1781 struct l2cap_conf_opt *opt = *ptr;
1782 int len;
1783
1784 len = L2CAP_CONF_OPT_SIZE + opt->len;
1785 *ptr += len;
1786
1787 *type = opt->type;
1788 *olen = opt->len;
1789
1790 switch (opt->len) {
1791 case 1:
1792 *val = *((u8 *) opt->val);
1793 break;
1794
1795 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001796 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 break;
1798
1799 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001800 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801 break;
1802
1803 default:
1804 *val = (unsigned long) opt->val;
1805 break;
1806 }
1807
1808 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1809 return len;
1810}
1811
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1813{
1814 struct l2cap_conf_opt *opt = *ptr;
1815
1816 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1817
1818 opt->type = type;
1819 opt->len = len;
1820
1821 switch (len) {
1822 case 1:
1823 *((u8 *) opt->val) = val;
1824 break;
1825
1826 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001827 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 break;
1829
1830 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001831 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 break;
1833
1834 default:
1835 memcpy(opt->val, (void *) val, len);
1836 break;
1837 }
1838
1839 *ptr += L2CAP_CONF_OPT_SIZE + len;
1840}
1841
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001842static void l2cap_ack_timeout(unsigned long arg)
1843{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001844 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001845
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001846 bh_lock_sock(chan->sk);
1847 l2cap_send_ack(chan);
1848 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001849}
1850
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001851static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001852{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001853 struct sock *sk = chan->sk;
1854
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001855 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001856 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001857 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001858 chan->num_acked = 0;
1859 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001860
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001861 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1862 (unsigned long) chan);
1863 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1864 (unsigned long) chan);
1865 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001866
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001867 skb_queue_head_init(&chan->srej_q);
1868 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001869
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001870 INIT_LIST_HEAD(&chan->srej_l);
1871
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001872 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001873
1874 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001875}
1876
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001877static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1878{
1879 switch (mode) {
1880 case L2CAP_MODE_STREAMING:
1881 case L2CAP_MODE_ERTM:
1882 if (l2cap_mode_supported(mode, remote_feat_mask))
1883 return mode;
1884 /* fall through */
1885 default:
1886 return L2CAP_MODE_BASIC;
1887 }
1888}
1889
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001890static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001893 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 void *ptr = req->data;
1895
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001896 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001898 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001899 goto done;
1900
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001901 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001902 case L2CAP_MODE_STREAMING:
1903 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001904 if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001905 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001906
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001907 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001908 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001909 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001910 break;
1911 }
1912
1913done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001914 if (chan->imtu != L2CAP_DEFAULT_MTU)
1915 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001916
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001917 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001918 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001919 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1920 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001921 break;
1922
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001923 rfc.mode = L2CAP_MODE_BASIC;
1924 rfc.txwin_size = 0;
1925 rfc.max_transmit = 0;
1926 rfc.retrans_timeout = 0;
1927 rfc.monitor_timeout = 0;
1928 rfc.max_pdu_size = 0;
1929
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001930 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1931 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001932 break;
1933
1934 case L2CAP_MODE_ERTM:
1935 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001936 rfc.txwin_size = chan->tx_win;
1937 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001938 rfc.retrans_timeout = 0;
1939 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001940 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001941 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1942 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001943
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001944 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1945 (unsigned long) &rfc);
1946
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001947 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001948 break;
1949
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001950 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001951 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001952 chan->fcs = L2CAP_FCS_NONE;
1953 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001954 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001955 break;
1956
1957 case L2CAP_MODE_STREAMING:
1958 rfc.mode = L2CAP_MODE_STREAMING;
1959 rfc.txwin_size = 0;
1960 rfc.max_transmit = 0;
1961 rfc.retrans_timeout = 0;
1962 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001963 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001964 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1965 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001966
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001967 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1968 (unsigned long) &rfc);
1969
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001970 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001971 break;
1972
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001973 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001974 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001975 chan->fcs = L2CAP_FCS_NONE;
1976 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001977 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001978 break;
1979 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001981 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001982 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983
1984 return ptr - data;
1985}
1986
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001987static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001989 struct l2cap_conf_rsp *rsp = data;
1990 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001991 void *req = chan->conf_req;
1992 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001993 int type, hint, olen;
1994 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001995 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001996 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001997 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001999 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01002000
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002001 while (len >= L2CAP_CONF_OPT_SIZE) {
2002 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002004 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002005 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002006
2007 switch (type) {
2008 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002009 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002010 break;
2011
2012 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002013 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002014 break;
2015
2016 case L2CAP_CONF_QOS:
2017 break;
2018
Marcel Holtmann6464f352007-10-20 13:39:51 +02002019 case L2CAP_CONF_RFC:
2020 if (olen == sizeof(rfc))
2021 memcpy(&rfc, (void *) val, olen);
2022 break;
2023
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002024 case L2CAP_CONF_FCS:
2025 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002026 chan->conf_state |= L2CAP_CONF_NO_FCS_RECV;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002027
2028 break;
2029
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002030 default:
2031 if (hint)
2032 break;
2033
2034 result = L2CAP_CONF_UNKNOWN;
2035 *((u8 *) ptr++) = type;
2036 break;
2037 }
2038 }
2039
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002040 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002041 goto done;
2042
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002043 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002044 case L2CAP_MODE_STREAMING:
2045 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002046 if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002047 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002048 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002049 break;
2050 }
2051
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002052 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002053 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002054
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002055 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002056 }
2057
2058done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002059 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002060 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002061 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002062
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002063 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002064 return -ECONNREFUSED;
2065
2066 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2067 sizeof(rfc), (unsigned long) &rfc);
2068 }
2069
2070
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002071 if (result == L2CAP_CONF_SUCCESS) {
2072 /* Configure output options and let the other side know
2073 * which ones we don't like. */
2074
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002075 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2076 result = L2CAP_CONF_UNACCEPT;
2077 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002078 chan->omtu = mtu;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002079 chan->conf_state |= L2CAP_CONF_MTU_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002080 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002081 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002082
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002083 switch (rfc.mode) {
2084 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002085 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002086 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002087 break;
2088
2089 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002090 chan->remote_tx_win = rfc.txwin_size;
2091 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002092
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002093 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2094 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002095
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002096 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002097
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002098 rfc.retrans_timeout =
2099 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2100 rfc.monitor_timeout =
2101 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002102
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002103 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002104
2105 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2106 sizeof(rfc), (unsigned long) &rfc);
2107
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002108 break;
2109
2110 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002111 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2112 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002113
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002114 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002115
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002116 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002117
2118 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2119 sizeof(rfc), (unsigned long) &rfc);
2120
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002121 break;
2122
2123 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002124 result = L2CAP_CONF_UNACCEPT;
2125
2126 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002127 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002128 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002129
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002130 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002131 chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002132 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002133 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002134 rsp->result = cpu_to_le16(result);
2135 rsp->flags = cpu_to_le16(0x0000);
2136
2137 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138}
2139
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002140static 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 -03002141{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002142 struct l2cap_conf_req *req = data;
2143 void *ptr = req->data;
2144 int type, olen;
2145 unsigned long val;
2146 struct l2cap_conf_rfc rfc;
2147
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002148 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002149
2150 while (len >= L2CAP_CONF_OPT_SIZE) {
2151 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2152
2153 switch (type) {
2154 case L2CAP_CONF_MTU:
2155 if (val < L2CAP_DEFAULT_MIN_MTU) {
2156 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002157 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002158 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002159 chan->imtu = val;
2160 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002161 break;
2162
2163 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002164 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002165 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002166 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002167 break;
2168
2169 case L2CAP_CONF_RFC:
2170 if (olen == sizeof(rfc))
2171 memcpy(&rfc, (void *)val, olen);
2172
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002173 if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002174 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002175 return -ECONNREFUSED;
2176
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002177 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002178
2179 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2180 sizeof(rfc), (unsigned long) &rfc);
2181 break;
2182 }
2183 }
2184
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002185 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002186 return -ECONNREFUSED;
2187
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002188 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002189
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002190 if (*result == L2CAP_CONF_SUCCESS) {
2191 switch (rfc.mode) {
2192 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002193 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2194 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2195 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002196 break;
2197 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002198 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002199 }
2200 }
2201
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002202 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002203 req->flags = cpu_to_le16(0x0000);
2204
2205 return ptr - data;
2206}
2207
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002208static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209{
2210 struct l2cap_conf_rsp *rsp = data;
2211 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002213 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002215 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002216 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002217 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218
2219 return ptr - data;
2220}
2221
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002222void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002223{
2224 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002225 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002226 u8 buf[128];
2227
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002228 rsp.scid = cpu_to_le16(chan->dcid);
2229 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002230 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2231 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2232 l2cap_send_cmd(conn, chan->ident,
2233 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2234
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002235 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002236 return;
2237
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002238 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002239 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2240 l2cap_build_conf_req(chan, buf), buf);
2241 chan->num_conf_req++;
2242}
2243
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002244static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002245{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002246 int type, olen;
2247 unsigned long val;
2248 struct l2cap_conf_rfc rfc;
2249
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002250 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002251
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002252 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002253 return;
2254
2255 while (len >= L2CAP_CONF_OPT_SIZE) {
2256 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2257
2258 switch (type) {
2259 case L2CAP_CONF_RFC:
2260 if (olen == sizeof(rfc))
2261 memcpy(&rfc, (void *)val, olen);
2262 goto done;
2263 }
2264 }
2265
2266done:
2267 switch (rfc.mode) {
2268 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002269 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2270 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2271 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002272 break;
2273 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002274 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002275 }
2276}
2277
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002278static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2279{
2280 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2281
2282 if (rej->reason != 0x0000)
2283 return 0;
2284
2285 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2286 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002287 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002288
2289 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002290 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002291
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002292 l2cap_conn_start(conn);
2293 }
2294
2295 return 0;
2296}
2297
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2299{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2301 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002302 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002303 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002304 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305
2306 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002307 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308
2309 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2310
2311 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002312 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2313 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 result = L2CAP_CR_BAD_PSM;
2315 goto sendresp;
2316 }
2317
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002318 parent = pchan->sk;
2319
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002320 bh_lock_sock(parent);
2321
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002322 /* Check if the ACL is secure enough (if not SDP) */
2323 if (psm != cpu_to_le16(0x0001) &&
2324 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002325 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002326 result = L2CAP_CR_SEC_BLOCK;
2327 goto response;
2328 }
2329
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330 result = L2CAP_CR_NO_MEM;
2331
2332 /* Check for backlog size */
2333 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002334 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 goto response;
2336 }
2337
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002338 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339 if (!sk)
2340 goto response;
2341
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002342 chan = l2cap_chan_create(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002343 if (!chan) {
2344 l2cap_sock_kill(sk);
2345 goto response;
2346 }
2347
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03002348 l2cap_pi(sk)->chan = chan;
2349
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002350 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351
2352 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002353 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2354 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355 sock_set_flag(sk, SOCK_ZAPPED);
2356 l2cap_sock_kill(sk);
2357 goto response;
2358 }
2359
2360 hci_conn_hold(conn->hcon);
2361
2362 l2cap_sock_init(sk, parent);
2363 bacpy(&bt_sk(sk)->src, conn->src);
2364 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002365 chan->psm = psm;
2366 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002368 bt_accept_enqueue(parent, sk);
2369
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002370 __l2cap_chan_add(conn, chan);
2371
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002372 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002374 l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002376 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377
Marcel Holtmann984947d2009-02-06 23:35:19 +01002378 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002379 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002380 if (bt_sk(sk)->defer_setup) {
2381 sk->sk_state = BT_CONNECT2;
2382 result = L2CAP_CR_PEND;
2383 status = L2CAP_CS_AUTHOR_PEND;
2384 parent->sk_data_ready(parent, 0);
2385 } else {
2386 sk->sk_state = BT_CONFIG;
2387 result = L2CAP_CR_SUCCESS;
2388 status = L2CAP_CS_NO_INFO;
2389 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002390 } else {
2391 sk->sk_state = BT_CONNECT2;
2392 result = L2CAP_CR_PEND;
2393 status = L2CAP_CS_AUTHEN_PEND;
2394 }
2395 } else {
2396 sk->sk_state = BT_CONNECT2;
2397 result = L2CAP_CR_PEND;
2398 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 }
2400
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002401 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402
2403response:
2404 bh_unlock_sock(parent);
2405
2406sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002407 rsp.scid = cpu_to_le16(scid);
2408 rsp.dcid = cpu_to_le16(dcid);
2409 rsp.result = cpu_to_le16(result);
2410 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002412
2413 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2414 struct l2cap_info_req info;
2415 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2416
2417 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2418 conn->info_ident = l2cap_get_ident(conn);
2419
2420 mod_timer(&conn->info_timer, jiffies +
2421 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2422
2423 l2cap_send_cmd(conn, conn->info_ident,
2424 L2CAP_INFO_REQ, sizeof(info), &info);
2425 }
2426
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002427 if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002428 result == L2CAP_CR_SUCCESS) {
2429 u8 buf[128];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002430 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002431 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002432 l2cap_build_conf_req(chan, buf), buf);
2433 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002434 }
2435
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 return 0;
2437}
2438
2439static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2440{
2441 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2442 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002443 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444 struct sock *sk;
2445 u8 req[128];
2446
2447 scid = __le16_to_cpu(rsp->scid);
2448 dcid = __le16_to_cpu(rsp->dcid);
2449 result = __le16_to_cpu(rsp->result);
2450 status = __le16_to_cpu(rsp->status);
2451
2452 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2453
2454 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002455 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002456 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002457 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002459 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002460 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002461 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462 }
2463
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002464 sk = chan->sk;
2465
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466 switch (result) {
2467 case L2CAP_CR_SUCCESS:
2468 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002469 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002470 chan->dcid = dcid;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002471 chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002472
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002473 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002474 break;
2475
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002476 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002477
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002479 l2cap_build_conf_req(chan, req), req);
2480 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481 break;
2482
2483 case L2CAP_CR_PEND:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002484 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485 break;
2486
2487 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002488 /* don't delete l2cap channel if sk is owned by user */
2489 if (sock_owned_by_user(sk)) {
2490 sk->sk_state = BT_DISCONN;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002491 l2cap_chan_clear_timer(chan);
2492 l2cap_chan_set_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002493 break;
2494 }
2495
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002496 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 break;
2498 }
2499
2500 bh_unlock_sock(sk);
2501 return 0;
2502}
2503
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002504static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002505{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002506 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
2507
Mat Martineau8c462b62010-08-24 15:35:42 -07002508 /* FCS is enabled only in ERTM or streaming mode, if one or both
2509 * sides request it.
2510 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002511 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002512 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002513 else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002514 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002515}
2516
Al Viro88219a02007-07-29 00:17:25 -07002517static 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 -07002518{
2519 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2520 u16 dcid, flags;
2521 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002522 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002524 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525
2526 dcid = __le16_to_cpu(req->dcid);
2527 flags = __le16_to_cpu(req->flags);
2528
2529 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2530
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002531 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002532 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533 return -ENOENT;
2534
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002535 sk = chan->sk;
2536
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002537 if (sk->sk_state != BT_CONFIG) {
2538 struct l2cap_cmd_rej rej;
2539
2540 rej.reason = cpu_to_le16(0x0002);
2541 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2542 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002543 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002544 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002545
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002546 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002547 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002548 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002549 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002550 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002551 L2CAP_CONF_REJECT, flags), rsp);
2552 goto unlock;
2553 }
2554
2555 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002556 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2557 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558
2559 if (flags & 0x0001) {
2560 /* Incomplete config. Send empty response. */
2561 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002562 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002563 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564 goto unlock;
2565 }
2566
2567 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002568 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002569 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002570 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002572 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002574 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002575 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002576
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002577 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002578 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002579
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002580 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002581 goto unlock;
2582
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002583 if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002584 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002585
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002587
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002588 chan->next_tx_seq = 0;
2589 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002590 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002591 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002592 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002593
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002595 goto unlock;
2596 }
2597
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002598 if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002599 u8 buf[64];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002600 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002602 l2cap_build_conf_req(chan, buf), buf);
2603 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604 }
2605
2606unlock:
2607 bh_unlock_sock(sk);
2608 return 0;
2609}
2610
2611static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2612{
2613 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2614 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002615 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002617 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618
2619 scid = __le16_to_cpu(rsp->scid);
2620 flags = __le16_to_cpu(rsp->flags);
2621 result = __le16_to_cpu(rsp->result);
2622
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002623 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2624 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002626 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002627 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628 return 0;
2629
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002630 sk = chan->sk;
2631
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 switch (result) {
2633 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002634 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635 break;
2636
2637 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002638 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002639 char req[64];
2640
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002641 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002642 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002643 goto done;
2644 }
2645
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002646 /* throw out any old stored conf requests */
2647 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002648 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2649 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002650 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002651 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002652 goto done;
2653 }
2654
2655 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2656 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002657 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002658 if (result != L2CAP_CONF_SUCCESS)
2659 goto done;
2660 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661 }
2662
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002663 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002664 sk->sk_err = ECONNRESET;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002665 l2cap_chan_set_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002666 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667 goto done;
2668 }
2669
2670 if (flags & 0x01)
2671 goto done;
2672
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002673 chan->conf_state |= L2CAP_CONF_INPUT_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002675 if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002676 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002677
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002679 chan->next_tx_seq = 0;
2680 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002681 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002682 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002683 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002684
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685 l2cap_chan_ready(sk);
2686 }
2687
2688done:
2689 bh_unlock_sock(sk);
2690 return 0;
2691}
2692
2693static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2694{
2695 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2696 struct l2cap_disconn_rsp rsp;
2697 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002698 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699 struct sock *sk;
2700
2701 scid = __le16_to_cpu(req->scid);
2702 dcid = __le16_to_cpu(req->dcid);
2703
2704 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2705
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002706 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002707 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708 return 0;
2709
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002710 sk = chan->sk;
2711
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002712 rsp.dcid = cpu_to_le16(chan->scid);
2713 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2715
2716 sk->sk_shutdown = SHUTDOWN_MASK;
2717
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002718 /* don't delete l2cap channel if sk is owned by user */
2719 if (sock_owned_by_user(sk)) {
2720 sk->sk_state = BT_DISCONN;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002721 l2cap_chan_clear_timer(chan);
2722 l2cap_chan_set_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002723 bh_unlock_sock(sk);
2724 return 0;
2725 }
2726
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002727 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 bh_unlock_sock(sk);
2729
2730 l2cap_sock_kill(sk);
2731 return 0;
2732}
2733
2734static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2735{
2736 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2737 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002738 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 struct sock *sk;
2740
2741 scid = __le16_to_cpu(rsp->scid);
2742 dcid = __le16_to_cpu(rsp->dcid);
2743
2744 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2745
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002746 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002747 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 return 0;
2749
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002750 sk = chan->sk;
2751
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002752 /* don't delete l2cap channel if sk is owned by user */
2753 if (sock_owned_by_user(sk)) {
2754 sk->sk_state = BT_DISCONN;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002755 l2cap_chan_clear_timer(chan);
2756 l2cap_chan_set_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002757 bh_unlock_sock(sk);
2758 return 0;
2759 }
2760
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002761 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 bh_unlock_sock(sk);
2763
2764 l2cap_sock_kill(sk);
2765 return 0;
2766}
2767
2768static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2769{
2770 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 u16 type;
2772
2773 type = __le16_to_cpu(req->type);
2774
2775 BT_DBG("type 0x%4.4x", type);
2776
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002777 if (type == L2CAP_IT_FEAT_MASK) {
2778 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002779 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002780 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2781 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2782 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002783 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002784 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2785 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002786 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002787 l2cap_send_cmd(conn, cmd->ident,
2788 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002789 } else if (type == L2CAP_IT_FIXED_CHAN) {
2790 u8 buf[12];
2791 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2792 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2793 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2794 memcpy(buf + 4, l2cap_fixed_chan, 8);
2795 l2cap_send_cmd(conn, cmd->ident,
2796 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002797 } else {
2798 struct l2cap_info_rsp rsp;
2799 rsp.type = cpu_to_le16(type);
2800 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2801 l2cap_send_cmd(conn, cmd->ident,
2802 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2803 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804
2805 return 0;
2806}
2807
2808static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2809{
2810 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2811 u16 type, result;
2812
2813 type = __le16_to_cpu(rsp->type);
2814 result = __le16_to_cpu(rsp->result);
2815
2816 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2817
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002818 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2819 if (cmd->ident != conn->info_ident ||
2820 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2821 return 0;
2822
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002823 del_timer(&conn->info_timer);
2824
Ville Tervoadb08ed2010-08-04 09:43:33 +03002825 if (result != L2CAP_IR_SUCCESS) {
2826 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2827 conn->info_ident = 0;
2828
2829 l2cap_conn_start(conn);
2830
2831 return 0;
2832 }
2833
Marcel Holtmann984947d2009-02-06 23:35:19 +01002834 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002835 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002836
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002837 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002838 struct l2cap_info_req req;
2839 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2840
2841 conn->info_ident = l2cap_get_ident(conn);
2842
2843 l2cap_send_cmd(conn, conn->info_ident,
2844 L2CAP_INFO_REQ, sizeof(req), &req);
2845 } else {
2846 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2847 conn->info_ident = 0;
2848
2849 l2cap_conn_start(conn);
2850 }
2851 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002852 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002853 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002854
2855 l2cap_conn_start(conn);
2856 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002857
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858 return 0;
2859}
2860
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002861static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002862 u16 to_multiplier)
2863{
2864 u16 max_latency;
2865
2866 if (min > max || min < 6 || max > 3200)
2867 return -EINVAL;
2868
2869 if (to_multiplier < 10 || to_multiplier > 3200)
2870 return -EINVAL;
2871
2872 if (max >= to_multiplier * 8)
2873 return -EINVAL;
2874
2875 max_latency = (to_multiplier * 8 / max) - 1;
2876 if (latency > 499 || latency > max_latency)
2877 return -EINVAL;
2878
2879 return 0;
2880}
2881
2882static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2883 struct l2cap_cmd_hdr *cmd, u8 *data)
2884{
2885 struct hci_conn *hcon = conn->hcon;
2886 struct l2cap_conn_param_update_req *req;
2887 struct l2cap_conn_param_update_rsp rsp;
2888 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002889 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002890
2891 if (!(hcon->link_mode & HCI_LM_MASTER))
2892 return -EINVAL;
2893
2894 cmd_len = __le16_to_cpu(cmd->len);
2895 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2896 return -EPROTO;
2897
2898 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002899 min = __le16_to_cpu(req->min);
2900 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002901 latency = __le16_to_cpu(req->latency);
2902 to_multiplier = __le16_to_cpu(req->to_multiplier);
2903
2904 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2905 min, max, latency, to_multiplier);
2906
2907 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002908
2909 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2910 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002911 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2912 else
2913 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2914
2915 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2916 sizeof(rsp), &rsp);
2917
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002918 if (!err)
2919 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2920
Claudio Takahaside731152011-02-11 19:28:55 -02002921 return 0;
2922}
2923
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002924static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2925 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2926{
2927 int err = 0;
2928
2929 switch (cmd->code) {
2930 case L2CAP_COMMAND_REJ:
2931 l2cap_command_rej(conn, cmd, data);
2932 break;
2933
2934 case L2CAP_CONN_REQ:
2935 err = l2cap_connect_req(conn, cmd, data);
2936 break;
2937
2938 case L2CAP_CONN_RSP:
2939 err = l2cap_connect_rsp(conn, cmd, data);
2940 break;
2941
2942 case L2CAP_CONF_REQ:
2943 err = l2cap_config_req(conn, cmd, cmd_len, data);
2944 break;
2945
2946 case L2CAP_CONF_RSP:
2947 err = l2cap_config_rsp(conn, cmd, data);
2948 break;
2949
2950 case L2CAP_DISCONN_REQ:
2951 err = l2cap_disconnect_req(conn, cmd, data);
2952 break;
2953
2954 case L2CAP_DISCONN_RSP:
2955 err = l2cap_disconnect_rsp(conn, cmd, data);
2956 break;
2957
2958 case L2CAP_ECHO_REQ:
2959 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2960 break;
2961
2962 case L2CAP_ECHO_RSP:
2963 break;
2964
2965 case L2CAP_INFO_REQ:
2966 err = l2cap_information_req(conn, cmd, data);
2967 break;
2968
2969 case L2CAP_INFO_RSP:
2970 err = l2cap_information_rsp(conn, cmd, data);
2971 break;
2972
2973 default:
2974 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2975 err = -EINVAL;
2976 break;
2977 }
2978
2979 return err;
2980}
2981
2982static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2983 struct l2cap_cmd_hdr *cmd, u8 *data)
2984{
2985 switch (cmd->code) {
2986 case L2CAP_COMMAND_REJ:
2987 return 0;
2988
2989 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002990 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002991
2992 case L2CAP_CONN_PARAM_UPDATE_RSP:
2993 return 0;
2994
2995 default:
2996 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2997 return -EINVAL;
2998 }
2999}
3000
3001static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3002 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003{
3004 u8 *data = skb->data;
3005 int len = skb->len;
3006 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003007 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008
3009 l2cap_raw_recv(conn, skb);
3010
3011 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003012 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3014 data += L2CAP_CMD_HDR_SIZE;
3015 len -= L2CAP_CMD_HDR_SIZE;
3016
Al Viro88219a02007-07-29 00:17:25 -07003017 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018
Al Viro88219a02007-07-29 00:17:25 -07003019 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 -07003020
Al Viro88219a02007-07-29 00:17:25 -07003021 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022 BT_DBG("corrupted command");
3023 break;
3024 }
3025
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003026 if (conn->hcon->type == LE_LINK)
3027 err = l2cap_le_sig_cmd(conn, &cmd, data);
3028 else
3029 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030
3031 if (err) {
3032 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003033
3034 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035
3036 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003037 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3039 }
3040
Al Viro88219a02007-07-29 00:17:25 -07003041 data += cmd_len;
3042 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043 }
3044
3045 kfree_skb(skb);
3046}
3047
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003048static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003049{
3050 u16 our_fcs, rcv_fcs;
3051 int hdr_size = L2CAP_HDR_SIZE + 2;
3052
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003053 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003054 skb_trim(skb, skb->len - 2);
3055 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3056 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3057
3058 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003059 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003060 }
3061 return 0;
3062}
3063
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003064static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003065{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003066 u16 control = 0;
3067
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003068 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003069
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003070 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003071
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003072 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003073 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003074 l2cap_send_sframe(chan, control);
3075 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003076 }
3077
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003078 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
3079 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003080
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003081 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003082
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003083 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003084 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003085 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003086 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003087 }
3088}
3089
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003090static 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 -03003091{
3092 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03003093 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003094
3095 bt_cb(skb)->tx_seq = tx_seq;
3096 bt_cb(skb)->sar = sar;
3097
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003098 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003099 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003100 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003101 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003102 }
3103
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003104 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03003105 if (tx_seq_offset < 0)
3106 tx_seq_offset += 64;
3107
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003108 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003109 if (bt_cb(next_skb)->tx_seq == tx_seq)
3110 return -EINVAL;
3111
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03003112 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003113 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03003114 if (next_tx_seq_offset < 0)
3115 next_tx_seq_offset += 64;
3116
3117 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003118 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003119 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003120 }
3121
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003122 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003123 break;
3124
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003125 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003126
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003127 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003128
3129 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003130}
3131
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003132static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003133{
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003134 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003135 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003136
3137 switch (control & L2CAP_CTRL_SAR) {
3138 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003139 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003140 goto drop;
3141
Ruiyi Zhang224f8af2011-05-13 13:07:52 +08003142 return sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003143
3144 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003145 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003146 goto drop;
3147
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003148 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003149
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003150 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003151 goto disconnect;
3152
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003153 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3154 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003155 return -ENOMEM;
3156
3157 /* pull sdu_len bytes only after alloc, because of Local Busy
3158 * condition we have to be sure that this will be executed
3159 * only once, i.e., when alloc does not fail */
3160 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003161
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003162 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003163
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003164 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003165 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003166 break;
3167
3168 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003169 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003170 goto disconnect;
3171
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003172 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003173 goto disconnect;
3174
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003175 chan->partial_sdu_len += skb->len;
3176 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003177 goto drop;
3178
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003179 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003180
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003181 break;
3182
3183 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003184 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003185 goto disconnect;
3186
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003187 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003188 goto disconnect;
3189
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003190 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003191 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003192
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003193 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003194 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003195
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003196 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003197 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003198
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003199 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003200 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003201
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003202 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003203 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003204 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003205 return -ENOMEM;
3206 }
3207
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003208 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003209 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003210 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003211 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003212 return err;
3213 }
3214
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003215 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
3216 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003217
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003218 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003219 break;
3220 }
3221
3222 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003223 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003224
3225drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003226 kfree_skb(chan->sdu);
3227 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003228
3229disconnect:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003230 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003231 kfree_skb(skb);
3232 return 0;
3233}
3234
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003235static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003236{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003237 struct sk_buff *skb;
3238 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003239 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003240
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003241 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003242 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003243 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003244 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003245 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003246 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003247 }
3248
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003249 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003250 }
3251
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003252 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003253 goto done;
3254
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003255 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003256 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003257 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003258 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003259
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003260 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003261 __mod_monitor_timer();
3262
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003263 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003264
3265done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003266 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3267 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003268
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003269 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003270
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003271 return 0;
3272}
3273
3274static void l2cap_busy_work(struct work_struct *work)
3275{
3276 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003277 struct l2cap_chan *chan =
3278 container_of(work, struct l2cap_chan, busy_work);
3279 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003280 int n_tries = 0, timeo = HZ/5, err;
3281 struct sk_buff *skb;
3282
3283 lock_sock(sk);
3284
3285 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003286 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003287 set_current_state(TASK_INTERRUPTIBLE);
3288
3289 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3290 err = -EBUSY;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003291 l2cap_send_disconn_req(chan->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003292 break;
3293 }
3294
3295 if (!timeo)
3296 timeo = HZ/5;
3297
3298 if (signal_pending(current)) {
3299 err = sock_intr_errno(timeo);
3300 break;
3301 }
3302
3303 release_sock(sk);
3304 timeo = schedule_timeout(timeo);
3305 lock_sock(sk);
3306
3307 err = sock_error(sk);
3308 if (err)
3309 break;
3310
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003311 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003312 break;
3313 }
3314
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003315 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003316 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003317
3318 release_sock(sk);
3319}
3320
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003321static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003322{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003323 int sctrl, err;
3324
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003325 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003326 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003327 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003328 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003329
3330
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003331 }
3332
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003333 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003334 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003335 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003336 return err;
3337 }
3338
3339 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003340 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003341
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003342 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003343 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003344 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003345
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003346 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003347 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003348 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003349
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003350 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003351
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003352 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003353
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003354 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003355
3356 return err;
3357}
3358
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003359static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003360{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003361 struct sk_buff *_skb;
3362 int err = -EINVAL;
3363
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003364 /*
3365 * TODO: We have to notify the userland if some data is lost with the
3366 * Streaming Mode.
3367 */
3368
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003369 switch (control & L2CAP_CTRL_SAR) {
3370 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003371 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003372 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003373 break;
3374 }
3375
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003376 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003377 if (!err)
3378 return 0;
3379
3380 break;
3381
3382 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003383 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003384 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003385 break;
3386 }
3387
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003388 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003389 skb_pull(skb, 2);
3390
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003391 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003392 err = -EMSGSIZE;
3393 break;
3394 }
3395
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003396 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3397 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003398 err = -ENOMEM;
3399 break;
3400 }
3401
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003402 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003403
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003404 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003405 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003406 err = 0;
3407 break;
3408
3409 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003410 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003411 break;
3412
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003413 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003414
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003415 chan->partial_sdu_len += skb->len;
3416 if (chan->partial_sdu_len > chan->sdu_len)
3417 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003418 else
3419 err = 0;
3420
3421 break;
3422
3423 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003424 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003425 break;
3426
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003427 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003428
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003429 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003430 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003431
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003432 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003433 goto drop;
3434
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003435 if (chan->partial_sdu_len == chan->sdu_len) {
3436 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003437 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003438 if (err < 0)
3439 kfree_skb(_skb);
3440 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003441 err = 0;
3442
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003443drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003444 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003445 break;
3446 }
3447
3448 kfree_skb(skb);
3449 return err;
3450}
3451
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003452static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003453{
3454 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003455 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003456
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003457 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003458 if (bt_cb(skb)->tx_seq != tx_seq)
3459 break;
3460
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003461 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003462 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003463 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003464 chan->buffer_seq_srej =
3465 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003466 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003467 }
3468}
3469
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003470static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003471{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003472 struct srej_list *l, *tmp;
3473 u16 control;
3474
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003475 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003476 if (l->tx_seq == tx_seq) {
3477 list_del(&l->list);
3478 kfree(l);
3479 return;
3480 }
3481 control = L2CAP_SUPER_SELECT_REJECT;
3482 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003483 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003484 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003485 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003486 }
3487}
3488
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003489static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003490{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003491 struct srej_list *new;
3492 u16 control;
3493
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003494 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003495 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003496 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003497 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003498
3499 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003500 new->tx_seq = chan->expected_tx_seq;
3501 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003502 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003503 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003504 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003505}
3506
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003507static 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 -03003508{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003509 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003510 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003511 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003512 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003513 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003514 int err = 0;
3515
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003516 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3517 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003518
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003519 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003520 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003521 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003522 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003523 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003524 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003525 }
3526
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003527 chan->expected_ack_seq = req_seq;
3528 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003529
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003530 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003531 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003532
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003533 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003534 if (tx_seq_offset < 0)
3535 tx_seq_offset += 64;
3536
3537 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003538 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003539 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003540 goto drop;
3541 }
3542
Mat Martineaue6949282011-06-03 16:21:10 -07003543 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003544 goto drop;
3545
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003546 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003547 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003548
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003549 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003550 struct srej_list, list);
3551 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003552 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003553 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003554
3555 list_del(&first->list);
3556 kfree(first);
3557
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003558 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003559 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003560 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3561 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003562 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003563 }
3564 } else {
3565 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003566
3567 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003568 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003569 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003570
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003571 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003572 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003573 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003574 return 0;
3575 }
3576 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003577 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003578 }
3579 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003580 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003581 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003582 if (expected_tx_seq_offset < 0)
3583 expected_tx_seq_offset += 64;
3584
3585 /* duplicated tx_seq */
3586 if (tx_seq_offset < expected_tx_seq_offset)
3587 goto drop;
3588
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003589 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003590
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003591 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003592
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003593 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003594 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003595
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003596 __skb_queue_head_init(&chan->srej_q);
3597 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003598 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003599
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003600 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003601
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003602 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003603
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003604 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003605 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003606 return 0;
3607
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003608expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003609 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003610
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003611 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003612 bt_cb(skb)->tx_seq = tx_seq;
3613 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003614 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003615 return 0;
3616 }
3617
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003618 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003619 if (err < 0)
3620 return 0;
3621
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003622 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003623 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3624 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003625 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003626 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003627 }
3628
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003629 __mod_ack_timer();
3630
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003631 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3632 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003633 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003634
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003635 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003636
3637drop:
3638 kfree_skb(skb);
3639 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003640}
3641
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003642static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003643{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003644 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003645 rx_control);
3646
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003647 chan->expected_ack_seq = __get_reqseq(rx_control);
3648 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003649
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003650 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003651 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3652 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3653 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003654 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003655 __mod_retrans_timer();
3656
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003657 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3658 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003659 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003660 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003661 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003662
3663 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003664 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003665
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003666 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3667 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003668 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003669 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003670
3671 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003672 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003673 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003674 __mod_retrans_timer();
3675
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003676 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3677 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3678 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003679 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003680 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003681 }
3682}
3683
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003684static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003685{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003686 u8 tx_seq = __get_reqseq(rx_control);
3687
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003688 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003689
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003690 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003691
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003692 chan->expected_ack_seq = tx_seq;
3693 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003694
3695 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003696 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3697 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003698 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003699 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003700 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003701 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003702
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003703 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3704 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003705 }
3706}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003707static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003708{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003709 u8 tx_seq = __get_reqseq(rx_control);
3710
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003711 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003712
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003713 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003714
3715 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003716 chan->expected_ack_seq = tx_seq;
3717 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003718
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003719 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3720 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003721
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003722 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003723
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003724 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003725 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003726 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003727 }
3728 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003729 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003730 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003731 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003732 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003733 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003734 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003735 l2cap_retransmit_one_frame(chan, tx_seq);
3736 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003737 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003738 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003739 }
3740 }
3741}
3742
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003743static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003744{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003745 u8 tx_seq = __get_reqseq(rx_control);
3746
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003747 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003748
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003749 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003750 chan->expected_ack_seq = tx_seq;
3751 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003752
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003753 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003754 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003755
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003756 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003757 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003758 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003759 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003760 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003761 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003762
3763 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003764 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003765 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003766 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003767}
3768
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003769static 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 -03003770{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003771 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003772
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003773 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003774 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003775 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003776 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003777 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003778 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003779 }
3780
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003781 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3782 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003783 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003784 break;
3785
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003786 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003787 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003788 break;
3789
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003790 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003791 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003792 break;
3793
3794 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003795 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003796 break;
3797 }
3798
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003799 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003800 return 0;
3801}
3802
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003803static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3804{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003805 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003806 u16 control;
3807 u8 req_seq;
3808 int len, next_tx_seq_offset, req_seq_offset;
3809
3810 control = get_unaligned_le16(skb->data);
3811 skb_pull(skb, 2);
3812 len = skb->len;
3813
3814 /*
3815 * We can just drop the corrupted I-frame here.
3816 * Receiver will miss it and start proper recovery
3817 * procedures and ask retransmission.
3818 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003819 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003820 goto drop;
3821
3822 if (__is_sar_start(control) && __is_iframe(control))
3823 len -= 2;
3824
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003825 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003826 len -= 2;
3827
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003828 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003829 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003830 goto drop;
3831 }
3832
3833 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003834 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003835 if (req_seq_offset < 0)
3836 req_seq_offset += 64;
3837
3838 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003839 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003840 if (next_tx_seq_offset < 0)
3841 next_tx_seq_offset += 64;
3842
3843 /* check for invalid req-seq */
3844 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003845 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003846 goto drop;
3847 }
3848
3849 if (__is_iframe(control)) {
3850 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003851 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003852 goto drop;
3853 }
3854
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003855 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003856 } else {
3857 if (len != 0) {
3858 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003859 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003860 goto drop;
3861 }
3862
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003863 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003864 }
3865
3866 return 0;
3867
3868drop:
3869 kfree_skb(skb);
3870 return 0;
3871}
3872
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3874{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003875 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003876 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003877 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003878 u8 tx_seq;
3879 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003881 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003882 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883 BT_DBG("unknown cid 0x%4.4x", cid);
3884 goto drop;
3885 }
3886
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003887 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003888
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003889 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890
3891 if (sk->sk_state != BT_CONNECTED)
3892 goto drop;
3893
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003894 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003895 case L2CAP_MODE_BASIC:
3896 /* If socket recv buffers overflows we drop data here
3897 * which is *bad* because L2CAP has to be reliable.
3898 * But we don't have any other choice. L2CAP doesn't
3899 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003900
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003901 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003902 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003904 if (!sock_queue_rcv_skb(sk, skb))
3905 goto done;
3906 break;
3907
3908 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003909 if (!sock_owned_by_user(sk)) {
3910 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003911 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003912 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003913 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003914 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003915
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003916 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003917
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003918 case L2CAP_MODE_STREAMING:
3919 control = get_unaligned_le16(skb->data);
3920 skb_pull(skb, 2);
3921 len = skb->len;
3922
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003923 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003924 goto drop;
3925
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003926 if (__is_sar_start(control))
3927 len -= 2;
3928
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003929 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003930 len -= 2;
3931
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003932 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003933 goto drop;
3934
3935 tx_seq = __get_txseq(control);
3936
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003937 if (chan->expected_tx_seq == tx_seq)
3938 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003939 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003940 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003941
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003942 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003943
3944 goto done;
3945
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003946 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003947 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003948 break;
3949 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950
3951drop:
3952 kfree_skb(skb);
3953
3954done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003955 if (sk)
3956 bh_unlock_sock(sk);
3957
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 return 0;
3959}
3960
Al Viro8e036fc2007-07-29 00:16:36 -07003961static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003963 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003964 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003966 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3967 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968 goto drop;
3969
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003970 sk = chan->sk;
3971
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003972 bh_lock_sock(sk);
3973
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974 BT_DBG("sk %p, len %d", sk, skb->len);
3975
3976 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3977 goto drop;
3978
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003979 if (l2cap_pi(sk)->chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980 goto drop;
3981
3982 if (!sock_queue_rcv_skb(sk, skb))
3983 goto done;
3984
3985drop:
3986 kfree_skb(skb);
3987
3988done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003989 if (sk)
3990 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991 return 0;
3992}
3993
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003994static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3995{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003996 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003997 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003998
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003999 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
4000 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004001 goto drop;
4002
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004003 sk = chan->sk;
4004
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004005 bh_lock_sock(sk);
4006
4007 BT_DBG("sk %p, len %d", sk, skb->len);
4008
4009 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
4010 goto drop;
4011
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004012 if (l2cap_pi(sk)->chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004013 goto drop;
4014
4015 if (!sock_queue_rcv_skb(sk, skb))
4016 goto done;
4017
4018drop:
4019 kfree_skb(skb);
4020
4021done:
4022 if (sk)
4023 bh_unlock_sock(sk);
4024 return 0;
4025}
4026
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4028{
4029 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004030 u16 cid, len;
4031 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032
4033 skb_pull(skb, L2CAP_HDR_SIZE);
4034 cid = __le16_to_cpu(lh->cid);
4035 len = __le16_to_cpu(lh->len);
4036
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004037 if (len != skb->len) {
4038 kfree_skb(skb);
4039 return;
4040 }
4041
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4043
4044 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004045 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004046 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047 l2cap_sig_channel(conn, skb);
4048 break;
4049
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004050 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004051 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052 skb_pull(skb, 2);
4053 l2cap_conless_channel(conn, psm, skb);
4054 break;
4055
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004056 case L2CAP_CID_LE_DATA:
4057 l2cap_att_channel(conn, cid, skb);
4058 break;
4059
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 default:
4061 l2cap_data_channel(conn, cid, skb);
4062 break;
4063 }
4064}
4065
4066/* ---- L2CAP interface with lower layer (HCI) ---- */
4067
4068static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4069{
4070 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004071 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072
4073 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004074 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075
4076 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4077
4078 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004079 read_lock(&chan_list_lock);
4080 list_for_each_entry(c, &chan_list, global_l) {
4081 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004082
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083 if (sk->sk_state != BT_LISTEN)
4084 continue;
4085
4086 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004087 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004088 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004089 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004091 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4092 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004093 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004094 lm2 |= HCI_LM_MASTER;
4095 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004097 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098
4099 return exact ? lm1 : lm2;
4100}
4101
4102static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4103{
Marcel Holtmann01394182006-07-03 10:02:46 +02004104 struct l2cap_conn *conn;
4105
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4107
Ville Tervoacd7d372011-02-10 22:38:49 -03004108 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004109 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110
4111 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112 conn = l2cap_conn_add(hcon, status);
4113 if (conn)
4114 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004115 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116 l2cap_conn_del(hcon, bt_err(status));
4117
4118 return 0;
4119}
4120
Marcel Holtmann2950f212009-02-12 14:02:50 +01004121static int l2cap_disconn_ind(struct hci_conn *hcon)
4122{
4123 struct l2cap_conn *conn = hcon->l2cap_data;
4124
4125 BT_DBG("hcon %p", hcon);
4126
4127 if (hcon->type != ACL_LINK || !conn)
4128 return 0x13;
4129
4130 return conn->disc_reason;
4131}
4132
4133static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134{
4135 BT_DBG("hcon %p reason %d", hcon, reason);
4136
Ville Tervoacd7d372011-02-10 22:38:49 -03004137 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004138 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004139
4140 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004141
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142 return 0;
4143}
4144
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004145static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004146{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004147 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004148 return;
4149
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004150 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004151 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanab078012011-05-02 18:25:01 -03004152 l2cap_chan_clear_timer(chan);
4153 l2cap_chan_set_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004154 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004155 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004156 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004157 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanab078012011-05-02 18:25:01 -03004158 l2cap_chan_clear_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004159 }
4160}
4161
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004162static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004163{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004164 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004165 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166
Marcel Holtmann01394182006-07-03 10:02:46 +02004167 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004169
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170 BT_DBG("conn %p", conn);
4171
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004172 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004174 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004175 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004176
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177 bh_lock_sock(sk);
4178
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03004179 if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004180 bh_unlock_sock(sk);
4181 continue;
4182 }
4183
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004184 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004185 sk->sk_state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004186 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004187 bh_unlock_sock(sk);
4188 continue;
4189 }
4190
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004191 if (sk->sk_state == BT_CONNECT) {
4192 if (!status) {
4193 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004194 req.scid = cpu_to_le16(chan->scid);
4195 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004196
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004197 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03004198 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004199
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004200 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004201 L2CAP_CONN_REQ, sizeof(req), &req);
4202 } else {
Gustavo F. Padovanab078012011-05-02 18:25:01 -03004203 l2cap_chan_clear_timer(chan);
4204 l2cap_chan_set_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004205 }
4206 } else if (sk->sk_state == BT_CONNECT2) {
4207 struct l2cap_conn_rsp rsp;
4208 __u16 result;
4209
4210 if (!status) {
4211 sk->sk_state = BT_CONFIG;
4212 result = L2CAP_CR_SUCCESS;
4213 } else {
4214 sk->sk_state = BT_DISCONN;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03004215 l2cap_chan_set_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004216 result = L2CAP_CR_SEC_BLOCK;
4217 }
4218
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004219 rsp.scid = cpu_to_le16(chan->dcid);
4220 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004221 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02004222 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004223 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4224 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225 }
4226
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227 bh_unlock_sock(sk);
4228 }
4229
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004230 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004231
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232 return 0;
4233}
4234
4235static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4236{
4237 struct l2cap_conn *conn = hcon->l2cap_data;
4238
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004239 if (!conn)
4240 conn = l2cap_conn_add(hcon, 0);
4241
4242 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004243 goto drop;
4244
4245 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4246
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004247 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004249 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004250 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004251 int len;
4252
4253 if (conn->rx_len) {
4254 BT_ERR("Unexpected start frame (len %d)", skb->len);
4255 kfree_skb(conn->rx_skb);
4256 conn->rx_skb = NULL;
4257 conn->rx_len = 0;
4258 l2cap_conn_unreliable(conn, ECOMM);
4259 }
4260
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004261 /* Start fragment always begin with Basic L2CAP header */
4262 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004263 BT_ERR("Frame is too short (len %d)", skb->len);
4264 l2cap_conn_unreliable(conn, ECOMM);
4265 goto drop;
4266 }
4267
4268 hdr = (struct l2cap_hdr *) skb->data;
4269 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004270 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271
4272 if (len == skb->len) {
4273 /* Complete frame received */
4274 l2cap_recv_frame(conn, skb);
4275 return 0;
4276 }
4277
4278 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4279
4280 if (skb->len > len) {
4281 BT_ERR("Frame is too long (len %d, expected len %d)",
4282 skb->len, len);
4283 l2cap_conn_unreliable(conn, ECOMM);
4284 goto drop;
4285 }
4286
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004287 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004288
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004289 if (chan && chan->sk) {
4290 struct sock *sk = chan->sk;
4291
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004292 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004293 BT_ERR("Frame exceeding recv MTU (len %d, "
4294 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004295 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004296 bh_unlock_sock(sk);
4297 l2cap_conn_unreliable(conn, ECOMM);
4298 goto drop;
4299 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004300 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004301 }
4302
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004304 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4305 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306 goto drop;
4307
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004308 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004309 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310 conn->rx_len = len - skb->len;
4311 } else {
4312 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4313
4314 if (!conn->rx_len) {
4315 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4316 l2cap_conn_unreliable(conn, ECOMM);
4317 goto drop;
4318 }
4319
4320 if (skb->len > conn->rx_len) {
4321 BT_ERR("Fragment is too long (len %d, expected %d)",
4322 skb->len, conn->rx_len);
4323 kfree_skb(conn->rx_skb);
4324 conn->rx_skb = NULL;
4325 conn->rx_len = 0;
4326 l2cap_conn_unreliable(conn, ECOMM);
4327 goto drop;
4328 }
4329
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004330 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004331 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332 conn->rx_len -= skb->len;
4333
4334 if (!conn->rx_len) {
4335 /* Complete frame received */
4336 l2cap_recv_frame(conn, conn->rx_skb);
4337 conn->rx_skb = NULL;
4338 }
4339 }
4340
4341drop:
4342 kfree_skb(skb);
4343 return 0;
4344}
4345
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004346static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004348 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004350 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004351
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004352 list_for_each_entry(c, &chan_list, global_l) {
4353 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004355 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 +01004356 batostr(&bt_sk(sk)->src),
4357 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004358 sk->sk_state, __le16_to_cpu(c->psm),
4359 c->scid, c->dcid, c->imtu, c->omtu,
4360 c->sec_level, c->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004361 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004362
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004363 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004364
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004365 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004366}
4367
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004368static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4369{
4370 return single_open(file, l2cap_debugfs_show, inode->i_private);
4371}
4372
4373static const struct file_operations l2cap_debugfs_fops = {
4374 .open = l2cap_debugfs_open,
4375 .read = seq_read,
4376 .llseek = seq_lseek,
4377 .release = single_release,
4378};
4379
4380static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004381
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382static struct hci_proto l2cap_hci_proto = {
4383 .name = "L2CAP",
4384 .id = HCI_PROTO_L2CAP,
4385 .connect_ind = l2cap_connect_ind,
4386 .connect_cfm = l2cap_connect_cfm,
4387 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004388 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004389 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004390 .recv_acldata = l2cap_recv_acldata
4391};
4392
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004393int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394{
4395 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004396
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004397 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398 if (err < 0)
4399 return err;
4400
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004401 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004402 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004403 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004404 goto error;
4405 }
4406
4407 err = hci_register_proto(&l2cap_hci_proto);
4408 if (err < 0) {
4409 BT_ERR("L2CAP protocol registration failed");
4410 bt_sock_unregister(BTPROTO_L2CAP);
4411 goto error;
4412 }
4413
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004414 if (bt_debugfs) {
4415 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4416 bt_debugfs, NULL, &l2cap_debugfs_fops);
4417 if (!l2cap_debugfs)
4418 BT_ERR("Failed to create L2CAP debug file");
4419 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421 return 0;
4422
4423error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004424 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004425 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004426 return err;
4427}
4428
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004429void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004431 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004433 flush_workqueue(_busy_wq);
4434 destroy_workqueue(_busy_wq);
4435
Linus Torvalds1da177e2005-04-16 15:20:36 -07004436 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4437 BT_ERR("L2CAP protocol unregistration failed");
4438
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004439 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440}
4441
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004442module_param(disable_ertm, bool, 0644);
4443MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");