blob: 8369f568039196ddf43172f0cf15f5db951d19c8 [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
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300845 chan = pchan->ops->new_connection(pchan->data);
846 if (!chan)
Ville Tervob62f3282011-02-10 22:38:50 -0300847 goto clean;
848
Gustavo F. Padovan80808e42011-05-16 17:24:37 -0300849 sk = chan->sk;
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300850
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300851 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300852
853 hci_conn_hold(conn->hcon);
854
Ville Tervob62f3282011-02-10 22:38:50 -0300855 bacpy(&bt_sk(sk)->src, conn->src);
856 bacpy(&bt_sk(sk)->dst, conn->dst);
857
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300858 bt_accept_enqueue(parent, sk);
859
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300860 __l2cap_chan_add(conn, chan);
861
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300862 l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300863
864 sk->sk_state = BT_CONNECTED;
865 parent->sk_data_ready(parent, 0);
866
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300867 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300868
869clean:
870 bh_unlock_sock(parent);
871}
872
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200873static void l2cap_conn_ready(struct l2cap_conn *conn)
874{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300875 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200876
877 BT_DBG("conn %p", conn);
878
Ville Tervob62f3282011-02-10 22:38:50 -0300879 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
880 l2cap_le_conn_ready(conn);
881
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300882 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200883
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300884 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300885 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300886
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200887 bh_lock_sock(sk);
888
Ville Tervoacd7d372011-02-10 22:38:49 -0300889 if (conn->hcon->type == LE_LINK) {
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300890 l2cap_chan_clear_timer(chan);
Ville Tervoacd7d372011-02-10 22:38:49 -0300891 sk->sk_state = BT_CONNECTED;
892 sk->sk_state_change(sk);
893 }
894
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300895 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300896 l2cap_chan_clear_timer(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200897 sk->sk_state = BT_CONNECTED;
898 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200899 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300900 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200901
902 bh_unlock_sock(sk);
903 }
904
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300905 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200906}
907
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200908/* Notify sockets that we cannot guaranty reliability anymore */
909static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
910{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300911 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200912
913 BT_DBG("conn %p", conn);
914
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300915 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200916
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300917 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300918 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300919
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300920 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200921 sk->sk_err = err;
922 }
923
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300924 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200925}
926
927static void l2cap_info_timeout(unsigned long arg)
928{
929 struct l2cap_conn *conn = (void *) arg;
930
Marcel Holtmann984947d2009-02-06 23:35:19 +0100931 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100932 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100933
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200934 l2cap_conn_start(conn);
935}
936
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
938{
Marcel Holtmann01394182006-07-03 10:02:46 +0200939 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940
Marcel Holtmann01394182006-07-03 10:02:46 +0200941 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 return conn;
943
Marcel Holtmann01394182006-07-03 10:02:46 +0200944 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
945 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947
948 hcon->l2cap_data = conn;
949 conn->hcon = hcon;
950
Marcel Holtmann01394182006-07-03 10:02:46 +0200951 BT_DBG("hcon %p conn %p", hcon, conn);
952
Ville Tervoacd7d372011-02-10 22:38:49 -0300953 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
954 conn->mtu = hcon->hdev->le_mtu;
955 else
956 conn->mtu = hcon->hdev->acl_mtu;
957
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 conn->src = &hcon->hdev->bdaddr;
959 conn->dst = &hcon->dst;
960
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200961 conn->feat_mask = 0;
962
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300964 rwlock_init(&conn->chan_lock);
965
966 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967
Ville Tervob62f3282011-02-10 22:38:50 -0300968 if (hcon->type != LE_LINK)
969 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000970 (unsigned long) conn);
971
Marcel Holtmann2950f212009-02-12 14:02:50 +0100972 conn->disc_reason = 0x13;
973
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 return conn;
975}
976
Marcel Holtmann01394182006-07-03 10:02:46 +0200977static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978{
Marcel Holtmann01394182006-07-03 10:02:46 +0200979 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300980 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 struct sock *sk;
982
Marcel Holtmann01394182006-07-03 10:02:46 +0200983 if (!conn)
984 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985
986 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
987
Wei Yongjun7585b972009-02-25 18:29:52 +0800988 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989
990 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300991 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300992 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300994 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 bh_unlock_sock(sk);
996 l2cap_sock_kill(sk);
997 }
998
Dave Young8e8440f2008-03-03 12:18:55 -0800999 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1000 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -08001001
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 hcon->l2cap_data = NULL;
1003 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004}
1005
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001006static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001008 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001009 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001010 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011}
1012
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014
1015/* Find socket with psm and source bdaddr.
1016 * Returns closest match.
1017 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001018static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001020 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001022 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001023
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001024 list_for_each_entry(c, &chan_list, global_l) {
1025 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001026
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 if (state && sk->sk_state != state)
1028 continue;
1029
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001030 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001032 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001033 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001034 return c;
1035 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036
1037 /* Closest match */
1038 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001039 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 }
1041 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001043 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001044
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001045 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046}
1047
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001048int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001050 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 bdaddr_t *src = &bt_sk(sk)->src;
1052 bdaddr_t *dst = &bt_sk(sk)->dst;
1053 struct l2cap_conn *conn;
1054 struct hci_conn *hcon;
1055 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001056 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001057 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001059 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001060 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001062 hdev = hci_get_route(dst, src);
1063 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 return -EHOSTUNREACH;
1065
1066 hci_dev_lock_bh(hdev);
1067
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001068 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001069
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001070 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001071 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001072 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001073 else
1074 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001075 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001076
Ville Tervo30e76272011-02-22 16:10:53 -03001077 if (IS_ERR(hcon)) {
1078 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001080 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081
1082 conn = l2cap_conn_add(hcon, 0);
1083 if (!conn) {
1084 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001085 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 goto done;
1087 }
1088
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 /* Update source addr of the socket */
1090 bacpy(src, conn->src);
1091
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001092 l2cap_chan_add(conn, chan);
1093
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 sk->sk_state = BT_CONNECT;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03001095 l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096
1097 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001098 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanab078012011-05-02 18:25:01 -03001099 l2cap_chan_clear_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001100 if (l2cap_check_security(chan))
Johan Hedbergd00ef242011-01-19 12:06:51 +05301101 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001102 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001103 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 }
1105
Ville Tervo30e76272011-02-22 16:10:53 -03001106 err = 0;
1107
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108done:
1109 hci_dev_unlock_bh(hdev);
1110 hci_dev_put(hdev);
1111 return err;
1112}
1113
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001114int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001115{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001116 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001117 DECLARE_WAITQUEUE(wait, current);
1118 int err = 0;
1119 int timeo = HZ/5;
1120
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001121 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001122 while ((chan->unacked_frames > 0 && chan->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001123 set_current_state(TASK_INTERRUPTIBLE);
1124
1125 if (!timeo)
1126 timeo = HZ/5;
1127
1128 if (signal_pending(current)) {
1129 err = sock_intr_errno(timeo);
1130 break;
1131 }
1132
1133 release_sock(sk);
1134 timeo = schedule_timeout(timeo);
1135 lock_sock(sk);
1136
1137 err = sock_error(sk);
1138 if (err)
1139 break;
1140 }
1141 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001142 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001143 return err;
1144}
1145
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001146static void l2cap_monitor_timeout(unsigned long arg)
1147{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001148 struct l2cap_chan *chan = (void *) arg;
1149 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001150
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001151 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001152
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001153 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001154 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001155 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001156 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001157 return;
1158 }
1159
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001160 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001161 __mod_monitor_timer();
1162
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001163 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001164 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001165}
1166
1167static void l2cap_retrans_timeout(unsigned long arg)
1168{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001169 struct l2cap_chan *chan = (void *) arg;
1170 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001171
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001172 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001173
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001174 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001175 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001176 __mod_monitor_timer();
1177
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001178 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001179
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001180 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001181 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001182}
1183
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001184static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001185{
1186 struct sk_buff *skb;
1187
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001188 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001189 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001190 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001191 break;
1192
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001193 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001194 kfree_skb(skb);
1195
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001196 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001197 }
1198
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001199 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001200 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001201}
1202
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001203void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001204{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001205 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001206 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001207
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001208 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001209
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001210 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001211 flags = ACL_START_NO_FLUSH;
1212 else
1213 flags = ACL_START;
1214
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -07001215 bt_cb(skb)->force_active = chan->force_active;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001216 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001217}
1218
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001219void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001220{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001221 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001222 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001223
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001224 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001225 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001226 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001227 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001228
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001229 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001230 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1231 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001232 }
1233
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001234 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001235
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001236 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001237 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001238}
1239
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001240static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001241{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001242 struct sk_buff *skb, *tx_skb;
1243 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001244
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001245 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001246 if (!skb)
1247 return;
1248
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001249 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001250 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001251 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001252
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001253 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001254 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001255
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001256 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001257
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001258 if (chan->remote_max_tx &&
1259 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001260 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001261 return;
1262 }
1263
1264 tx_skb = skb_clone(skb, GFP_ATOMIC);
1265 bt_cb(skb)->retries++;
1266 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001267 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001268
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001269 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001270 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001271 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001272 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001273
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001274 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001275 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001276
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001277 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1278
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001279 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001280 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1281 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1282 }
1283
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001284 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001285}
1286
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001287int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001288{
1289 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001290 struct sock *sk = chan->sk;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001291 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001292 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001293
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001294 if (sk->sk_state != BT_CONNECTED)
1295 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001296
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001297 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001298
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001299 if (chan->remote_max_tx &&
1300 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001301 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001302 break;
1303 }
1304
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001305 tx_skb = skb_clone(skb, GFP_ATOMIC);
1306
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001307 bt_cb(skb)->retries++;
1308
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001309 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001310 control &= L2CAP_CTRL_SAR;
1311
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001312 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001313 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001314 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001315 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001316 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1317 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001318 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1319
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001320
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001321 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001322 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1323 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1324 }
1325
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001326 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001327
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001328 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001329
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001330 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1331 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001332
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301333 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001334 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301335
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001336 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001337
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001338 if (skb_queue_is_last(&chan->tx_q, skb))
1339 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001340 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001341 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001342
1343 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001344 }
1345
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001346 return nsent;
1347}
1348
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001349static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001350{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001351 int ret;
1352
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001353 if (!skb_queue_empty(&chan->tx_q))
1354 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001355
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001356 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001357 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001358 return ret;
1359}
1360
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001361static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001362{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001363 u16 control = 0;
1364
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001365 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001366
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001367 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001368 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001369 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1370 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001371 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001372 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001373
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001374 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001375 return;
1376
1377 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001378 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001379}
1380
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001381static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001382{
1383 struct srej_list *tail;
1384 u16 control;
1385
1386 control = L2CAP_SUPER_SELECT_REJECT;
1387 control |= L2CAP_CTRL_FINAL;
1388
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001389 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001390 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1391
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001392 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001393}
1394
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001395static 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 -07001396{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001397 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001398 struct sk_buff **frag;
1399 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001401 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001402 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403
1404 sent += count;
1405 len -= count;
1406
1407 /* Continuation fragments (no L2CAP header) */
1408 frag = &skb_shinfo(skb)->frag_list;
1409 while (len) {
1410 count = min_t(unsigned int, conn->mtu, len);
1411
1412 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1413 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001414 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001415 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1416 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417
1418 sent += count;
1419 len -= count;
1420
1421 frag = &(*frag)->next;
1422 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423
1424 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001425}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001427struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001428{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001429 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001430 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001431 struct sk_buff *skb;
1432 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1433 struct l2cap_hdr *lh;
1434
1435 BT_DBG("sk %p len %d", sk, (int)len);
1436
1437 count = min_t(unsigned int, (conn->mtu - hlen), len);
1438 skb = bt_skb_send_alloc(sk, count + hlen,
1439 msg->msg_flags & MSG_DONTWAIT, &err);
1440 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001441 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001442
1443 /* Create L2CAP header */
1444 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001445 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001446 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001447 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001448
1449 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1450 if (unlikely(err < 0)) {
1451 kfree_skb(skb);
1452 return ERR_PTR(err);
1453 }
1454 return skb;
1455}
1456
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001457struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001458{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001459 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001460 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001461 struct sk_buff *skb;
1462 int err, count, hlen = L2CAP_HDR_SIZE;
1463 struct l2cap_hdr *lh;
1464
1465 BT_DBG("sk %p len %d", sk, (int)len);
1466
1467 count = min_t(unsigned int, (conn->mtu - hlen), len);
1468 skb = bt_skb_send_alloc(sk, count + hlen,
1469 msg->msg_flags & MSG_DONTWAIT, &err);
1470 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001471 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001472
1473 /* Create L2CAP header */
1474 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001475 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001476 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1477
1478 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1479 if (unlikely(err < 0)) {
1480 kfree_skb(skb);
1481 return ERR_PTR(err);
1482 }
1483 return skb;
1484}
1485
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001486struct 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 -03001487{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001488 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001489 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001490 struct sk_buff *skb;
1491 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1492 struct l2cap_hdr *lh;
1493
1494 BT_DBG("sk %p len %d", sk, (int)len);
1495
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001496 if (!conn)
1497 return ERR_PTR(-ENOTCONN);
1498
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001499 if (sdulen)
1500 hlen += 2;
1501
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001502 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001503 hlen += 2;
1504
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001505 count = min_t(unsigned int, (conn->mtu - hlen), len);
1506 skb = bt_skb_send_alloc(sk, count + hlen,
1507 msg->msg_flags & MSG_DONTWAIT, &err);
1508 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001509 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001510
1511 /* Create L2CAP header */
1512 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001513 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001514 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1515 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001516 if (sdulen)
1517 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001518
1519 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1520 if (unlikely(err < 0)) {
1521 kfree_skb(skb);
1522 return ERR_PTR(err);
1523 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001524
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001525 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001526 put_unaligned_le16(0, skb_put(skb, 2));
1527
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001528 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001529 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530}
1531
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001532int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001533{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001534 struct sk_buff *skb;
1535 struct sk_buff_head sar_queue;
1536 u16 control;
1537 size_t size = 0;
1538
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001539 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001540 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001541 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001542 if (IS_ERR(skb))
1543 return PTR_ERR(skb);
1544
1545 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001546 len -= chan->remote_mps;
1547 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001548
1549 while (len > 0) {
1550 size_t buflen;
1551
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001552 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001553 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001554 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001555 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001556 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001557 buflen = len;
1558 }
1559
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001560 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001561 if (IS_ERR(skb)) {
1562 skb_queue_purge(&sar_queue);
1563 return PTR_ERR(skb);
1564 }
1565
1566 __skb_queue_tail(&sar_queue, skb);
1567 len -= buflen;
1568 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001569 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001570 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1571 if (chan->tx_send_head == NULL)
1572 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001573
1574 return size;
1575}
1576
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001577int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1578{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001579 struct sk_buff *skb;
1580 u16 control;
1581 int err;
1582
1583 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001584 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001585 skb = l2cap_create_connless_pdu(chan, msg, len);
1586 if (IS_ERR(skb))
1587 return PTR_ERR(skb);
1588
1589 l2cap_do_send(chan, skb);
1590 return len;
1591 }
1592
1593 switch (chan->mode) {
1594 case L2CAP_MODE_BASIC:
1595 /* Check outgoing MTU */
1596 if (len > chan->omtu)
1597 return -EMSGSIZE;
1598
1599 /* Create a basic PDU */
1600 skb = l2cap_create_basic_pdu(chan, msg, len);
1601 if (IS_ERR(skb))
1602 return PTR_ERR(skb);
1603
1604 l2cap_do_send(chan, skb);
1605 err = len;
1606 break;
1607
1608 case L2CAP_MODE_ERTM:
1609 case L2CAP_MODE_STREAMING:
1610 /* Entire SDU fits into one PDU */
1611 if (len <= chan->remote_mps) {
1612 control = L2CAP_SDU_UNSEGMENTED;
1613 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1614 0);
1615 if (IS_ERR(skb))
1616 return PTR_ERR(skb);
1617
1618 __skb_queue_tail(&chan->tx_q, skb);
1619
1620 if (chan->tx_send_head == NULL)
1621 chan->tx_send_head = skb;
1622
1623 } else {
1624 /* Segment SDU into multiples PDUs */
1625 err = l2cap_sar_segment_sdu(chan, msg, len);
1626 if (err < 0)
1627 return err;
1628 }
1629
1630 if (chan->mode == L2CAP_MODE_STREAMING) {
1631 l2cap_streaming_send(chan);
1632 err = len;
1633 break;
1634 }
1635
1636 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
1637 (chan->conn_state & L2CAP_CONN_WAIT_F)) {
1638 err = len;
1639 break;
1640 }
1641
1642 err = l2cap_ertm_send(chan);
1643 if (err >= 0)
1644 err = len;
1645
1646 break;
1647
1648 default:
1649 BT_DBG("bad state %1.1x", chan->mode);
1650 err = -EBADFD;
1651 }
1652
1653 return err;
1654}
1655
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656static void l2cap_chan_ready(struct sock *sk)
1657{
1658 struct sock *parent = bt_sk(sk)->parent;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001659 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660
1661 BT_DBG("sk %p, parent %p", sk, parent);
1662
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001663 chan->conf_state = 0;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03001664 l2cap_chan_clear_timer(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665
1666 if (!parent) {
1667 /* Outgoing channel.
1668 * Wake up socket sleeping on connect.
1669 */
1670 sk->sk_state = BT_CONNECTED;
1671 sk->sk_state_change(sk);
1672 } else {
1673 /* Incoming channel.
1674 * Wake up socket sleeping on accept.
1675 */
1676 parent->sk_data_ready(parent, 0);
1677 }
1678}
1679
1680/* Copy frame to all raw sockets on that connection */
1681static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1682{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001684 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685
1686 BT_DBG("conn %p", conn);
1687
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001688 read_lock(&conn->chan_lock);
1689 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001690 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001691 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 continue;
1693
1694 /* Don't send frame to the socket it came from */
1695 if (skb->sk == sk)
1696 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001697 nskb = skb_clone(skb, GFP_ATOMIC);
1698 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 continue;
1700
1701 if (sock_queue_rcv_skb(sk, nskb))
1702 kfree_skb(nskb);
1703 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001704 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705}
1706
1707/* ---- L2CAP signalling commands ---- */
1708static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1709 u8 code, u8 ident, u16 dlen, void *data)
1710{
1711 struct sk_buff *skb, **frag;
1712 struct l2cap_cmd_hdr *cmd;
1713 struct l2cap_hdr *lh;
1714 int len, count;
1715
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001716 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1717 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718
1719 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1720 count = min_t(unsigned int, conn->mtu, len);
1721
1722 skb = bt_skb_alloc(count, GFP_ATOMIC);
1723 if (!skb)
1724 return NULL;
1725
1726 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001727 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001728
1729 if (conn->hcon->type == LE_LINK)
1730 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1731 else
1732 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733
1734 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1735 cmd->code = code;
1736 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001737 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738
1739 if (dlen) {
1740 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1741 memcpy(skb_put(skb, count), data, count);
1742 data += count;
1743 }
1744
1745 len -= skb->len;
1746
1747 /* Continuation fragments (no L2CAP header) */
1748 frag = &skb_shinfo(skb)->frag_list;
1749 while (len) {
1750 count = min_t(unsigned int, conn->mtu, len);
1751
1752 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1753 if (!*frag)
1754 goto fail;
1755
1756 memcpy(skb_put(*frag, count), data, count);
1757
1758 len -= count;
1759 data += count;
1760
1761 frag = &(*frag)->next;
1762 }
1763
1764 return skb;
1765
1766fail:
1767 kfree_skb(skb);
1768 return NULL;
1769}
1770
1771static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1772{
1773 struct l2cap_conf_opt *opt = *ptr;
1774 int len;
1775
1776 len = L2CAP_CONF_OPT_SIZE + opt->len;
1777 *ptr += len;
1778
1779 *type = opt->type;
1780 *olen = opt->len;
1781
1782 switch (opt->len) {
1783 case 1:
1784 *val = *((u8 *) opt->val);
1785 break;
1786
1787 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001788 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 break;
1790
1791 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001792 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 break;
1794
1795 default:
1796 *val = (unsigned long) opt->val;
1797 break;
1798 }
1799
1800 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1801 return len;
1802}
1803
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1805{
1806 struct l2cap_conf_opt *opt = *ptr;
1807
1808 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1809
1810 opt->type = type;
1811 opt->len = len;
1812
1813 switch (len) {
1814 case 1:
1815 *((u8 *) opt->val) = val;
1816 break;
1817
1818 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001819 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820 break;
1821
1822 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001823 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824 break;
1825
1826 default:
1827 memcpy(opt->val, (void *) val, len);
1828 break;
1829 }
1830
1831 *ptr += L2CAP_CONF_OPT_SIZE + len;
1832}
1833
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001834static void l2cap_ack_timeout(unsigned long arg)
1835{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001836 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001837
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001838 bh_lock_sock(chan->sk);
1839 l2cap_send_ack(chan);
1840 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001841}
1842
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001843static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001844{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001845 struct sock *sk = chan->sk;
1846
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001847 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001848 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001849 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001850 chan->num_acked = 0;
1851 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001852
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001853 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1854 (unsigned long) chan);
1855 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1856 (unsigned long) chan);
1857 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001858
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001859 skb_queue_head_init(&chan->srej_q);
1860 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001861
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001862 INIT_LIST_HEAD(&chan->srej_l);
1863
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001864 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001865
1866 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001867}
1868
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001869static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1870{
1871 switch (mode) {
1872 case L2CAP_MODE_STREAMING:
1873 case L2CAP_MODE_ERTM:
1874 if (l2cap_mode_supported(mode, remote_feat_mask))
1875 return mode;
1876 /* fall through */
1877 default:
1878 return L2CAP_MODE_BASIC;
1879 }
1880}
1881
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001882static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001885 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 void *ptr = req->data;
1887
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001888 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001890 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001891 goto done;
1892
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001893 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001894 case L2CAP_MODE_STREAMING:
1895 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001896 if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001897 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001898
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001899 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001900 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001901 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001902 break;
1903 }
1904
1905done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001906 if (chan->imtu != L2CAP_DEFAULT_MTU)
1907 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001908
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001909 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001910 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001911 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1912 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001913 break;
1914
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001915 rfc.mode = L2CAP_MODE_BASIC;
1916 rfc.txwin_size = 0;
1917 rfc.max_transmit = 0;
1918 rfc.retrans_timeout = 0;
1919 rfc.monitor_timeout = 0;
1920 rfc.max_pdu_size = 0;
1921
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001922 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1923 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001924 break;
1925
1926 case L2CAP_MODE_ERTM:
1927 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001928 rfc.txwin_size = chan->tx_win;
1929 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001930 rfc.retrans_timeout = 0;
1931 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001932 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001933 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1934 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001935
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001936 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1937 (unsigned long) &rfc);
1938
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001939 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001940 break;
1941
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001942 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001943 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001944 chan->fcs = L2CAP_FCS_NONE;
1945 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001946 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001947 break;
1948
1949 case L2CAP_MODE_STREAMING:
1950 rfc.mode = L2CAP_MODE_STREAMING;
1951 rfc.txwin_size = 0;
1952 rfc.max_transmit = 0;
1953 rfc.retrans_timeout = 0;
1954 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001955 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001956 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1957 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001958
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001959 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1960 (unsigned long) &rfc);
1961
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001962 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001963 break;
1964
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001965 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001966 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001967 chan->fcs = L2CAP_FCS_NONE;
1968 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001969 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001970 break;
1971 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001973 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001974 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975
1976 return ptr - data;
1977}
1978
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001979static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001981 struct l2cap_conf_rsp *rsp = data;
1982 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001983 void *req = chan->conf_req;
1984 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001985 int type, hint, olen;
1986 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001987 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001988 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001989 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001991 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001992
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001993 while (len >= L2CAP_CONF_OPT_SIZE) {
1994 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001996 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001997 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001998
1999 switch (type) {
2000 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002001 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002002 break;
2003
2004 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002005 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002006 break;
2007
2008 case L2CAP_CONF_QOS:
2009 break;
2010
Marcel Holtmann6464f352007-10-20 13:39:51 +02002011 case L2CAP_CONF_RFC:
2012 if (olen == sizeof(rfc))
2013 memcpy(&rfc, (void *) val, olen);
2014 break;
2015
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002016 case L2CAP_CONF_FCS:
2017 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002018 chan->conf_state |= L2CAP_CONF_NO_FCS_RECV;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002019
2020 break;
2021
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002022 default:
2023 if (hint)
2024 break;
2025
2026 result = L2CAP_CONF_UNKNOWN;
2027 *((u8 *) ptr++) = type;
2028 break;
2029 }
2030 }
2031
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002032 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002033 goto done;
2034
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002035 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002036 case L2CAP_MODE_STREAMING:
2037 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002038 if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002039 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002040 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002041 break;
2042 }
2043
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002044 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002045 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002046
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002047 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002048 }
2049
2050done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002051 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002052 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002053 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002054
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002055 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002056 return -ECONNREFUSED;
2057
2058 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2059 sizeof(rfc), (unsigned long) &rfc);
2060 }
2061
2062
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002063 if (result == L2CAP_CONF_SUCCESS) {
2064 /* Configure output options and let the other side know
2065 * which ones we don't like. */
2066
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002067 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2068 result = L2CAP_CONF_UNACCEPT;
2069 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002070 chan->omtu = mtu;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002071 chan->conf_state |= L2CAP_CONF_MTU_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002072 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002073 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002074
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002075 switch (rfc.mode) {
2076 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002077 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002078 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002079 break;
2080
2081 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002082 chan->remote_tx_win = rfc.txwin_size;
2083 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002084
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002085 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2086 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002087
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002088 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002089
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002090 rfc.retrans_timeout =
2091 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2092 rfc.monitor_timeout =
2093 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002094
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002095 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002096
2097 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2098 sizeof(rfc), (unsigned long) &rfc);
2099
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002100 break;
2101
2102 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002103 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2104 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002105
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002106 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002107
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002108 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002109
2110 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2111 sizeof(rfc), (unsigned long) &rfc);
2112
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002113 break;
2114
2115 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002116 result = L2CAP_CONF_UNACCEPT;
2117
2118 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002119 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002120 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002121
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002122 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002123 chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002124 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002125 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002126 rsp->result = cpu_to_le16(result);
2127 rsp->flags = cpu_to_le16(0x0000);
2128
2129 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130}
2131
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002132static 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 -03002133{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002134 struct l2cap_conf_req *req = data;
2135 void *ptr = req->data;
2136 int type, olen;
2137 unsigned long val;
2138 struct l2cap_conf_rfc rfc;
2139
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002140 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002141
2142 while (len >= L2CAP_CONF_OPT_SIZE) {
2143 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2144
2145 switch (type) {
2146 case L2CAP_CONF_MTU:
2147 if (val < L2CAP_DEFAULT_MIN_MTU) {
2148 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002149 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002150 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002151 chan->imtu = val;
2152 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002153 break;
2154
2155 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002156 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002157 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002158 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002159 break;
2160
2161 case L2CAP_CONF_RFC:
2162 if (olen == sizeof(rfc))
2163 memcpy(&rfc, (void *)val, olen);
2164
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002165 if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002166 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002167 return -ECONNREFUSED;
2168
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002169 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002170
2171 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2172 sizeof(rfc), (unsigned long) &rfc);
2173 break;
2174 }
2175 }
2176
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002177 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002178 return -ECONNREFUSED;
2179
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002180 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002181
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002182 if (*result == L2CAP_CONF_SUCCESS) {
2183 switch (rfc.mode) {
2184 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002185 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2186 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2187 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002188 break;
2189 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002190 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002191 }
2192 }
2193
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002194 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002195 req->flags = cpu_to_le16(0x0000);
2196
2197 return ptr - data;
2198}
2199
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002200static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201{
2202 struct l2cap_conf_rsp *rsp = data;
2203 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002205 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002207 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002208 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002209 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210
2211 return ptr - data;
2212}
2213
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002214void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002215{
2216 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002217 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002218 u8 buf[128];
2219
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002220 rsp.scid = cpu_to_le16(chan->dcid);
2221 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002222 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2223 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2224 l2cap_send_cmd(conn, chan->ident,
2225 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2226
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002227 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002228 return;
2229
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002230 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002231 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2232 l2cap_build_conf_req(chan, buf), buf);
2233 chan->num_conf_req++;
2234}
2235
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002236static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002237{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002238 int type, olen;
2239 unsigned long val;
2240 struct l2cap_conf_rfc rfc;
2241
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002242 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002243
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002244 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002245 return;
2246
2247 while (len >= L2CAP_CONF_OPT_SIZE) {
2248 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2249
2250 switch (type) {
2251 case L2CAP_CONF_RFC:
2252 if (olen == sizeof(rfc))
2253 memcpy(&rfc, (void *)val, olen);
2254 goto done;
2255 }
2256 }
2257
2258done:
2259 switch (rfc.mode) {
2260 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002261 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2262 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2263 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002264 break;
2265 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002266 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002267 }
2268}
2269
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002270static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2271{
2272 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2273
2274 if (rej->reason != 0x0000)
2275 return 0;
2276
2277 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2278 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002279 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002280
2281 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002282 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002283
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002284 l2cap_conn_start(conn);
2285 }
2286
2287 return 0;
2288}
2289
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2291{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2293 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002294 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002295 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002296 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297
2298 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002299 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300
2301 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2302
2303 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002304 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2305 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 result = L2CAP_CR_BAD_PSM;
2307 goto sendresp;
2308 }
2309
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002310 parent = pchan->sk;
2311
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002312 bh_lock_sock(parent);
2313
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002314 /* Check if the ACL is secure enough (if not SDP) */
2315 if (psm != cpu_to_le16(0x0001) &&
2316 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002317 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002318 result = L2CAP_CR_SEC_BLOCK;
2319 goto response;
2320 }
2321
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 result = L2CAP_CR_NO_MEM;
2323
2324 /* Check for backlog size */
2325 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002326 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 goto response;
2328 }
2329
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002330 chan = pchan->ops->new_connection(pchan->data);
2331 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 goto response;
2333
Gustavo F. Padovan80808e42011-05-16 17:24:37 -03002334 sk = chan->sk;
2335
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002336 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337
2338 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002339 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2340 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 sock_set_flag(sk, SOCK_ZAPPED);
2342 l2cap_sock_kill(sk);
2343 goto response;
2344 }
2345
2346 hci_conn_hold(conn->hcon);
2347
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 bacpy(&bt_sk(sk)->src, conn->src);
2349 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002350 chan->psm = psm;
2351 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002353 bt_accept_enqueue(parent, sk);
2354
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002355 __l2cap_chan_add(conn, chan);
2356
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002357 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002359 l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002361 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362
Marcel Holtmann984947d2009-02-06 23:35:19 +01002363 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002364 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002365 if (bt_sk(sk)->defer_setup) {
2366 sk->sk_state = BT_CONNECT2;
2367 result = L2CAP_CR_PEND;
2368 status = L2CAP_CS_AUTHOR_PEND;
2369 parent->sk_data_ready(parent, 0);
2370 } else {
2371 sk->sk_state = BT_CONFIG;
2372 result = L2CAP_CR_SUCCESS;
2373 status = L2CAP_CS_NO_INFO;
2374 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002375 } else {
2376 sk->sk_state = BT_CONNECT2;
2377 result = L2CAP_CR_PEND;
2378 status = L2CAP_CS_AUTHEN_PEND;
2379 }
2380 } else {
2381 sk->sk_state = BT_CONNECT2;
2382 result = L2CAP_CR_PEND;
2383 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384 }
2385
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002386 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387
2388response:
2389 bh_unlock_sock(parent);
2390
2391sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002392 rsp.scid = cpu_to_le16(scid);
2393 rsp.dcid = cpu_to_le16(dcid);
2394 rsp.result = cpu_to_le16(result);
2395 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002397
2398 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2399 struct l2cap_info_req info;
2400 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2401
2402 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2403 conn->info_ident = l2cap_get_ident(conn);
2404
2405 mod_timer(&conn->info_timer, jiffies +
2406 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2407
2408 l2cap_send_cmd(conn, conn->info_ident,
2409 L2CAP_INFO_REQ, sizeof(info), &info);
2410 }
2411
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002412 if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002413 result == L2CAP_CR_SUCCESS) {
2414 u8 buf[128];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002415 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002416 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002417 l2cap_build_conf_req(chan, buf), buf);
2418 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002419 }
2420
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 return 0;
2422}
2423
2424static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2425{
2426 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2427 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002428 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 struct sock *sk;
2430 u8 req[128];
2431
2432 scid = __le16_to_cpu(rsp->scid);
2433 dcid = __le16_to_cpu(rsp->dcid);
2434 result = __le16_to_cpu(rsp->result);
2435 status = __le16_to_cpu(rsp->status);
2436
2437 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2438
2439 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002440 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002441 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002442 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002444 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002445 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002446 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 }
2448
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002449 sk = chan->sk;
2450
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 switch (result) {
2452 case L2CAP_CR_SUCCESS:
2453 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002454 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002455 chan->dcid = dcid;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002456 chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002457
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002458 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002459 break;
2460
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002461 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002462
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002464 l2cap_build_conf_req(chan, req), req);
2465 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466 break;
2467
2468 case L2CAP_CR_PEND:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002469 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 break;
2471
2472 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002473 /* don't delete l2cap channel if sk is owned by user */
2474 if (sock_owned_by_user(sk)) {
2475 sk->sk_state = BT_DISCONN;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002476 l2cap_chan_clear_timer(chan);
2477 l2cap_chan_set_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002478 break;
2479 }
2480
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002481 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482 break;
2483 }
2484
2485 bh_unlock_sock(sk);
2486 return 0;
2487}
2488
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002489static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002490{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002491 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
2492
Mat Martineau8c462b62010-08-24 15:35:42 -07002493 /* FCS is enabled only in ERTM or streaming mode, if one or both
2494 * sides request it.
2495 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002496 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002497 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002498 else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002499 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002500}
2501
Al Viro88219a02007-07-29 00:17:25 -07002502static 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 -07002503{
2504 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2505 u16 dcid, flags;
2506 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002507 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002509 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510
2511 dcid = __le16_to_cpu(req->dcid);
2512 flags = __le16_to_cpu(req->flags);
2513
2514 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2515
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002516 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002517 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518 return -ENOENT;
2519
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002520 sk = chan->sk;
2521
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002522 if (sk->sk_state != BT_CONFIG) {
2523 struct l2cap_cmd_rej rej;
2524
2525 rej.reason = cpu_to_le16(0x0002);
2526 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2527 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002528 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002529 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002530
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002531 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002532 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002533 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002534 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002535 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002536 L2CAP_CONF_REJECT, flags), rsp);
2537 goto unlock;
2538 }
2539
2540 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002541 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2542 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543
2544 if (flags & 0x0001) {
2545 /* Incomplete config. Send empty response. */
2546 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002547 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002548 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549 goto unlock;
2550 }
2551
2552 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002553 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002554 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002555 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002557 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002559 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002560 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002561
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002562 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002563 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002564
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002565 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002566 goto unlock;
2567
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002568 if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002569 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002570
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002572
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002573 chan->next_tx_seq = 0;
2574 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002575 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002576 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002577 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002578
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002580 goto unlock;
2581 }
2582
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002583 if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002584 u8 buf[64];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002585 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002587 l2cap_build_conf_req(chan, buf), buf);
2588 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589 }
2590
2591unlock:
2592 bh_unlock_sock(sk);
2593 return 0;
2594}
2595
2596static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2597{
2598 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2599 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002600 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002602 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603
2604 scid = __le16_to_cpu(rsp->scid);
2605 flags = __le16_to_cpu(rsp->flags);
2606 result = __le16_to_cpu(rsp->result);
2607
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002608 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2609 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002611 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002612 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 return 0;
2614
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002615 sk = chan->sk;
2616
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617 switch (result) {
2618 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002619 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 break;
2621
2622 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002623 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002624 char req[64];
2625
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002626 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002627 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002628 goto done;
2629 }
2630
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002631 /* throw out any old stored conf requests */
2632 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002633 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2634 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002635 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002636 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002637 goto done;
2638 }
2639
2640 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2641 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002642 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002643 if (result != L2CAP_CONF_SUCCESS)
2644 goto done;
2645 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 }
2647
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002648 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002649 sk->sk_err = ECONNRESET;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002650 l2cap_chan_set_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002651 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652 goto done;
2653 }
2654
2655 if (flags & 0x01)
2656 goto done;
2657
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002658 chan->conf_state |= L2CAP_CONF_INPUT_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002660 if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002661 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002662
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002664 chan->next_tx_seq = 0;
2665 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002666 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002667 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002668 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002669
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670 l2cap_chan_ready(sk);
2671 }
2672
2673done:
2674 bh_unlock_sock(sk);
2675 return 0;
2676}
2677
2678static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2679{
2680 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2681 struct l2cap_disconn_rsp rsp;
2682 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002683 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 struct sock *sk;
2685
2686 scid = __le16_to_cpu(req->scid);
2687 dcid = __le16_to_cpu(req->dcid);
2688
2689 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2690
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002691 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002692 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693 return 0;
2694
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002695 sk = chan->sk;
2696
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002697 rsp.dcid = cpu_to_le16(chan->scid);
2698 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2700
2701 sk->sk_shutdown = SHUTDOWN_MASK;
2702
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002703 /* don't delete l2cap channel if sk is owned by user */
2704 if (sock_owned_by_user(sk)) {
2705 sk->sk_state = BT_DISCONN;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002706 l2cap_chan_clear_timer(chan);
2707 l2cap_chan_set_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002708 bh_unlock_sock(sk);
2709 return 0;
2710 }
2711
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002712 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713 bh_unlock_sock(sk);
2714
2715 l2cap_sock_kill(sk);
2716 return 0;
2717}
2718
2719static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2720{
2721 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2722 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002723 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 struct sock *sk;
2725
2726 scid = __le16_to_cpu(rsp->scid);
2727 dcid = __le16_to_cpu(rsp->dcid);
2728
2729 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2730
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002731 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002732 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 return 0;
2734
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002735 sk = chan->sk;
2736
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002737 /* don't delete l2cap channel if sk is owned by user */
2738 if (sock_owned_by_user(sk)) {
2739 sk->sk_state = BT_DISCONN;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002740 l2cap_chan_clear_timer(chan);
2741 l2cap_chan_set_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002742 bh_unlock_sock(sk);
2743 return 0;
2744 }
2745
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002746 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747 bh_unlock_sock(sk);
2748
2749 l2cap_sock_kill(sk);
2750 return 0;
2751}
2752
2753static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2754{
2755 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756 u16 type;
2757
2758 type = __le16_to_cpu(req->type);
2759
2760 BT_DBG("type 0x%4.4x", type);
2761
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002762 if (type == L2CAP_IT_FEAT_MASK) {
2763 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002764 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002765 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2766 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2767 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002768 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002769 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2770 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002771 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002772 l2cap_send_cmd(conn, cmd->ident,
2773 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002774 } else if (type == L2CAP_IT_FIXED_CHAN) {
2775 u8 buf[12];
2776 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2777 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2778 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2779 memcpy(buf + 4, l2cap_fixed_chan, 8);
2780 l2cap_send_cmd(conn, cmd->ident,
2781 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002782 } else {
2783 struct l2cap_info_rsp rsp;
2784 rsp.type = cpu_to_le16(type);
2785 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2786 l2cap_send_cmd(conn, cmd->ident,
2787 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2788 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789
2790 return 0;
2791}
2792
2793static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2794{
2795 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2796 u16 type, result;
2797
2798 type = __le16_to_cpu(rsp->type);
2799 result = __le16_to_cpu(rsp->result);
2800
2801 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2802
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002803 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2804 if (cmd->ident != conn->info_ident ||
2805 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2806 return 0;
2807
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002808 del_timer(&conn->info_timer);
2809
Ville Tervoadb08ed2010-08-04 09:43:33 +03002810 if (result != L2CAP_IR_SUCCESS) {
2811 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2812 conn->info_ident = 0;
2813
2814 l2cap_conn_start(conn);
2815
2816 return 0;
2817 }
2818
Marcel Holtmann984947d2009-02-06 23:35:19 +01002819 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002820 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002821
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002822 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002823 struct l2cap_info_req req;
2824 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2825
2826 conn->info_ident = l2cap_get_ident(conn);
2827
2828 l2cap_send_cmd(conn, conn->info_ident,
2829 L2CAP_INFO_REQ, sizeof(req), &req);
2830 } else {
2831 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2832 conn->info_ident = 0;
2833
2834 l2cap_conn_start(conn);
2835 }
2836 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002837 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002838 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002839
2840 l2cap_conn_start(conn);
2841 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002842
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843 return 0;
2844}
2845
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002846static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002847 u16 to_multiplier)
2848{
2849 u16 max_latency;
2850
2851 if (min > max || min < 6 || max > 3200)
2852 return -EINVAL;
2853
2854 if (to_multiplier < 10 || to_multiplier > 3200)
2855 return -EINVAL;
2856
2857 if (max >= to_multiplier * 8)
2858 return -EINVAL;
2859
2860 max_latency = (to_multiplier * 8 / max) - 1;
2861 if (latency > 499 || latency > max_latency)
2862 return -EINVAL;
2863
2864 return 0;
2865}
2866
2867static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2868 struct l2cap_cmd_hdr *cmd, u8 *data)
2869{
2870 struct hci_conn *hcon = conn->hcon;
2871 struct l2cap_conn_param_update_req *req;
2872 struct l2cap_conn_param_update_rsp rsp;
2873 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002874 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002875
2876 if (!(hcon->link_mode & HCI_LM_MASTER))
2877 return -EINVAL;
2878
2879 cmd_len = __le16_to_cpu(cmd->len);
2880 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2881 return -EPROTO;
2882
2883 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002884 min = __le16_to_cpu(req->min);
2885 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002886 latency = __le16_to_cpu(req->latency);
2887 to_multiplier = __le16_to_cpu(req->to_multiplier);
2888
2889 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2890 min, max, latency, to_multiplier);
2891
2892 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002893
2894 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2895 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002896 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2897 else
2898 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2899
2900 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2901 sizeof(rsp), &rsp);
2902
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002903 if (!err)
2904 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2905
Claudio Takahaside731152011-02-11 19:28:55 -02002906 return 0;
2907}
2908
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002909static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2910 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2911{
2912 int err = 0;
2913
2914 switch (cmd->code) {
2915 case L2CAP_COMMAND_REJ:
2916 l2cap_command_rej(conn, cmd, data);
2917 break;
2918
2919 case L2CAP_CONN_REQ:
2920 err = l2cap_connect_req(conn, cmd, data);
2921 break;
2922
2923 case L2CAP_CONN_RSP:
2924 err = l2cap_connect_rsp(conn, cmd, data);
2925 break;
2926
2927 case L2CAP_CONF_REQ:
2928 err = l2cap_config_req(conn, cmd, cmd_len, data);
2929 break;
2930
2931 case L2CAP_CONF_RSP:
2932 err = l2cap_config_rsp(conn, cmd, data);
2933 break;
2934
2935 case L2CAP_DISCONN_REQ:
2936 err = l2cap_disconnect_req(conn, cmd, data);
2937 break;
2938
2939 case L2CAP_DISCONN_RSP:
2940 err = l2cap_disconnect_rsp(conn, cmd, data);
2941 break;
2942
2943 case L2CAP_ECHO_REQ:
2944 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2945 break;
2946
2947 case L2CAP_ECHO_RSP:
2948 break;
2949
2950 case L2CAP_INFO_REQ:
2951 err = l2cap_information_req(conn, cmd, data);
2952 break;
2953
2954 case L2CAP_INFO_RSP:
2955 err = l2cap_information_rsp(conn, cmd, data);
2956 break;
2957
2958 default:
2959 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2960 err = -EINVAL;
2961 break;
2962 }
2963
2964 return err;
2965}
2966
2967static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2968 struct l2cap_cmd_hdr *cmd, u8 *data)
2969{
2970 switch (cmd->code) {
2971 case L2CAP_COMMAND_REJ:
2972 return 0;
2973
2974 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002975 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002976
2977 case L2CAP_CONN_PARAM_UPDATE_RSP:
2978 return 0;
2979
2980 default:
2981 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2982 return -EINVAL;
2983 }
2984}
2985
2986static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2987 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988{
2989 u8 *data = skb->data;
2990 int len = skb->len;
2991 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002992 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993
2994 l2cap_raw_recv(conn, skb);
2995
2996 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002997 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2999 data += L2CAP_CMD_HDR_SIZE;
3000 len -= L2CAP_CMD_HDR_SIZE;
3001
Al Viro88219a02007-07-29 00:17:25 -07003002 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003
Al Viro88219a02007-07-29 00:17:25 -07003004 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 -07003005
Al Viro88219a02007-07-29 00:17:25 -07003006 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 BT_DBG("corrupted command");
3008 break;
3009 }
3010
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003011 if (conn->hcon->type == LE_LINK)
3012 err = l2cap_le_sig_cmd(conn, &cmd, data);
3013 else
3014 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015
3016 if (err) {
3017 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003018
3019 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020
3021 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003022 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3024 }
3025
Al Viro88219a02007-07-29 00:17:25 -07003026 data += cmd_len;
3027 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028 }
3029
3030 kfree_skb(skb);
3031}
3032
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003033static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003034{
3035 u16 our_fcs, rcv_fcs;
3036 int hdr_size = L2CAP_HDR_SIZE + 2;
3037
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003038 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003039 skb_trim(skb, skb->len - 2);
3040 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3041 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3042
3043 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003044 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003045 }
3046 return 0;
3047}
3048
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003049static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003050{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003051 u16 control = 0;
3052
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003053 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003054
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003055 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003056
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003057 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003058 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003059 l2cap_send_sframe(chan, control);
3060 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003061 }
3062
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003063 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
3064 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003065
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003066 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003067
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003068 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003069 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003070 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003071 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003072 }
3073}
3074
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003075static 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 -03003076{
3077 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003078 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003079
3080 bt_cb(skb)->tx_seq = tx_seq;
3081 bt_cb(skb)->sar = sar;
3082
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003083 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003084 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003085 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003086 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003087 }
3088
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003089 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003090 if (tx_seq_offset < 0)
3091 tx_seq_offset += 64;
3092
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003093 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003094 if (bt_cb(next_skb)->tx_seq == tx_seq)
3095 return -EINVAL;
3096
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003097 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003098 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003099 if (next_tx_seq_offset < 0)
3100 next_tx_seq_offset += 64;
3101
3102 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003103 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003104 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003105 }
3106
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003107 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003108 break;
3109
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003110 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003111
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003112 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003113
3114 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003115}
3116
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003117static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003118{
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003119 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003120 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003121
3122 switch (control & L2CAP_CTRL_SAR) {
3123 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003124 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003125 goto drop;
3126
Ruiyi Zhang224f8af2011-05-13 13:07:52 +08003127 return sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003128
3129 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003130 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003131 goto drop;
3132
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003133 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003134
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003135 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003136 goto disconnect;
3137
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003138 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3139 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003140 return -ENOMEM;
3141
3142 /* pull sdu_len bytes only after alloc, because of Local Busy
3143 * condition we have to be sure that this will be executed
3144 * only once, i.e., when alloc does not fail */
3145 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003146
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003147 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003148
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003149 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003150 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003151 break;
3152
3153 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003154 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003155 goto disconnect;
3156
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003157 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003158 goto disconnect;
3159
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003160 chan->partial_sdu_len += skb->len;
3161 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003162 goto drop;
3163
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003164 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003165
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003166 break;
3167
3168 case L2CAP_SDU_END:
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. Padovan525cd182011-03-25 19:43:39 -03003175 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003176 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003177
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003178 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003179 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003180
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003181 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003182 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003183
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003184 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003185 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003186
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003187 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003188 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003189 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003190 return -ENOMEM;
3191 }
3192
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003193 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003194 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003195 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003196 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003197 return err;
3198 }
3199
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003200 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
3201 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003202
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003203 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003204 break;
3205 }
3206
3207 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003208 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003209
3210drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003211 kfree_skb(chan->sdu);
3212 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003213
3214disconnect:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003215 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003216 kfree_skb(skb);
3217 return 0;
3218}
3219
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003220static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003221{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003222 struct sk_buff *skb;
3223 u16 control;
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003224 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003225
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003226 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003227 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003228 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003229 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003230 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003231 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003232 }
3233
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003234 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003235 }
3236
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003237 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003238 goto done;
3239
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003240 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003241 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003242 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003243 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003244
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003245 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003246 __mod_monitor_timer();
3247
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003248 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003249
3250done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003251 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3252 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003253
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003254 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003255
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003256 return 0;
3257}
3258
3259static void l2cap_busy_work(struct work_struct *work)
3260{
3261 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003262 struct l2cap_chan *chan =
3263 container_of(work, struct l2cap_chan, busy_work);
3264 struct sock *sk = chan->sk;
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003265 int n_tries = 0, timeo = HZ/5, err;
3266 struct sk_buff *skb;
3267
3268 lock_sock(sk);
3269
3270 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003271 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003272 set_current_state(TASK_INTERRUPTIBLE);
3273
3274 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3275 err = -EBUSY;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003276 l2cap_send_disconn_req(chan->conn, chan, EBUSY);
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003277 break;
3278 }
3279
3280 if (!timeo)
3281 timeo = HZ/5;
3282
3283 if (signal_pending(current)) {
3284 err = sock_intr_errno(timeo);
3285 break;
3286 }
3287
3288 release_sock(sk);
3289 timeo = schedule_timeout(timeo);
3290 lock_sock(sk);
3291
3292 err = sock_error(sk);
3293 if (err)
3294 break;
3295
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003296 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003297 break;
3298 }
3299
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003300 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003301 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003302
3303 release_sock(sk);
3304}
3305
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003306static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003307{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003308 int sctrl, err;
3309
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003310 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003311 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003312 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003313 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132eb2010-06-21 19:39:50 -03003314
3315
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003316 }
3317
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003318 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003319 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003320 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003321 return err;
3322 }
3323
3324 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003325 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003326
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003327 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003328 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003329 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003330
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003331 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003332 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003333 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003334
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003335 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003336
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003337 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003338
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003339 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003340
3341 return err;
3342}
3343
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003344static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003345{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003346 struct sk_buff *_skb;
3347 int err = -EINVAL;
3348
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003349 /*
3350 * TODO: We have to notify the userland if some data is lost with the
3351 * Streaming Mode.
3352 */
3353
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003354 switch (control & L2CAP_CTRL_SAR) {
3355 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003356 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003357 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003358 break;
3359 }
3360
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003361 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003362 if (!err)
3363 return 0;
3364
3365 break;
3366
3367 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003368 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003369 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003370 break;
3371 }
3372
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003373 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003374 skb_pull(skb, 2);
3375
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003376 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003377 err = -EMSGSIZE;
3378 break;
3379 }
3380
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003381 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3382 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003383 err = -ENOMEM;
3384 break;
3385 }
3386
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003387 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003388
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003389 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003390 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003391 err = 0;
3392 break;
3393
3394 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003395 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003396 break;
3397
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003398 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003399
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003400 chan->partial_sdu_len += skb->len;
3401 if (chan->partial_sdu_len > chan->sdu_len)
3402 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003403 else
3404 err = 0;
3405
3406 break;
3407
3408 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003409 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003410 break;
3411
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003412 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003413
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003414 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003415 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003416
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003417 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003418 goto drop;
3419
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003420 if (chan->partial_sdu_len == chan->sdu_len) {
3421 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003422 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003423 if (err < 0)
3424 kfree_skb(_skb);
3425 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003426 err = 0;
3427
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003428drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003429 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003430 break;
3431 }
3432
3433 kfree_skb(skb);
3434 return err;
3435}
3436
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003437static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003438{
3439 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003440 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003441
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003442 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003443 if (bt_cb(skb)->tx_seq != tx_seq)
3444 break;
3445
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003446 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003447 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003448 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003449 chan->buffer_seq_srej =
3450 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003451 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003452 }
3453}
3454
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003455static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003456{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003457 struct srej_list *l, *tmp;
3458 u16 control;
3459
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003460 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003461 if (l->tx_seq == tx_seq) {
3462 list_del(&l->list);
3463 kfree(l);
3464 return;
3465 }
3466 control = L2CAP_SUPER_SELECT_REJECT;
3467 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003468 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003469 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003470 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003471 }
3472}
3473
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003474static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003475{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003476 struct srej_list *new;
3477 u16 control;
3478
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003479 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003480 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003481 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003482 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003483
3484 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003485 new->tx_seq = chan->expected_tx_seq;
3486 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003487 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003488 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003489 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003490}
3491
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003492static 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 -03003493{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003494 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003495 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003496 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003497 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003498 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003499 int err = 0;
3500
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003501 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3502 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003503
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003504 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003505 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003506 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003507 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003508 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003509 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003510 }
3511
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003512 chan->expected_ack_seq = req_seq;
3513 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003514
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003515 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003516 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003517
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003518 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003519 if (tx_seq_offset < 0)
3520 tx_seq_offset += 64;
3521
3522 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003523 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003524 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003525 goto drop;
3526 }
3527
Mat Martineaue6949282011-06-03 16:21:10 -07003528 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003529 goto drop;
3530
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003531 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003532 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003533
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003534 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003535 struct srej_list, list);
3536 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003537 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003538 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003539
3540 list_del(&first->list);
3541 kfree(first);
3542
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003543 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003544 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003545 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3546 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003547 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003548 }
3549 } else {
3550 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003551
3552 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003553 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003554 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003555
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003556 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003557 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003558 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003559 return 0;
3560 }
3561 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003562 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003563 }
3564 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003565 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003566 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003567 if (expected_tx_seq_offset < 0)
3568 expected_tx_seq_offset += 64;
3569
3570 /* duplicated tx_seq */
3571 if (tx_seq_offset < expected_tx_seq_offset)
3572 goto drop;
3573
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003574 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003575
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003576 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003577
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003578 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003579 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003580
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003581 __skb_queue_head_init(&chan->srej_q);
3582 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003583 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003584
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003585 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003586
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003587 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003588
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003589 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003590 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003591 return 0;
3592
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003593expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003594 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003595
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003596 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003597 bt_cb(skb)->tx_seq = tx_seq;
3598 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003599 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003600 return 0;
3601 }
3602
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003603 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003604 if (err < 0)
3605 return 0;
3606
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003607 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003608 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3609 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003610 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003611 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003612 }
3613
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003614 __mod_ack_timer();
3615
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003616 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3617 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003618 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003619
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003620 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003621
3622drop:
3623 kfree_skb(skb);
3624 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003625}
3626
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003627static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003628{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003629 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003630 rx_control);
3631
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003632 chan->expected_ack_seq = __get_reqseq(rx_control);
3633 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003634
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003635 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003636 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3637 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3638 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003639 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003640 __mod_retrans_timer();
3641
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003642 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3643 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003644 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003645 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003646 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003647
3648 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003649 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003650
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003651 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3652 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003653 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003654 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003655
3656 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003657 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003658 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003659 __mod_retrans_timer();
3660
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003661 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3662 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3663 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003664 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003665 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003666 }
3667}
3668
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003669static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003670{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003671 u8 tx_seq = __get_reqseq(rx_control);
3672
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003673 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003674
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003675 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003676
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003677 chan->expected_ack_seq = tx_seq;
3678 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003679
3680 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003681 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3682 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003683 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003684 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003685 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003686 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003687
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003688 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3689 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003690 }
3691}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003692static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003693{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003694 u8 tx_seq = __get_reqseq(rx_control);
3695
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003696 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003697
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003698 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003699
3700 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003701 chan->expected_ack_seq = tx_seq;
3702 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003703
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003704 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3705 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003706
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003707 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003708
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003709 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003710 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003711 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003712 }
3713 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003714 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003715 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003716 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003717 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003718 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003719 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003720 l2cap_retransmit_one_frame(chan, tx_seq);
3721 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003722 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003723 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003724 }
3725 }
3726}
3727
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003728static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003729{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003730 u8 tx_seq = __get_reqseq(rx_control);
3731
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003732 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003733
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003734 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003735 chan->expected_ack_seq = tx_seq;
3736 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003737
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003738 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003739 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003740
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003741 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003742 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003743 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003744 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003745 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003746 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003747
3748 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003749 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003750 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003751 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003752}
3753
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003754static 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 -03003755{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003756 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003757
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003758 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003759 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003760 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003761 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003762 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003763 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003764 }
3765
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003766 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3767 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003768 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003769 break;
3770
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003771 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003772 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003773 break;
3774
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003775 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003776 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003777 break;
3778
3779 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003780 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003781 break;
3782 }
3783
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003784 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003785 return 0;
3786}
3787
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003788static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3789{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003790 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003791 u16 control;
3792 u8 req_seq;
3793 int len, next_tx_seq_offset, req_seq_offset;
3794
3795 control = get_unaligned_le16(skb->data);
3796 skb_pull(skb, 2);
3797 len = skb->len;
3798
3799 /*
3800 * We can just drop the corrupted I-frame here.
3801 * Receiver will miss it and start proper recovery
3802 * procedures and ask retransmission.
3803 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003804 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003805 goto drop;
3806
3807 if (__is_sar_start(control) && __is_iframe(control))
3808 len -= 2;
3809
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003810 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003811 len -= 2;
3812
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003813 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003814 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003815 goto drop;
3816 }
3817
3818 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003819 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003820 if (req_seq_offset < 0)
3821 req_seq_offset += 64;
3822
3823 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003824 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003825 if (next_tx_seq_offset < 0)
3826 next_tx_seq_offset += 64;
3827
3828 /* check for invalid req-seq */
3829 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003830 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003831 goto drop;
3832 }
3833
3834 if (__is_iframe(control)) {
3835 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003836 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003837 goto drop;
3838 }
3839
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003840 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003841 } else {
3842 if (len != 0) {
3843 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003844 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003845 goto drop;
3846 }
3847
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003848 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003849 }
3850
3851 return 0;
3852
3853drop:
3854 kfree_skb(skb);
3855 return 0;
3856}
3857
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3859{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003860 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003861 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003862 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003863 u8 tx_seq;
3864 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003866 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003867 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868 BT_DBG("unknown cid 0x%4.4x", cid);
3869 goto drop;
3870 }
3871
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003872 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003873
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003874 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875
3876 if (sk->sk_state != BT_CONNECTED)
3877 goto drop;
3878
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003879 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003880 case L2CAP_MODE_BASIC:
3881 /* If socket recv buffers overflows we drop data here
3882 * which is *bad* because L2CAP has to be reliable.
3883 * But we don't have any other choice. L2CAP doesn't
3884 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003886 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003887 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003889 if (!sock_queue_rcv_skb(sk, skb))
3890 goto done;
3891 break;
3892
3893 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003894 if (!sock_owned_by_user(sk)) {
3895 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003896 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003897 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003898 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003899 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003900
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003901 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003902
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003903 case L2CAP_MODE_STREAMING:
3904 control = get_unaligned_le16(skb->data);
3905 skb_pull(skb, 2);
3906 len = skb->len;
3907
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003908 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003909 goto drop;
3910
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003911 if (__is_sar_start(control))
3912 len -= 2;
3913
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003914 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003915 len -= 2;
3916
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003917 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003918 goto drop;
3919
3920 tx_seq = __get_txseq(control);
3921
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003922 if (chan->expected_tx_seq == tx_seq)
3923 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003924 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003925 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003926
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003927 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003928
3929 goto done;
3930
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003931 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003932 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003933 break;
3934 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003935
3936drop:
3937 kfree_skb(skb);
3938
3939done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003940 if (sk)
3941 bh_unlock_sock(sk);
3942
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943 return 0;
3944}
3945
Al Viro8e036fc2007-07-29 00:16:36 -07003946static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003947{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003948 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003949 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003951 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3952 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953 goto drop;
3954
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003955 sk = chan->sk;
3956
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003957 bh_lock_sock(sk);
3958
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959 BT_DBG("sk %p, len %d", sk, skb->len);
3960
3961 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3962 goto drop;
3963
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003964 if (l2cap_pi(sk)->chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965 goto drop;
3966
3967 if (!sock_queue_rcv_skb(sk, skb))
3968 goto done;
3969
3970drop:
3971 kfree_skb(skb);
3972
3973done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003974 if (sk)
3975 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003976 return 0;
3977}
3978
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003979static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3980{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003981 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003982 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003983
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003984 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3985 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003986 goto drop;
3987
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003988 sk = chan->sk;
3989
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003990 bh_lock_sock(sk);
3991
3992 BT_DBG("sk %p, len %d", sk, skb->len);
3993
3994 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3995 goto drop;
3996
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003997 if (l2cap_pi(sk)->chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003998 goto drop;
3999
4000 if (!sock_queue_rcv_skb(sk, skb))
4001 goto done;
4002
4003drop:
4004 kfree_skb(skb);
4005
4006done:
4007 if (sk)
4008 bh_unlock_sock(sk);
4009 return 0;
4010}
4011
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4013{
4014 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004015 u16 cid, len;
4016 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017
4018 skb_pull(skb, L2CAP_HDR_SIZE);
4019 cid = __le16_to_cpu(lh->cid);
4020 len = __le16_to_cpu(lh->len);
4021
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004022 if (len != skb->len) {
4023 kfree_skb(skb);
4024 return;
4025 }
4026
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4028
4029 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004030 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004031 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032 l2cap_sig_channel(conn, skb);
4033 break;
4034
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004035 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004036 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037 skb_pull(skb, 2);
4038 l2cap_conless_channel(conn, psm, skb);
4039 break;
4040
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004041 case L2CAP_CID_LE_DATA:
4042 l2cap_att_channel(conn, cid, skb);
4043 break;
4044
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045 default:
4046 l2cap_data_channel(conn, cid, skb);
4047 break;
4048 }
4049}
4050
4051/* ---- L2CAP interface with lower layer (HCI) ---- */
4052
4053static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4054{
4055 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004056 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057
4058 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004059 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060
4061 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4062
4063 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004064 read_lock(&chan_list_lock);
4065 list_for_each_entry(c, &chan_list, global_l) {
4066 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004067
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068 if (sk->sk_state != BT_LISTEN)
4069 continue;
4070
4071 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004072 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004073 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004074 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004076 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4077 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004078 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004079 lm2 |= HCI_LM_MASTER;
4080 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004082 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083
4084 return exact ? lm1 : lm2;
4085}
4086
4087static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4088{
Marcel Holtmann01394182006-07-03 10:02:46 +02004089 struct l2cap_conn *conn;
4090
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4092
Ville Tervoacd7d372011-02-10 22:38:49 -03004093 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004094 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095
4096 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097 conn = l2cap_conn_add(hcon, status);
4098 if (conn)
4099 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004100 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101 l2cap_conn_del(hcon, bt_err(status));
4102
4103 return 0;
4104}
4105
Marcel Holtmann2950f212009-02-12 14:02:50 +01004106static int l2cap_disconn_ind(struct hci_conn *hcon)
4107{
4108 struct l2cap_conn *conn = hcon->l2cap_data;
4109
4110 BT_DBG("hcon %p", hcon);
4111
4112 if (hcon->type != ACL_LINK || !conn)
4113 return 0x13;
4114
4115 return conn->disc_reason;
4116}
4117
4118static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119{
4120 BT_DBG("hcon %p reason %d", hcon, reason);
4121
Ville Tervoacd7d372011-02-10 22:38:49 -03004122 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004123 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124
4125 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004126
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127 return 0;
4128}
4129
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004130static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004131{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004132 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004133 return;
4134
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004135 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004136 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanab078012011-05-02 18:25:01 -03004137 l2cap_chan_clear_timer(chan);
4138 l2cap_chan_set_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004139 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004140 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004141 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004142 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanab078012011-05-02 18:25:01 -03004143 l2cap_chan_clear_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004144 }
4145}
4146
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004147static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004149 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004150 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151
Marcel Holtmann01394182006-07-03 10:02:46 +02004152 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004154
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155 BT_DBG("conn %p", conn);
4156
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004157 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004159 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004160 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004161
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162 bh_lock_sock(sk);
4163
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03004164 if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004165 bh_unlock_sock(sk);
4166 continue;
4167 }
4168
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004169 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004170 sk->sk_state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004171 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004172 bh_unlock_sock(sk);
4173 continue;
4174 }
4175
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004176 if (sk->sk_state == BT_CONNECT) {
4177 if (!status) {
4178 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004179 req.scid = cpu_to_le16(chan->scid);
4180 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004181
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004182 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03004183 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004184
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004185 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004186 L2CAP_CONN_REQ, sizeof(req), &req);
4187 } else {
Gustavo F. Padovanab078012011-05-02 18:25:01 -03004188 l2cap_chan_clear_timer(chan);
4189 l2cap_chan_set_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004190 }
4191 } else if (sk->sk_state == BT_CONNECT2) {
4192 struct l2cap_conn_rsp rsp;
4193 __u16 result;
4194
4195 if (!status) {
4196 sk->sk_state = BT_CONFIG;
4197 result = L2CAP_CR_SUCCESS;
4198 } else {
4199 sk->sk_state = BT_DISCONN;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03004200 l2cap_chan_set_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004201 result = L2CAP_CR_SEC_BLOCK;
4202 }
4203
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004204 rsp.scid = cpu_to_le16(chan->dcid);
4205 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004206 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02004207 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004208 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4209 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004210 }
4211
Linus Torvalds1da177e2005-04-16 15:20:36 -07004212 bh_unlock_sock(sk);
4213 }
4214
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004215 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004216
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217 return 0;
4218}
4219
4220static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4221{
4222 struct l2cap_conn *conn = hcon->l2cap_data;
4223
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004224 if (!conn)
4225 conn = l2cap_conn_add(hcon, 0);
4226
4227 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228 goto drop;
4229
4230 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4231
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004232 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004234 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004235 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236 int len;
4237
4238 if (conn->rx_len) {
4239 BT_ERR("Unexpected start frame (len %d)", skb->len);
4240 kfree_skb(conn->rx_skb);
4241 conn->rx_skb = NULL;
4242 conn->rx_len = 0;
4243 l2cap_conn_unreliable(conn, ECOMM);
4244 }
4245
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004246 /* Start fragment always begin with Basic L2CAP header */
4247 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248 BT_ERR("Frame is too short (len %d)", skb->len);
4249 l2cap_conn_unreliable(conn, ECOMM);
4250 goto drop;
4251 }
4252
4253 hdr = (struct l2cap_hdr *) skb->data;
4254 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004255 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256
4257 if (len == skb->len) {
4258 /* Complete frame received */
4259 l2cap_recv_frame(conn, skb);
4260 return 0;
4261 }
4262
4263 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4264
4265 if (skb->len > len) {
4266 BT_ERR("Frame is too long (len %d, expected len %d)",
4267 skb->len, len);
4268 l2cap_conn_unreliable(conn, ECOMM);
4269 goto drop;
4270 }
4271
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004272 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004273
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004274 if (chan && chan->sk) {
4275 struct sock *sk = chan->sk;
4276
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004277 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004278 BT_ERR("Frame exceeding recv MTU (len %d, "
4279 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004280 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004281 bh_unlock_sock(sk);
4282 l2cap_conn_unreliable(conn, ECOMM);
4283 goto drop;
4284 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004285 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004286 }
4287
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004289 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4290 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291 goto drop;
4292
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004293 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004294 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295 conn->rx_len = len - skb->len;
4296 } else {
4297 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4298
4299 if (!conn->rx_len) {
4300 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4301 l2cap_conn_unreliable(conn, ECOMM);
4302 goto drop;
4303 }
4304
4305 if (skb->len > conn->rx_len) {
4306 BT_ERR("Fragment is too long (len %d, expected %d)",
4307 skb->len, conn->rx_len);
4308 kfree_skb(conn->rx_skb);
4309 conn->rx_skb = NULL;
4310 conn->rx_len = 0;
4311 l2cap_conn_unreliable(conn, ECOMM);
4312 goto drop;
4313 }
4314
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004315 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004316 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317 conn->rx_len -= skb->len;
4318
4319 if (!conn->rx_len) {
4320 /* Complete frame received */
4321 l2cap_recv_frame(conn, conn->rx_skb);
4322 conn->rx_skb = NULL;
4323 }
4324 }
4325
4326drop:
4327 kfree_skb(skb);
4328 return 0;
4329}
4330
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004331static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004333 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004335 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004337 list_for_each_entry(c, &chan_list, global_l) {
4338 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004340 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 +01004341 batostr(&bt_sk(sk)->src),
4342 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004343 sk->sk_state, __le16_to_cpu(c->psm),
4344 c->scid, c->dcid, c->imtu, c->omtu,
4345 c->sec_level, c->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004346 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004348 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004349
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004350 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004351}
4352
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004353static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4354{
4355 return single_open(file, l2cap_debugfs_show, inode->i_private);
4356}
4357
4358static const struct file_operations l2cap_debugfs_fops = {
4359 .open = l2cap_debugfs_open,
4360 .read = seq_read,
4361 .llseek = seq_lseek,
4362 .release = single_release,
4363};
4364
4365static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004366
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367static struct hci_proto l2cap_hci_proto = {
4368 .name = "L2CAP",
4369 .id = HCI_PROTO_L2CAP,
4370 .connect_ind = l2cap_connect_ind,
4371 .connect_cfm = l2cap_connect_cfm,
4372 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004373 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004374 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375 .recv_acldata = l2cap_recv_acldata
4376};
4377
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004378int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004379{
4380 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004381
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004382 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004383 if (err < 0)
4384 return err;
4385
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004386 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004387 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004388 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004389 goto error;
4390 }
4391
4392 err = hci_register_proto(&l2cap_hci_proto);
4393 if (err < 0) {
4394 BT_ERR("L2CAP protocol registration failed");
4395 bt_sock_unregister(BTPROTO_L2CAP);
4396 goto error;
4397 }
4398
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004399 if (bt_debugfs) {
4400 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4401 bt_debugfs, NULL, &l2cap_debugfs_fops);
4402 if (!l2cap_debugfs)
4403 BT_ERR("Failed to create L2CAP debug file");
4404 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406 return 0;
4407
4408error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004409 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004410 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004411 return err;
4412}
4413
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004414void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004416 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004418 flush_workqueue(_busy_wq);
4419 destroy_workqueue(_busy_wq);
4420
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4422 BT_ERR("L2CAP protocol unregistration failed");
4423
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004424 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004425}
4426
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004427module_param(disable_ertm, bool, 0644);
4428MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");