blob: 6908a835a7a3f0110efc77e31380b376b32d4c96 [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;
438
439 rsp.scid = cpu_to_le16(chan->dcid);
440 rsp.dcid = cpu_to_le16(chan->scid);
441 rsp.result = cpu_to_le16(result);
442 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
443 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
444 sizeof(rsp), &rsp);
445 }
446
447 l2cap_chan_del(chan, reason);
448 break;
449
450 case BT_CONNECT:
451 case BT_DISCONN:
452 l2cap_chan_del(chan, reason);
453 break;
454
455 default:
456 sock_set_flag(sk, SOCK_ZAPPED);
457 break;
458 }
459}
460
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300461static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530462{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300463 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300464 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530465 case BT_SECURITY_HIGH:
466 return HCI_AT_DEDICATED_BONDING_MITM;
467 case BT_SECURITY_MEDIUM:
468 return HCI_AT_DEDICATED_BONDING;
469 default:
470 return HCI_AT_NO_BONDING;
471 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300472 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300473 if (chan->sec_level == BT_SECURITY_LOW)
474 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530475
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300476 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530477 return HCI_AT_NO_BONDING_MITM;
478 else
479 return HCI_AT_NO_BONDING;
480 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300481 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530482 case BT_SECURITY_HIGH:
483 return HCI_AT_GENERAL_BONDING_MITM;
484 case BT_SECURITY_MEDIUM:
485 return HCI_AT_GENERAL_BONDING;
486 default:
487 return HCI_AT_NO_BONDING;
488 }
489 }
490}
491
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200492/* Service level security */
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300493static inline int l2cap_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200494{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300495 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100496 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200497
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300498 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100499
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300500 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200501}
502
Johannes Bergb5ad8b72011-06-01 08:54:45 +0200503static u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200504{
505 u8 id;
506
507 /* Get next available identificator.
508 * 1 - 128 are used by kernel.
509 * 129 - 199 are reserved.
510 * 200 - 254 are used by utilities like l2ping, etc.
511 */
512
513 spin_lock_bh(&conn->lock);
514
515 if (++conn->tx_ident > 128)
516 conn->tx_ident = 1;
517
518 id = conn->tx_ident;
519
520 spin_unlock_bh(&conn->lock);
521
522 return id;
523}
524
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300525static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200526{
527 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200528 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200529
530 BT_DBG("code 0x%2.2x", code);
531
532 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300533 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200534
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200535 if (lmp_no_flush_capable(conn->hcon->hdev))
536 flags = ACL_START_NO_FLUSH;
537 else
538 flags = ACL_START;
539
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700540 bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
541
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200542 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200543}
544
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300545static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300546{
547 struct sk_buff *skb;
548 struct l2cap_hdr *lh;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300549 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300550 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300551 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300552 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200553 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300554
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300555 if (sk->sk_state != BT_CONNECTED)
556 return;
557
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300558 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300559 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300560
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300561 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300562
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300563 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300564 control |= L2CAP_CTRL_FRAME_TYPE;
565
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300566 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300567 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300568 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300569 }
570
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300571 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300572 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300573 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300574 }
575
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300576 skb = bt_skb_alloc(count, GFP_ATOMIC);
577 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300578 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300579
580 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300581 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300582 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300583 put_unaligned_le16(control, skb_put(skb, 2));
584
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300585 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300586 u16 fcs = crc16(0, (u8 *)lh, count - 2);
587 put_unaligned_le16(fcs, skb_put(skb, 2));
588 }
589
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200590 if (lmp_no_flush_capable(conn->hcon->hdev))
591 flags = ACL_START_NO_FLUSH;
592 else
593 flags = ACL_START;
594
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700595 bt_cb(skb)->force_active = chan->force_active;
596
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300597 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300598}
599
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300600static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300601{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300602 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300603 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300604 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300605 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300606 control |= L2CAP_SUPER_RCV_READY;
607
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300608 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300609
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300610 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300611}
612
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300613static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300614{
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300615 return !(chan->conf_state & L2CAP_CONF_CONNECT_PEND);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300616}
617
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300618static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200619{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300620 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200621
622 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100623 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
624 return;
625
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300626 if (l2cap_check_security(chan) &&
627 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200628 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300629 req.scid = cpu_to_le16(chan->scid);
630 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200631
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300632 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300633 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200634
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300635 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
636 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200637 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200638 } else {
639 struct l2cap_info_req req;
640 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
641
642 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
643 conn->info_ident = l2cap_get_ident(conn);
644
645 mod_timer(&conn->info_timer, jiffies +
646 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
647
648 l2cap_send_cmd(conn, conn->info_ident,
649 L2CAP_INFO_REQ, sizeof(req), &req);
650 }
651}
652
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300653static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
654{
655 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300656 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300657 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
658
659 switch (mode) {
660 case L2CAP_MODE_ERTM:
661 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
662 case L2CAP_MODE_STREAMING:
663 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
664 default:
665 return 0x00;
666 }
667}
668
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300669static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300670{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300671 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300672 struct l2cap_disconn_req req;
673
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300674 if (!conn)
675 return;
676
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300677 sk = chan->sk;
678
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300679 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300680 del_timer(&chan->retrans_timer);
681 del_timer(&chan->monitor_timer);
682 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300683 }
684
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300685 req.dcid = cpu_to_le16(chan->dcid);
686 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300687 l2cap_send_cmd(conn, l2cap_get_ident(conn),
688 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300689
690 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300691 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300692}
693
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200695static void l2cap_conn_start(struct l2cap_conn *conn)
696{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300697 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200698
699 BT_DBG("conn %p", conn);
700
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300701 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200702
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300703 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300704 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300705
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200706 bh_lock_sock(sk);
707
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300708 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200709 bh_unlock_sock(sk);
710 continue;
711 }
712
713 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300714 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300715
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300716 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300717 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300718 bh_unlock_sock(sk);
719 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200720 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300721
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300722 if (!l2cap_mode_supported(chan->mode,
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300723 conn->feat_mask)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300724 && chan->conf_state &
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300725 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300726 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300727 * so release the lock */
728 read_unlock_bh(&conn->chan_lock);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300729 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300730 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300731 bh_unlock_sock(sk);
732 continue;
733 }
734
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300735 req.scid = cpu_to_le16(chan->scid);
736 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300737
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300738 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300739 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300740
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300741 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
742 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300743
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200744 } else if (sk->sk_state == BT_CONNECT2) {
745 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300746 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300747 rsp.scid = cpu_to_le16(chan->dcid);
748 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200749
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300750 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100751 if (bt_sk(sk)->defer_setup) {
752 struct sock *parent = bt_sk(sk)->parent;
753 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
754 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
755 parent->sk_data_ready(parent, 0);
756
757 } else {
758 sk->sk_state = BT_CONFIG;
759 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
760 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
761 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200762 } else {
763 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
764 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
765 }
766
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300767 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
768 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300769
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300770 if (chan->conf_state & L2CAP_CONF_REQ_SENT ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300771 rsp.result != L2CAP_CR_SUCCESS) {
772 bh_unlock_sock(sk);
773 continue;
774 }
775
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300776 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300777 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300778 l2cap_build_conf_req(chan, buf), buf);
779 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200780 }
781
782 bh_unlock_sock(sk);
783 }
784
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300785 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200786}
787
Ville Tervob62f3282011-02-10 22:38:50 -0300788/* Find socket with cid and source bdaddr.
789 * Returns closest match, locked.
790 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300791static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300792{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300793 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300794
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300795 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300796
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300797 list_for_each_entry(c, &chan_list, global_l) {
798 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300799
Ville Tervob62f3282011-02-10 22:38:50 -0300800 if (state && sk->sk_state != state)
801 continue;
802
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300803 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300804 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300805 if (!bacmp(&bt_sk(sk)->src, src)) {
806 read_unlock(&chan_list_lock);
807 return c;
808 }
Ville Tervob62f3282011-02-10 22:38:50 -0300809
810 /* Closest match */
811 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300812 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300813 }
814 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300815
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300816 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300817
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300818 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300819}
820
821static void l2cap_le_conn_ready(struct l2cap_conn *conn)
822{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300823 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300824 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300825
826 BT_DBG("");
827
828 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300829 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300830 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300831 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300832 return;
833
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300834 parent = pchan->sk;
835
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300836 bh_lock_sock(parent);
837
Ville Tervob62f3282011-02-10 22:38:50 -0300838 /* Check for backlog size */
839 if (sk_acceptq_is_full(parent)) {
840 BT_DBG("backlog full %d", parent->sk_ack_backlog);
841 goto clean;
842 }
843
844 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
845 if (!sk)
846 goto clean;
847
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300848 chan = l2cap_chan_create(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300849 if (!chan) {
850 l2cap_sock_kill(sk);
851 goto clean;
852 }
853
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300854 l2cap_pi(sk)->chan = chan;
855
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300856 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300857
858 hci_conn_hold(conn->hcon);
859
860 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300861
Ville Tervob62f3282011-02-10 22:38:50 -0300862 bacpy(&bt_sk(sk)->src, conn->src);
863 bacpy(&bt_sk(sk)->dst, conn->dst);
864
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300865 bt_accept_enqueue(parent, sk);
866
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300867 __l2cap_chan_add(conn, chan);
868
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300869 l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300870
871 sk->sk_state = BT_CONNECTED;
872 parent->sk_data_ready(parent, 0);
873
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300874 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300875
876clean:
877 bh_unlock_sock(parent);
878}
879
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200880static void l2cap_conn_ready(struct l2cap_conn *conn)
881{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300882 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200883
884 BT_DBG("conn %p", conn);
885
Ville Tervob62f3282011-02-10 22:38:50 -0300886 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
887 l2cap_le_conn_ready(conn);
888
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300889 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200890
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300891 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300892 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300893
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200894 bh_lock_sock(sk);
895
Ville Tervoacd7d372011-02-10 22:38:49 -0300896 if (conn->hcon->type == LE_LINK) {
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300897 l2cap_chan_clear_timer(chan);
Ville Tervoacd7d372011-02-10 22:38:49 -0300898 sk->sk_state = BT_CONNECTED;
899 sk->sk_state_change(sk);
900 }
901
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300902 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300903 l2cap_chan_clear_timer(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200904 sk->sk_state = BT_CONNECTED;
905 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200906 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300907 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200908
909 bh_unlock_sock(sk);
910 }
911
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300912 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200913}
914
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200915/* Notify sockets that we cannot guaranty reliability anymore */
916static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
917{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300918 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200919
920 BT_DBG("conn %p", conn);
921
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300922 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200923
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300924 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300925 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300926
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300927 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200928 sk->sk_err = err;
929 }
930
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300931 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200932}
933
934static void l2cap_info_timeout(unsigned long arg)
935{
936 struct l2cap_conn *conn = (void *) arg;
937
Marcel Holtmann984947d2009-02-06 23:35:19 +0100938 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100939 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100940
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200941 l2cap_conn_start(conn);
942}
943
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
945{
Marcel Holtmann01394182006-07-03 10:02:46 +0200946 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947
Marcel Holtmann01394182006-07-03 10:02:46 +0200948 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 return conn;
950
Marcel Holtmann01394182006-07-03 10:02:46 +0200951 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
952 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954
955 hcon->l2cap_data = conn;
956 conn->hcon = hcon;
957
Marcel Holtmann01394182006-07-03 10:02:46 +0200958 BT_DBG("hcon %p conn %p", hcon, conn);
959
Ville Tervoacd7d372011-02-10 22:38:49 -0300960 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
961 conn->mtu = hcon->hdev->le_mtu;
962 else
963 conn->mtu = hcon->hdev->acl_mtu;
964
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 conn->src = &hcon->hdev->bdaddr;
966 conn->dst = &hcon->dst;
967
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200968 conn->feat_mask = 0;
969
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300971 rwlock_init(&conn->chan_lock);
972
973 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974
Ville Tervob62f3282011-02-10 22:38:50 -0300975 if (hcon->type != LE_LINK)
976 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000977 (unsigned long) conn);
978
Marcel Holtmann2950f212009-02-12 14:02:50 +0100979 conn->disc_reason = 0x13;
980
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 return conn;
982}
983
Marcel Holtmann01394182006-07-03 10:02:46 +0200984static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985{
Marcel Holtmann01394182006-07-03 10:02:46 +0200986 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300987 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 struct sock *sk;
989
Marcel Holtmann01394182006-07-03 10:02:46 +0200990 if (!conn)
991 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992
993 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
994
Wei Yongjun7585b972009-02-25 18:29:52 +0800995 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996
997 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300998 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300999 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001001 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 bh_unlock_sock(sk);
1003 l2cap_sock_kill(sk);
1004 }
1005
Dave Young8e8440f2008-03-03 12:18:55 -08001006 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1007 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -08001008
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 hcon->l2cap_data = NULL;
1010 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011}
1012
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001013static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001015 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001016 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001017 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018}
1019
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021
1022/* Find socket with psm and source bdaddr.
1023 * Returns closest match.
1024 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001025static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001027 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001029 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001030
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001031 list_for_each_entry(c, &chan_list, global_l) {
1032 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001033
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 if (state && sk->sk_state != state)
1035 continue;
1036
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001037 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001039 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001040 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001041 return c;
1042 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043
1044 /* Closest match */
1045 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001046 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 }
1048 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001050 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001051
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001052 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053}
1054
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001055int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001057 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 bdaddr_t *src = &bt_sk(sk)->src;
1059 bdaddr_t *dst = &bt_sk(sk)->dst;
1060 struct l2cap_conn *conn;
1061 struct hci_conn *hcon;
1062 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001063 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001064 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001066 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001067 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001069 hdev = hci_get_route(dst, src);
1070 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 return -EHOSTUNREACH;
1072
1073 hci_dev_lock_bh(hdev);
1074
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001075 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001076
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001077 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001078 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001079 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001080 else
1081 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001082 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001083
Ville Tervo30e76272011-02-22 16:10:53 -03001084 if (IS_ERR(hcon)) {
1085 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001087 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088
1089 conn = l2cap_conn_add(hcon, 0);
1090 if (!conn) {
1091 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001092 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 goto done;
1094 }
1095
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 /* Update source addr of the socket */
1097 bacpy(src, conn->src);
1098
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001099 l2cap_chan_add(conn, chan);
1100
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 sk->sk_state = BT_CONNECT;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03001102 l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103
1104 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001105 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanab078012011-05-02 18:25:01 -03001106 l2cap_chan_clear_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001107 if (l2cap_check_security(chan))
Johan Hedbergd00ef242011-01-19 12:06:51 +05301108 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001109 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001110 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 }
1112
Ville Tervo30e76272011-02-22 16:10:53 -03001113 err = 0;
1114
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115done:
1116 hci_dev_unlock_bh(hdev);
1117 hci_dev_put(hdev);
1118 return err;
1119}
1120
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001121int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001122{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001123 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001124 DECLARE_WAITQUEUE(wait, current);
1125 int err = 0;
1126 int timeo = HZ/5;
1127
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001128 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001129 while ((chan->unacked_frames > 0 && chan->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001130 set_current_state(TASK_INTERRUPTIBLE);
1131
1132 if (!timeo)
1133 timeo = HZ/5;
1134
1135 if (signal_pending(current)) {
1136 err = sock_intr_errno(timeo);
1137 break;
1138 }
1139
1140 release_sock(sk);
1141 timeo = schedule_timeout(timeo);
1142 lock_sock(sk);
1143
1144 err = sock_error(sk);
1145 if (err)
1146 break;
1147 }
1148 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001149 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001150 return err;
1151}
1152
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001153static void l2cap_monitor_timeout(unsigned long arg)
1154{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001155 struct l2cap_chan *chan = (void *) arg;
1156 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001157
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001158 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001159
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001160 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001161 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001162 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001163 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001164 return;
1165 }
1166
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001167 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001168 __mod_monitor_timer();
1169
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001170 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001171 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001172}
1173
1174static void l2cap_retrans_timeout(unsigned long arg)
1175{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001176 struct l2cap_chan *chan = (void *) arg;
1177 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001178
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001179 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001180
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001181 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001182 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001183 __mod_monitor_timer();
1184
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001185 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001186
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001187 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001188 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001189}
1190
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001191static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001192{
1193 struct sk_buff *skb;
1194
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001195 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001196 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001197 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001198 break;
1199
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001200 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001201 kfree_skb(skb);
1202
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001203 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001204 }
1205
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001206 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001207 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001208}
1209
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001210void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001211{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001212 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001213 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001214
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001215 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001216
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001217 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001218 flags = ACL_START_NO_FLUSH;
1219 else
1220 flags = ACL_START;
1221
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -07001222 bt_cb(skb)->force_active = chan->force_active;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001223 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001224}
1225
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001226void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001227{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001228 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001229 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001230
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001231 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001232 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001233 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001234 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001235
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001236 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001237 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1238 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001239 }
1240
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001241 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001242
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001243 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001244 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001245}
1246
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001247static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001248{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001249 struct sk_buff *skb, *tx_skb;
1250 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001251
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001252 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001253 if (!skb)
1254 return;
1255
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001256 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001257 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001258 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001259
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001260 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001261 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001262
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001263 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001264
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001265 if (chan->remote_max_tx &&
1266 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001267 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001268 return;
1269 }
1270
1271 tx_skb = skb_clone(skb, GFP_ATOMIC);
1272 bt_cb(skb)->retries++;
1273 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001274 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001275
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001276 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001277 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001278 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001279 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001280
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001281 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001282 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001283
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001284 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1285
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001286 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001287 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1288 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1289 }
1290
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001291 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001292}
1293
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001294int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001295{
1296 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001297 struct sock *sk = chan->sk;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001298 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001299 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001300
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001301 if (sk->sk_state != BT_CONNECTED)
1302 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001303
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001304 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001305
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001306 if (chan->remote_max_tx &&
1307 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001308 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001309 break;
1310 }
1311
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001312 tx_skb = skb_clone(skb, GFP_ATOMIC);
1313
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001314 bt_cb(skb)->retries++;
1315
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001316 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001317 control &= L2CAP_CTRL_SAR;
1318
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001319 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001320 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001321 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001322 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001323 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1324 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001325 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1326
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001327
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001328 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001329 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1330 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1331 }
1332
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001333 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001334
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001335 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001336
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001337 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1338 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001339
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301340 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001341 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301342
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001343 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001344
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001345 if (skb_queue_is_last(&chan->tx_q, skb))
1346 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001347 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001348 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001349
1350 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001351 }
1352
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001353 return nsent;
1354}
1355
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001356static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001357{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001358 int ret;
1359
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001360 if (!skb_queue_empty(&chan->tx_q))
1361 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001362
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001363 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001364 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001365 return ret;
1366}
1367
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001368static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001369{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001370 u16 control = 0;
1371
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001372 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001373
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001374 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001375 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001376 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1377 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001378 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001379 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001380
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001381 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001382 return;
1383
1384 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001385 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001386}
1387
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001388static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001389{
1390 struct srej_list *tail;
1391 u16 control;
1392
1393 control = L2CAP_SUPER_SELECT_REJECT;
1394 control |= L2CAP_CTRL_FINAL;
1395
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001396 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001397 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1398
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001399 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001400}
1401
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001402static 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 -07001403{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001404 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001405 struct sk_buff **frag;
1406 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001408 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001409 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410
1411 sent += count;
1412 len -= count;
1413
1414 /* Continuation fragments (no L2CAP header) */
1415 frag = &skb_shinfo(skb)->frag_list;
1416 while (len) {
1417 count = min_t(unsigned int, conn->mtu, len);
1418
1419 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1420 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001421 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001422 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1423 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424
1425 sent += count;
1426 len -= count;
1427
1428 frag = &(*frag)->next;
1429 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
1431 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001432}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001434struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001435{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001436 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001437 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001438 struct sk_buff *skb;
1439 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1440 struct l2cap_hdr *lh;
1441
1442 BT_DBG("sk %p len %d", sk, (int)len);
1443
1444 count = min_t(unsigned int, (conn->mtu - hlen), len);
1445 skb = bt_skb_send_alloc(sk, count + hlen,
1446 msg->msg_flags & MSG_DONTWAIT, &err);
1447 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001448 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001449
1450 /* Create L2CAP header */
1451 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001452 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001453 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001454 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001455
1456 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1457 if (unlikely(err < 0)) {
1458 kfree_skb(skb);
1459 return ERR_PTR(err);
1460 }
1461 return skb;
1462}
1463
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001464struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001465{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001466 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001467 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001468 struct sk_buff *skb;
1469 int err, count, hlen = L2CAP_HDR_SIZE;
1470 struct l2cap_hdr *lh;
1471
1472 BT_DBG("sk %p len %d", sk, (int)len);
1473
1474 count = min_t(unsigned int, (conn->mtu - hlen), len);
1475 skb = bt_skb_send_alloc(sk, count + hlen,
1476 msg->msg_flags & MSG_DONTWAIT, &err);
1477 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001478 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001479
1480 /* Create L2CAP header */
1481 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001482 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001483 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1484
1485 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1486 if (unlikely(err < 0)) {
1487 kfree_skb(skb);
1488 return ERR_PTR(err);
1489 }
1490 return skb;
1491}
1492
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001493struct 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 -03001494{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001495 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001496 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001497 struct sk_buff *skb;
1498 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1499 struct l2cap_hdr *lh;
1500
1501 BT_DBG("sk %p len %d", sk, (int)len);
1502
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001503 if (!conn)
1504 return ERR_PTR(-ENOTCONN);
1505
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001506 if (sdulen)
1507 hlen += 2;
1508
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001509 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001510 hlen += 2;
1511
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001512 count = min_t(unsigned int, (conn->mtu - hlen), len);
1513 skb = bt_skb_send_alloc(sk, count + hlen,
1514 msg->msg_flags & MSG_DONTWAIT, &err);
1515 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001516 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001517
1518 /* Create L2CAP header */
1519 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001520 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001521 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1522 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001523 if (sdulen)
1524 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001525
1526 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1527 if (unlikely(err < 0)) {
1528 kfree_skb(skb);
1529 return ERR_PTR(err);
1530 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001531
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001532 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001533 put_unaligned_le16(0, skb_put(skb, 2));
1534
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001535 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001536 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537}
1538
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001539int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001540{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001541 struct sk_buff *skb;
1542 struct sk_buff_head sar_queue;
1543 u16 control;
1544 size_t size = 0;
1545
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001546 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001547 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001548 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001549 if (IS_ERR(skb))
1550 return PTR_ERR(skb);
1551
1552 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001553 len -= chan->remote_mps;
1554 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001555
1556 while (len > 0) {
1557 size_t buflen;
1558
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001559 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001560 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001561 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001562 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001563 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001564 buflen = len;
1565 }
1566
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001567 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001568 if (IS_ERR(skb)) {
1569 skb_queue_purge(&sar_queue);
1570 return PTR_ERR(skb);
1571 }
1572
1573 __skb_queue_tail(&sar_queue, skb);
1574 len -= buflen;
1575 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001576 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001577 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1578 if (chan->tx_send_head == NULL)
1579 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001580
1581 return size;
1582}
1583
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001584int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1585{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001586 struct sk_buff *skb;
1587 u16 control;
1588 int err;
1589
1590 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001591 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001592 skb = l2cap_create_connless_pdu(chan, msg, len);
1593 if (IS_ERR(skb))
1594 return PTR_ERR(skb);
1595
1596 l2cap_do_send(chan, skb);
1597 return len;
1598 }
1599
1600 switch (chan->mode) {
1601 case L2CAP_MODE_BASIC:
1602 /* Check outgoing MTU */
1603 if (len > chan->omtu)
1604 return -EMSGSIZE;
1605
1606 /* Create a basic PDU */
1607 skb = l2cap_create_basic_pdu(chan, msg, len);
1608 if (IS_ERR(skb))
1609 return PTR_ERR(skb);
1610
1611 l2cap_do_send(chan, skb);
1612 err = len;
1613 break;
1614
1615 case L2CAP_MODE_ERTM:
1616 case L2CAP_MODE_STREAMING:
1617 /* Entire SDU fits into one PDU */
1618 if (len <= chan->remote_mps) {
1619 control = L2CAP_SDU_UNSEGMENTED;
1620 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1621 0);
1622 if (IS_ERR(skb))
1623 return PTR_ERR(skb);
1624
1625 __skb_queue_tail(&chan->tx_q, skb);
1626
1627 if (chan->tx_send_head == NULL)
1628 chan->tx_send_head = skb;
1629
1630 } else {
1631 /* Segment SDU into multiples PDUs */
1632 err = l2cap_sar_segment_sdu(chan, msg, len);
1633 if (err < 0)
1634 return err;
1635 }
1636
1637 if (chan->mode == L2CAP_MODE_STREAMING) {
1638 l2cap_streaming_send(chan);
1639 err = len;
1640 break;
1641 }
1642
1643 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
1644 (chan->conn_state & L2CAP_CONN_WAIT_F)) {
1645 err = len;
1646 break;
1647 }
1648
1649 err = l2cap_ertm_send(chan);
1650 if (err >= 0)
1651 err = len;
1652
1653 break;
1654
1655 default:
1656 BT_DBG("bad state %1.1x", chan->mode);
1657 err = -EBADFD;
1658 }
1659
1660 return err;
1661}
1662
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663static void l2cap_chan_ready(struct sock *sk)
1664{
1665 struct sock *parent = bt_sk(sk)->parent;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001666 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667
1668 BT_DBG("sk %p, parent %p", sk, parent);
1669
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001670 chan->conf_state = 0;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03001671 l2cap_chan_clear_timer(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672
1673 if (!parent) {
1674 /* Outgoing channel.
1675 * Wake up socket sleeping on connect.
1676 */
1677 sk->sk_state = BT_CONNECTED;
1678 sk->sk_state_change(sk);
1679 } else {
1680 /* Incoming channel.
1681 * Wake up socket sleeping on accept.
1682 */
1683 parent->sk_data_ready(parent, 0);
1684 }
1685}
1686
1687/* Copy frame to all raw sockets on that connection */
1688static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1689{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001691 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692
1693 BT_DBG("conn %p", conn);
1694
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001695 read_lock(&conn->chan_lock);
1696 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001697 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001698 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 continue;
1700
1701 /* Don't send frame to the socket it came from */
1702 if (skb->sk == sk)
1703 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001704 nskb = skb_clone(skb, GFP_ATOMIC);
1705 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 continue;
1707
1708 if (sock_queue_rcv_skb(sk, nskb))
1709 kfree_skb(nskb);
1710 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001711 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712}
1713
1714/* ---- L2CAP signalling commands ---- */
1715static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1716 u8 code, u8 ident, u16 dlen, void *data)
1717{
1718 struct sk_buff *skb, **frag;
1719 struct l2cap_cmd_hdr *cmd;
1720 struct l2cap_hdr *lh;
1721 int len, count;
1722
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001723 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1724 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725
1726 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1727 count = min_t(unsigned int, conn->mtu, len);
1728
1729 skb = bt_skb_alloc(count, GFP_ATOMIC);
1730 if (!skb)
1731 return NULL;
1732
1733 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001734 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001735
1736 if (conn->hcon->type == LE_LINK)
1737 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1738 else
1739 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740
1741 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1742 cmd->code = code;
1743 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001744 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745
1746 if (dlen) {
1747 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1748 memcpy(skb_put(skb, count), data, count);
1749 data += count;
1750 }
1751
1752 len -= skb->len;
1753
1754 /* Continuation fragments (no L2CAP header) */
1755 frag = &skb_shinfo(skb)->frag_list;
1756 while (len) {
1757 count = min_t(unsigned int, conn->mtu, len);
1758
1759 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1760 if (!*frag)
1761 goto fail;
1762
1763 memcpy(skb_put(*frag, count), data, count);
1764
1765 len -= count;
1766 data += count;
1767
1768 frag = &(*frag)->next;
1769 }
1770
1771 return skb;
1772
1773fail:
1774 kfree_skb(skb);
1775 return NULL;
1776}
1777
1778static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1779{
1780 struct l2cap_conf_opt *opt = *ptr;
1781 int len;
1782
1783 len = L2CAP_CONF_OPT_SIZE + opt->len;
1784 *ptr += len;
1785
1786 *type = opt->type;
1787 *olen = opt->len;
1788
1789 switch (opt->len) {
1790 case 1:
1791 *val = *((u8 *) opt->val);
1792 break;
1793
1794 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001795 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 break;
1797
1798 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001799 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 break;
1801
1802 default:
1803 *val = (unsigned long) opt->val;
1804 break;
1805 }
1806
1807 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1808 return len;
1809}
1810
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1812{
1813 struct l2cap_conf_opt *opt = *ptr;
1814
1815 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1816
1817 opt->type = type;
1818 opt->len = len;
1819
1820 switch (len) {
1821 case 1:
1822 *((u8 *) opt->val) = val;
1823 break;
1824
1825 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001826 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827 break;
1828
1829 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001830 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 break;
1832
1833 default:
1834 memcpy(opt->val, (void *) val, len);
1835 break;
1836 }
1837
1838 *ptr += L2CAP_CONF_OPT_SIZE + len;
1839}
1840
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001841static void l2cap_ack_timeout(unsigned long arg)
1842{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001843 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001844
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001845 bh_lock_sock(chan->sk);
1846 l2cap_send_ack(chan);
1847 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001848}
1849
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001850static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001851{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001852 struct sock *sk = chan->sk;
1853
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001854 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001855 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001856 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001857 chan->num_acked = 0;
1858 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001859
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001860 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1861 (unsigned long) chan);
1862 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1863 (unsigned long) chan);
1864 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001865
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001866 skb_queue_head_init(&chan->srej_q);
1867 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001868
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001869 INIT_LIST_HEAD(&chan->srej_l);
1870
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001871 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001872
1873 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001874}
1875
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001876static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1877{
1878 switch (mode) {
1879 case L2CAP_MODE_STREAMING:
1880 case L2CAP_MODE_ERTM:
1881 if (l2cap_mode_supported(mode, remote_feat_mask))
1882 return mode;
1883 /* fall through */
1884 default:
1885 return L2CAP_MODE_BASIC;
1886 }
1887}
1888
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001889static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001892 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 void *ptr = req->data;
1894
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001895 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001897 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001898 goto done;
1899
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001900 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001901 case L2CAP_MODE_STREAMING:
1902 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001903 if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001904 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001905
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001906 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001907 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001908 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001909 break;
1910 }
1911
1912done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001913 if (chan->imtu != L2CAP_DEFAULT_MTU)
1914 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001915
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001916 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001917 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001918 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1919 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001920 break;
1921
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001922 rfc.mode = L2CAP_MODE_BASIC;
1923 rfc.txwin_size = 0;
1924 rfc.max_transmit = 0;
1925 rfc.retrans_timeout = 0;
1926 rfc.monitor_timeout = 0;
1927 rfc.max_pdu_size = 0;
1928
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001929 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1930 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001931 break;
1932
1933 case L2CAP_MODE_ERTM:
1934 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001935 rfc.txwin_size = chan->tx_win;
1936 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001937 rfc.retrans_timeout = 0;
1938 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001939 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001940 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1941 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001942
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001943 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1944 (unsigned long) &rfc);
1945
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001946 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001947 break;
1948
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001949 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001950 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001951 chan->fcs = L2CAP_FCS_NONE;
1952 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001953 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001954 break;
1955
1956 case L2CAP_MODE_STREAMING:
1957 rfc.mode = L2CAP_MODE_STREAMING;
1958 rfc.txwin_size = 0;
1959 rfc.max_transmit = 0;
1960 rfc.retrans_timeout = 0;
1961 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001962 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001963 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1964 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001965
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001966 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1967 (unsigned long) &rfc);
1968
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001969 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001970 break;
1971
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001972 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001973 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001974 chan->fcs = L2CAP_FCS_NONE;
1975 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001976 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001977 break;
1978 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001980 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001981 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982
1983 return ptr - data;
1984}
1985
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001986static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001988 struct l2cap_conf_rsp *rsp = data;
1989 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001990 void *req = chan->conf_req;
1991 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001992 int type, hint, olen;
1993 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001994 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001995 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001996 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001998 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001999
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002000 while (len >= L2CAP_CONF_OPT_SIZE) {
2001 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03002003 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002004 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002005
2006 switch (type) {
2007 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002008 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002009 break;
2010
2011 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002012 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002013 break;
2014
2015 case L2CAP_CONF_QOS:
2016 break;
2017
Marcel Holtmann6464f352007-10-20 13:39:51 +02002018 case L2CAP_CONF_RFC:
2019 if (olen == sizeof(rfc))
2020 memcpy(&rfc, (void *) val, olen);
2021 break;
2022
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002023 case L2CAP_CONF_FCS:
2024 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002025 chan->conf_state |= L2CAP_CONF_NO_FCS_RECV;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002026
2027 break;
2028
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002029 default:
2030 if (hint)
2031 break;
2032
2033 result = L2CAP_CONF_UNKNOWN;
2034 *((u8 *) ptr++) = type;
2035 break;
2036 }
2037 }
2038
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002039 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002040 goto done;
2041
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002042 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002043 case L2CAP_MODE_STREAMING:
2044 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002045 if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002046 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002047 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002048 break;
2049 }
2050
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002051 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002052 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002053
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002054 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002055 }
2056
2057done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002058 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002059 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002060 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002061
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002062 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002063 return -ECONNREFUSED;
2064
2065 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2066 sizeof(rfc), (unsigned long) &rfc);
2067 }
2068
2069
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002070 if (result == L2CAP_CONF_SUCCESS) {
2071 /* Configure output options and let the other side know
2072 * which ones we don't like. */
2073
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002074 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2075 result = L2CAP_CONF_UNACCEPT;
2076 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002077 chan->omtu = mtu;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002078 chan->conf_state |= L2CAP_CONF_MTU_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002079 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002080 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002081
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002082 switch (rfc.mode) {
2083 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002084 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002085 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002086 break;
2087
2088 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002089 chan->remote_tx_win = rfc.txwin_size;
2090 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002091
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002092 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2093 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002094
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002095 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002096
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002097 rfc.retrans_timeout =
2098 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2099 rfc.monitor_timeout =
2100 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002101
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002102 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002103
2104 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2105 sizeof(rfc), (unsigned long) &rfc);
2106
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002107 break;
2108
2109 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002110 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2111 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002112
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002113 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002114
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002115 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002116
2117 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2118 sizeof(rfc), (unsigned long) &rfc);
2119
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002120 break;
2121
2122 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002123 result = L2CAP_CONF_UNACCEPT;
2124
2125 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002126 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002127 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002128
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002129 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002130 chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002131 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002132 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002133 rsp->result = cpu_to_le16(result);
2134 rsp->flags = cpu_to_le16(0x0000);
2135
2136 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137}
2138
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002139static 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 -03002140{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002141 struct l2cap_conf_req *req = data;
2142 void *ptr = req->data;
2143 int type, olen;
2144 unsigned long val;
2145 struct l2cap_conf_rfc rfc;
2146
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002147 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002148
2149 while (len >= L2CAP_CONF_OPT_SIZE) {
2150 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2151
2152 switch (type) {
2153 case L2CAP_CONF_MTU:
2154 if (val < L2CAP_DEFAULT_MIN_MTU) {
2155 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002156 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002157 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002158 chan->imtu = val;
2159 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002160 break;
2161
2162 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002163 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002164 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002165 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002166 break;
2167
2168 case L2CAP_CONF_RFC:
2169 if (olen == sizeof(rfc))
2170 memcpy(&rfc, (void *)val, olen);
2171
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002172 if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002173 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002174 return -ECONNREFUSED;
2175
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002176 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002177
2178 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2179 sizeof(rfc), (unsigned long) &rfc);
2180 break;
2181 }
2182 }
2183
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002184 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002185 return -ECONNREFUSED;
2186
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002187 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002188
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002189 if (*result == L2CAP_CONF_SUCCESS) {
2190 switch (rfc.mode) {
2191 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002192 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2193 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2194 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002195 break;
2196 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002197 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002198 }
2199 }
2200
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002201 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002202 req->flags = cpu_to_le16(0x0000);
2203
2204 return ptr - data;
2205}
2206
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002207static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208{
2209 struct l2cap_conf_rsp *rsp = data;
2210 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002212 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002214 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002215 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002216 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217
2218 return ptr - data;
2219}
2220
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002221void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002222{
2223 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002224 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002225 u8 buf[128];
2226
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002227 rsp.scid = cpu_to_le16(chan->dcid);
2228 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002229 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2230 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2231 l2cap_send_cmd(conn, chan->ident,
2232 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2233
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002234 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002235 return;
2236
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002237 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002238 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2239 l2cap_build_conf_req(chan, buf), buf);
2240 chan->num_conf_req++;
2241}
2242
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002243static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002244{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002245 int type, olen;
2246 unsigned long val;
2247 struct l2cap_conf_rfc rfc;
2248
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002249 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002250
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002251 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002252 return;
2253
2254 while (len >= L2CAP_CONF_OPT_SIZE) {
2255 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2256
2257 switch (type) {
2258 case L2CAP_CONF_RFC:
2259 if (olen == sizeof(rfc))
2260 memcpy(&rfc, (void *)val, olen);
2261 goto done;
2262 }
2263 }
2264
2265done:
2266 switch (rfc.mode) {
2267 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002268 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2269 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2270 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002271 break;
2272 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002273 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002274 }
2275}
2276
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002277static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2278{
2279 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2280
2281 if (rej->reason != 0x0000)
2282 return 0;
2283
2284 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2285 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002286 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002287
2288 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002289 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002290
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002291 l2cap_conn_start(conn);
2292 }
2293
2294 return 0;
2295}
2296
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2298{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2300 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002301 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002302 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002303 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304
2305 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002306 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307
2308 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2309
2310 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002311 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2312 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313 result = L2CAP_CR_BAD_PSM;
2314 goto sendresp;
2315 }
2316
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002317 parent = pchan->sk;
2318
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002319 bh_lock_sock(parent);
2320
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002321 /* Check if the ACL is secure enough (if not SDP) */
2322 if (psm != cpu_to_le16(0x0001) &&
2323 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002324 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002325 result = L2CAP_CR_SEC_BLOCK;
2326 goto response;
2327 }
2328
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 result = L2CAP_CR_NO_MEM;
2330
2331 /* Check for backlog size */
2332 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002333 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 goto response;
2335 }
2336
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002337 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 if (!sk)
2339 goto response;
2340
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002341 chan = l2cap_chan_create(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002342 if (!chan) {
2343 l2cap_sock_kill(sk);
2344 goto response;
2345 }
2346
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03002347 l2cap_pi(sk)->chan = chan;
2348
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002349 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350
2351 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002352 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2353 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 sock_set_flag(sk, SOCK_ZAPPED);
2355 l2cap_sock_kill(sk);
2356 goto response;
2357 }
2358
2359 hci_conn_hold(conn->hcon);
2360
2361 l2cap_sock_init(sk, parent);
2362 bacpy(&bt_sk(sk)->src, conn->src);
2363 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002364 chan->psm = psm;
2365 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002367 bt_accept_enqueue(parent, sk);
2368
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002369 __l2cap_chan_add(conn, chan);
2370
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002371 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002373 l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002375 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376
Marcel Holtmann984947d2009-02-06 23:35:19 +01002377 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002378 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002379 if (bt_sk(sk)->defer_setup) {
2380 sk->sk_state = BT_CONNECT2;
2381 result = L2CAP_CR_PEND;
2382 status = L2CAP_CS_AUTHOR_PEND;
2383 parent->sk_data_ready(parent, 0);
2384 } else {
2385 sk->sk_state = BT_CONFIG;
2386 result = L2CAP_CR_SUCCESS;
2387 status = L2CAP_CS_NO_INFO;
2388 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002389 } else {
2390 sk->sk_state = BT_CONNECT2;
2391 result = L2CAP_CR_PEND;
2392 status = L2CAP_CS_AUTHEN_PEND;
2393 }
2394 } else {
2395 sk->sk_state = BT_CONNECT2;
2396 result = L2CAP_CR_PEND;
2397 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 }
2399
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002400 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401
2402response:
2403 bh_unlock_sock(parent);
2404
2405sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002406 rsp.scid = cpu_to_le16(scid);
2407 rsp.dcid = cpu_to_le16(dcid);
2408 rsp.result = cpu_to_le16(result);
2409 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002411
2412 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2413 struct l2cap_info_req info;
2414 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2415
2416 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2417 conn->info_ident = l2cap_get_ident(conn);
2418
2419 mod_timer(&conn->info_timer, jiffies +
2420 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2421
2422 l2cap_send_cmd(conn, conn->info_ident,
2423 L2CAP_INFO_REQ, sizeof(info), &info);
2424 }
2425
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002426 if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002427 result == L2CAP_CR_SUCCESS) {
2428 u8 buf[128];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002429 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002430 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002431 l2cap_build_conf_req(chan, buf), buf);
2432 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002433 }
2434
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 return 0;
2436}
2437
2438static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2439{
2440 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2441 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002442 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 struct sock *sk;
2444 u8 req[128];
2445
2446 scid = __le16_to_cpu(rsp->scid);
2447 dcid = __le16_to_cpu(rsp->dcid);
2448 result = __le16_to_cpu(rsp->result);
2449 status = __le16_to_cpu(rsp->status);
2450
2451 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2452
2453 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002454 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002455 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002456 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002458 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002459 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002460 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461 }
2462
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002463 sk = chan->sk;
2464
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465 switch (result) {
2466 case L2CAP_CR_SUCCESS:
2467 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002468 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002469 chan->dcid = dcid;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002470 chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002471
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002472 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002473 break;
2474
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002475 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002476
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002478 l2cap_build_conf_req(chan, req), req);
2479 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 break;
2481
2482 case L2CAP_CR_PEND:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002483 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484 break;
2485
2486 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002487 /* don't delete l2cap channel if sk is owned by user */
2488 if (sock_owned_by_user(sk)) {
2489 sk->sk_state = BT_DISCONN;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002490 l2cap_chan_clear_timer(chan);
2491 l2cap_chan_set_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002492 break;
2493 }
2494
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002495 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496 break;
2497 }
2498
2499 bh_unlock_sock(sk);
2500 return 0;
2501}
2502
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002503static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002504{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002505 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
2506
Mat Martineau8c462b62010-08-24 15:35:42 -07002507 /* FCS is enabled only in ERTM or streaming mode, if one or both
2508 * sides request it.
2509 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002510 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002511 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002512 else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002513 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002514}
2515
Al Viro88219a02007-07-29 00:17:25 -07002516static 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 -07002517{
2518 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2519 u16 dcid, flags;
2520 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002521 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002523 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524
2525 dcid = __le16_to_cpu(req->dcid);
2526 flags = __le16_to_cpu(req->flags);
2527
2528 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2529
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002530 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002531 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532 return -ENOENT;
2533
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002534 sk = chan->sk;
2535
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002536 if (sk->sk_state != BT_CONFIG) {
2537 struct l2cap_cmd_rej rej;
2538
2539 rej.reason = cpu_to_le16(0x0002);
2540 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2541 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002542 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002543 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002544
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002545 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002546 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002547 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002548 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002549 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002550 L2CAP_CONF_REJECT, flags), rsp);
2551 goto unlock;
2552 }
2553
2554 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002555 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2556 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557
2558 if (flags & 0x0001) {
2559 /* Incomplete config. Send empty response. */
2560 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002561 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002562 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563 goto unlock;
2564 }
2565
2566 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002567 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002568 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002569 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002571 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002573 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002574 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002575
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002576 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002577 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002578
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002579 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002580 goto unlock;
2581
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002582 if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002583 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002584
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002586
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002587 chan->next_tx_seq = 0;
2588 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002589 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002590 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002591 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002592
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002594 goto unlock;
2595 }
2596
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002597 if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002598 u8 buf[64];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002599 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002601 l2cap_build_conf_req(chan, buf), buf);
2602 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603 }
2604
2605unlock:
2606 bh_unlock_sock(sk);
2607 return 0;
2608}
2609
2610static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2611{
2612 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2613 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002614 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002616 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617
2618 scid = __le16_to_cpu(rsp->scid);
2619 flags = __le16_to_cpu(rsp->flags);
2620 result = __le16_to_cpu(rsp->result);
2621
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002622 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2623 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002625 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002626 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 return 0;
2628
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002629 sk = chan->sk;
2630
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631 switch (result) {
2632 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002633 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634 break;
2635
2636 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002637 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002638 char req[64];
2639
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002640 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002641 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002642 goto done;
2643 }
2644
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002645 /* throw out any old stored conf requests */
2646 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002647 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2648 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002649 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002650 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002651 goto done;
2652 }
2653
2654 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2655 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002656 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002657 if (result != L2CAP_CONF_SUCCESS)
2658 goto done;
2659 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660 }
2661
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002662 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002663 sk->sk_err = ECONNRESET;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002664 l2cap_chan_set_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002665 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666 goto done;
2667 }
2668
2669 if (flags & 0x01)
2670 goto done;
2671
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002672 chan->conf_state |= L2CAP_CONF_INPUT_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002674 if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002675 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002676
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002678 chan->next_tx_seq = 0;
2679 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002680 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002681 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002682 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002683
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 l2cap_chan_ready(sk);
2685 }
2686
2687done:
2688 bh_unlock_sock(sk);
2689 return 0;
2690}
2691
2692static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2693{
2694 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2695 struct l2cap_disconn_rsp rsp;
2696 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002697 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698 struct sock *sk;
2699
2700 scid = __le16_to_cpu(req->scid);
2701 dcid = __le16_to_cpu(req->dcid);
2702
2703 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2704
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002705 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002706 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707 return 0;
2708
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002709 sk = chan->sk;
2710
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002711 rsp.dcid = cpu_to_le16(chan->scid);
2712 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2714
2715 sk->sk_shutdown = SHUTDOWN_MASK;
2716
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002717 /* don't delete l2cap channel if sk is owned by user */
2718 if (sock_owned_by_user(sk)) {
2719 sk->sk_state = BT_DISCONN;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002720 l2cap_chan_clear_timer(chan);
2721 l2cap_chan_set_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002722 bh_unlock_sock(sk);
2723 return 0;
2724 }
2725
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002726 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727 bh_unlock_sock(sk);
2728
2729 l2cap_sock_kill(sk);
2730 return 0;
2731}
2732
2733static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2734{
2735 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2736 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002737 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738 struct sock *sk;
2739
2740 scid = __le16_to_cpu(rsp->scid);
2741 dcid = __le16_to_cpu(rsp->dcid);
2742
2743 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2744
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002745 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002746 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747 return 0;
2748
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002749 sk = chan->sk;
2750
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002751 /* don't delete l2cap channel if sk is owned by user */
2752 if (sock_owned_by_user(sk)) {
2753 sk->sk_state = BT_DISCONN;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002754 l2cap_chan_clear_timer(chan);
2755 l2cap_chan_set_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002756 bh_unlock_sock(sk);
2757 return 0;
2758 }
2759
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002760 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 bh_unlock_sock(sk);
2762
2763 l2cap_sock_kill(sk);
2764 return 0;
2765}
2766
2767static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2768{
2769 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 u16 type;
2771
2772 type = __le16_to_cpu(req->type);
2773
2774 BT_DBG("type 0x%4.4x", type);
2775
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002776 if (type == L2CAP_IT_FEAT_MASK) {
2777 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002778 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002779 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2780 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2781 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002782 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002783 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2784 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002785 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002786 l2cap_send_cmd(conn, cmd->ident,
2787 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002788 } else if (type == L2CAP_IT_FIXED_CHAN) {
2789 u8 buf[12];
2790 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2791 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2792 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2793 memcpy(buf + 4, l2cap_fixed_chan, 8);
2794 l2cap_send_cmd(conn, cmd->ident,
2795 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002796 } else {
2797 struct l2cap_info_rsp rsp;
2798 rsp.type = cpu_to_le16(type);
2799 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2800 l2cap_send_cmd(conn, cmd->ident,
2801 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2802 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803
2804 return 0;
2805}
2806
2807static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2808{
2809 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2810 u16 type, result;
2811
2812 type = __le16_to_cpu(rsp->type);
2813 result = __le16_to_cpu(rsp->result);
2814
2815 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2816
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002817 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2818 if (cmd->ident != conn->info_ident ||
2819 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2820 return 0;
2821
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002822 del_timer(&conn->info_timer);
2823
Ville Tervoadb08ed2010-08-04 09:43:33 +03002824 if (result != L2CAP_IR_SUCCESS) {
2825 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2826 conn->info_ident = 0;
2827
2828 l2cap_conn_start(conn);
2829
2830 return 0;
2831 }
2832
Marcel Holtmann984947d2009-02-06 23:35:19 +01002833 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002834 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002835
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002836 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002837 struct l2cap_info_req req;
2838 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2839
2840 conn->info_ident = l2cap_get_ident(conn);
2841
2842 l2cap_send_cmd(conn, conn->info_ident,
2843 L2CAP_INFO_REQ, sizeof(req), &req);
2844 } else {
2845 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2846 conn->info_ident = 0;
2847
2848 l2cap_conn_start(conn);
2849 }
2850 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002851 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002852 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002853
2854 l2cap_conn_start(conn);
2855 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002856
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857 return 0;
2858}
2859
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002860static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002861 u16 to_multiplier)
2862{
2863 u16 max_latency;
2864
2865 if (min > max || min < 6 || max > 3200)
2866 return -EINVAL;
2867
2868 if (to_multiplier < 10 || to_multiplier > 3200)
2869 return -EINVAL;
2870
2871 if (max >= to_multiplier * 8)
2872 return -EINVAL;
2873
2874 max_latency = (to_multiplier * 8 / max) - 1;
2875 if (latency > 499 || latency > max_latency)
2876 return -EINVAL;
2877
2878 return 0;
2879}
2880
2881static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2882 struct l2cap_cmd_hdr *cmd, u8 *data)
2883{
2884 struct hci_conn *hcon = conn->hcon;
2885 struct l2cap_conn_param_update_req *req;
2886 struct l2cap_conn_param_update_rsp rsp;
2887 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002888 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002889
2890 if (!(hcon->link_mode & HCI_LM_MASTER))
2891 return -EINVAL;
2892
2893 cmd_len = __le16_to_cpu(cmd->len);
2894 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2895 return -EPROTO;
2896
2897 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002898 min = __le16_to_cpu(req->min);
2899 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002900 latency = __le16_to_cpu(req->latency);
2901 to_multiplier = __le16_to_cpu(req->to_multiplier);
2902
2903 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2904 min, max, latency, to_multiplier);
2905
2906 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002907
2908 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2909 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002910 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2911 else
2912 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2913
2914 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2915 sizeof(rsp), &rsp);
2916
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002917 if (!err)
2918 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2919
Claudio Takahaside731152011-02-11 19:28:55 -02002920 return 0;
2921}
2922
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002923static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2924 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2925{
2926 int err = 0;
2927
2928 switch (cmd->code) {
2929 case L2CAP_COMMAND_REJ:
2930 l2cap_command_rej(conn, cmd, data);
2931 break;
2932
2933 case L2CAP_CONN_REQ:
2934 err = l2cap_connect_req(conn, cmd, data);
2935 break;
2936
2937 case L2CAP_CONN_RSP:
2938 err = l2cap_connect_rsp(conn, cmd, data);
2939 break;
2940
2941 case L2CAP_CONF_REQ:
2942 err = l2cap_config_req(conn, cmd, cmd_len, data);
2943 break;
2944
2945 case L2CAP_CONF_RSP:
2946 err = l2cap_config_rsp(conn, cmd, data);
2947 break;
2948
2949 case L2CAP_DISCONN_REQ:
2950 err = l2cap_disconnect_req(conn, cmd, data);
2951 break;
2952
2953 case L2CAP_DISCONN_RSP:
2954 err = l2cap_disconnect_rsp(conn, cmd, data);
2955 break;
2956
2957 case L2CAP_ECHO_REQ:
2958 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2959 break;
2960
2961 case L2CAP_ECHO_RSP:
2962 break;
2963
2964 case L2CAP_INFO_REQ:
2965 err = l2cap_information_req(conn, cmd, data);
2966 break;
2967
2968 case L2CAP_INFO_RSP:
2969 err = l2cap_information_rsp(conn, cmd, data);
2970 break;
2971
2972 default:
2973 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2974 err = -EINVAL;
2975 break;
2976 }
2977
2978 return err;
2979}
2980
2981static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2982 struct l2cap_cmd_hdr *cmd, u8 *data)
2983{
2984 switch (cmd->code) {
2985 case L2CAP_COMMAND_REJ:
2986 return 0;
2987
2988 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002989 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002990
2991 case L2CAP_CONN_PARAM_UPDATE_RSP:
2992 return 0;
2993
2994 default:
2995 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2996 return -EINVAL;
2997 }
2998}
2999
3000static inline void l2cap_sig_channel(struct l2cap_conn *conn,
3001 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002{
3003 u8 *data = skb->data;
3004 int len = skb->len;
3005 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003006 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007
3008 l2cap_raw_recv(conn, skb);
3009
3010 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003011 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3013 data += L2CAP_CMD_HDR_SIZE;
3014 len -= L2CAP_CMD_HDR_SIZE;
3015
Al Viro88219a02007-07-29 00:17:25 -07003016 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017
Al Viro88219a02007-07-29 00:17:25 -07003018 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 -07003019
Al Viro88219a02007-07-29 00:17:25 -07003020 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021 BT_DBG("corrupted command");
3022 break;
3023 }
3024
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003025 if (conn->hcon->type == LE_LINK)
3026 err = l2cap_le_sig_cmd(conn, &cmd, data);
3027 else
3028 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029
3030 if (err) {
3031 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003032
3033 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034
3035 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003036 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3038 }
3039
Al Viro88219a02007-07-29 00:17:25 -07003040 data += cmd_len;
3041 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003042 }
3043
3044 kfree_skb(skb);
3045}
3046
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003047static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003048{
3049 u16 our_fcs, rcv_fcs;
3050 int hdr_size = L2CAP_HDR_SIZE + 2;
3051
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003052 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003053 skb_trim(skb, skb->len - 2);
3054 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3055 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3056
3057 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003058 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003059 }
3060 return 0;
3061}
3062
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003063static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003064{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003065 u16 control = 0;
3066
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003067 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003068
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003069 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003070
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003071 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003072 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003073 l2cap_send_sframe(chan, control);
3074 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003075 }
3076
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003077 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
3078 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003079
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003080 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003081
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003082 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003083 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003084 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003085 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003086 }
3087}
3088
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003089static 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 -03003090{
3091 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003092 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003093
3094 bt_cb(skb)->tx_seq = tx_seq;
3095 bt_cb(skb)->sar = sar;
3096
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003097 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003098 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003099 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003100 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003101 }
3102
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003103 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003104 if (tx_seq_offset < 0)
3105 tx_seq_offset += 64;
3106
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003107 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003108 if (bt_cb(next_skb)->tx_seq == tx_seq)
3109 return -EINVAL;
3110
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003111 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003112 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003113 if (next_tx_seq_offset < 0)
3114 next_tx_seq_offset += 64;
3115
3116 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003117 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003118 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003119 }
3120
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003121 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003122 break;
3123
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003124 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003125
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003126 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003127
3128 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003129}
3130
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003131static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003132{
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003133 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003134 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003135
3136 switch (control & L2CAP_CTRL_SAR) {
3137 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003138 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003139 goto drop;
3140
Ruiyi Zhang224f8af2011-05-13 13:07:52 +08003141 return sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003142
3143 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003144 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003145 goto drop;
3146
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003147 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003148
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003149 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003150 goto disconnect;
3151
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003152 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3153 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003154 return -ENOMEM;
3155
3156 /* pull sdu_len bytes only after alloc, because of Local Busy
3157 * condition we have to be sure that this will be executed
3158 * only once, i.e., when alloc does not fail */
3159 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003160
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003161 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003162
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003163 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003164 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003165 break;
3166
3167 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003168 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003169 goto disconnect;
3170
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003171 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003172 goto disconnect;
3173
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003174 chan->partial_sdu_len += skb->len;
3175 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003176 goto drop;
3177
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003178 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003179
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003180 break;
3181
3182 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003183 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003184 goto disconnect;
3185
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003186 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003187 goto disconnect;
3188
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003189 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003190 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003191
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003192 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003193 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003194
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003195 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003196 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003197
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003198 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003199 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003200
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003201 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003202 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003203 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003204 return -ENOMEM;
3205 }
3206
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003207 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003208 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003209 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003210 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003211 return err;
3212 }
3213
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003214 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
3215 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003216
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003217 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003218 break;
3219 }
3220
3221 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003222 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003223
3224drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003225 kfree_skb(chan->sdu);
3226 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003227
3228disconnect:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003229 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003230 kfree_skb(skb);
3231 return 0;
3232}
3233
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003234static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003235{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003236 struct sk_buff *skb;
3237 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003238 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003239
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003240 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003241 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003242 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003243 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003244 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003245 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003246 }
3247
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003248 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003249 }
3250
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003251 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003252 goto done;
3253
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003254 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003255 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003256 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003257 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003258
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003259 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003260 __mod_monitor_timer();
3261
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003262 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003263
3264done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003265 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3266 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003267
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003268 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003269
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003270 return 0;
3271}
3272
3273static void l2cap_busy_work(struct work_struct *work)
3274{
3275 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003276 struct l2cap_chan *chan =
3277 container_of(work, struct l2cap_chan, busy_work);
3278 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003279 int n_tries = 0, timeo = HZ/5, err;
3280 struct sk_buff *skb;
3281
3282 lock_sock(sk);
3283
3284 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003285 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003286 set_current_state(TASK_INTERRUPTIBLE);
3287
3288 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3289 err = -EBUSY;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003290 l2cap_send_disconn_req(chan->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003291 break;
3292 }
3293
3294 if (!timeo)
3295 timeo = HZ/5;
3296
3297 if (signal_pending(current)) {
3298 err = sock_intr_errno(timeo);
3299 break;
3300 }
3301
3302 release_sock(sk);
3303 timeo = schedule_timeout(timeo);
3304 lock_sock(sk);
3305
3306 err = sock_error(sk);
3307 if (err)
3308 break;
3309
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003310 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003311 break;
3312 }
3313
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003314 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003315 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003316
3317 release_sock(sk);
3318}
3319
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003320static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003321{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003322 int sctrl, err;
3323
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003324 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003325 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003326 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003327 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003328
3329
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003330 }
3331
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003332 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003333 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003334 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003335 return err;
3336 }
3337
3338 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003339 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003340
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003341 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003342 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003343 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003344
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003345 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003346 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003347 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003348
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003349 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003350
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003351 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003352
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003353 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003354
3355 return err;
3356}
3357
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003358static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003359{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003360 struct sk_buff *_skb;
3361 int err = -EINVAL;
3362
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003363 /*
3364 * TODO: We have to notify the userland if some data is lost with the
3365 * Streaming Mode.
3366 */
3367
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003368 switch (control & L2CAP_CTRL_SAR) {
3369 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003370 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003371 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003372 break;
3373 }
3374
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003375 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003376 if (!err)
3377 return 0;
3378
3379 break;
3380
3381 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003382 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003383 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003384 break;
3385 }
3386
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003387 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003388 skb_pull(skb, 2);
3389
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003390 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003391 err = -EMSGSIZE;
3392 break;
3393 }
3394
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003395 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3396 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003397 err = -ENOMEM;
3398 break;
3399 }
3400
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003401 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003402
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003403 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003404 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003405 err = 0;
3406 break;
3407
3408 case L2CAP_SDU_CONTINUE:
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. Padovan6f61fd472011-03-25 20:09:37 -03003414 chan->partial_sdu_len += skb->len;
3415 if (chan->partial_sdu_len > chan->sdu_len)
3416 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003417 else
3418 err = 0;
3419
3420 break;
3421
3422 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003423 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003424 break;
3425
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003426 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003427
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003428 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003429 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003430
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003431 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003432 goto drop;
3433
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003434 if (chan->partial_sdu_len == chan->sdu_len) {
3435 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003436 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003437 if (err < 0)
3438 kfree_skb(_skb);
3439 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003440 err = 0;
3441
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003442drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003443 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003444 break;
3445 }
3446
3447 kfree_skb(skb);
3448 return err;
3449}
3450
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003451static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003452{
3453 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003454 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003455
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003456 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003457 if (bt_cb(skb)->tx_seq != tx_seq)
3458 break;
3459
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003460 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003461 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003462 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003463 chan->buffer_seq_srej =
3464 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003465 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003466 }
3467}
3468
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003469static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003470{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003471 struct srej_list *l, *tmp;
3472 u16 control;
3473
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003474 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003475 if (l->tx_seq == tx_seq) {
3476 list_del(&l->list);
3477 kfree(l);
3478 return;
3479 }
3480 control = L2CAP_SUPER_SELECT_REJECT;
3481 control |= l->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 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003484 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003485 }
3486}
3487
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003488static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003489{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003490 struct srej_list *new;
3491 u16 control;
3492
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003493 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003494 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003495 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003496 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003497
3498 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003499 new->tx_seq = chan->expected_tx_seq;
3500 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003501 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003502 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003503 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003504}
3505
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003506static 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 -03003507{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003508 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003509 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003510 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003511 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003512 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003513 int err = 0;
3514
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003515 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3516 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003517
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003518 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003519 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003520 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003521 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003522 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003523 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003524 }
3525
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003526 chan->expected_ack_seq = req_seq;
3527 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003528
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003529 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003530 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003531
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003532 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003533 if (tx_seq_offset < 0)
3534 tx_seq_offset += 64;
3535
3536 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003537 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003538 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003539 goto drop;
3540 }
3541
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003542 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003543 goto drop;
3544
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003545 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003546 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003547
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003548 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003549 struct srej_list, list);
3550 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003551 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003552 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003553
3554 list_del(&first->list);
3555 kfree(first);
3556
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003557 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003558 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003559 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3560 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003561 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003562 }
3563 } else {
3564 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003565
3566 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003567 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003568 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003569
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003570 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003571 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003572 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003573 return 0;
3574 }
3575 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003576 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003577 }
3578 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003579 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003580 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003581 if (expected_tx_seq_offset < 0)
3582 expected_tx_seq_offset += 64;
3583
3584 /* duplicated tx_seq */
3585 if (tx_seq_offset < expected_tx_seq_offset)
3586 goto drop;
3587
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003588 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003589
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003590 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003591
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003592 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003593 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003594
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003595 __skb_queue_head_init(&chan->srej_q);
3596 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003597 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003598
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003599 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003600
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003601 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003602
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003603 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003604 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003605 return 0;
3606
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003607expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003608 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003609
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003610 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003611 bt_cb(skb)->tx_seq = tx_seq;
3612 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003613 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003614 return 0;
3615 }
3616
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003617 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003618 if (err < 0)
3619 return 0;
3620
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003621 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003622 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3623 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003624 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003625 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003626 }
3627
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003628 __mod_ack_timer();
3629
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003630 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3631 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003632 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003633
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003634 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003635
3636drop:
3637 kfree_skb(skb);
3638 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003639}
3640
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003641static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003642{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003643 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003644 rx_control);
3645
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003646 chan->expected_ack_seq = __get_reqseq(rx_control);
3647 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003648
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003649 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003650 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3651 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3652 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003653 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003654 __mod_retrans_timer();
3655
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003656 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3657 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003658 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003659 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003660 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003661
3662 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003663 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003664
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003665 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3666 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003667 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003668 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003669
3670 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003671 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003672 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003673 __mod_retrans_timer();
3674
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003675 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3676 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3677 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003678 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003679 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003680 }
3681}
3682
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003683static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003684{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003685 u8 tx_seq = __get_reqseq(rx_control);
3686
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003687 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003688
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003689 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003690
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003691 chan->expected_ack_seq = tx_seq;
3692 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003693
3694 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003695 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3696 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003697 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003698 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003699 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003700 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003701
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003702 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3703 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003704 }
3705}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003706static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003707{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003708 u8 tx_seq = __get_reqseq(rx_control);
3709
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003710 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003711
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003712 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003713
3714 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003715 chan->expected_ack_seq = tx_seq;
3716 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003717
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003718 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3719 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003720
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003721 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003722
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003723 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003724 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003725 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003726 }
3727 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003728 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003729 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003730 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003731 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003732 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003733 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003734 l2cap_retransmit_one_frame(chan, tx_seq);
3735 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003736 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003737 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003738 }
3739 }
3740}
3741
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003742static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003743{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003744 u8 tx_seq = __get_reqseq(rx_control);
3745
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003746 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003747
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003748 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003749 chan->expected_ack_seq = tx_seq;
3750 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003751
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003752 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003753 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003754
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003755 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003756 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003757 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003758 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003759 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003760 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003761
3762 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003763 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003764 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003765 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003766}
3767
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003768static 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 -03003769{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003770 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003771
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003772 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003773 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003774 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003775 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003776 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003777 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003778 }
3779
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003780 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3781 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003782 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003783 break;
3784
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003785 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003786 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003787 break;
3788
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003789 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003790 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003791 break;
3792
3793 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003794 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003795 break;
3796 }
3797
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003798 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003799 return 0;
3800}
3801
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003802static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3803{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003804 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003805 u16 control;
3806 u8 req_seq;
3807 int len, next_tx_seq_offset, req_seq_offset;
3808
3809 control = get_unaligned_le16(skb->data);
3810 skb_pull(skb, 2);
3811 len = skb->len;
3812
3813 /*
3814 * We can just drop the corrupted I-frame here.
3815 * Receiver will miss it and start proper recovery
3816 * procedures and ask retransmission.
3817 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003818 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003819 goto drop;
3820
3821 if (__is_sar_start(control) && __is_iframe(control))
3822 len -= 2;
3823
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003824 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003825 len -= 2;
3826
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003827 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003828 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003829 goto drop;
3830 }
3831
3832 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003833 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003834 if (req_seq_offset < 0)
3835 req_seq_offset += 64;
3836
3837 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003838 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003839 if (next_tx_seq_offset < 0)
3840 next_tx_seq_offset += 64;
3841
3842 /* check for invalid req-seq */
3843 if (req_seq_offset > next_tx_seq_offset) {
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
3848 if (__is_iframe(control)) {
3849 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003850 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003851 goto drop;
3852 }
3853
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003854 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003855 } else {
3856 if (len != 0) {
3857 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003858 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003859 goto drop;
3860 }
3861
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003862 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003863 }
3864
3865 return 0;
3866
3867drop:
3868 kfree_skb(skb);
3869 return 0;
3870}
3871
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3873{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003874 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003875 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003876 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003877 u8 tx_seq;
3878 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003880 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003881 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882 BT_DBG("unknown cid 0x%4.4x", cid);
3883 goto drop;
3884 }
3885
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003886 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003887
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003888 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889
3890 if (sk->sk_state != BT_CONNECTED)
3891 goto drop;
3892
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003893 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003894 case L2CAP_MODE_BASIC:
3895 /* If socket recv buffers overflows we drop data here
3896 * which is *bad* because L2CAP has to be reliable.
3897 * But we don't have any other choice. L2CAP doesn't
3898 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003900 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003901 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003903 if (!sock_queue_rcv_skb(sk, skb))
3904 goto done;
3905 break;
3906
3907 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003908 if (!sock_owned_by_user(sk)) {
3909 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003910 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003911 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003912 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003913 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003914
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003915 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003916
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003917 case L2CAP_MODE_STREAMING:
3918 control = get_unaligned_le16(skb->data);
3919 skb_pull(skb, 2);
3920 len = skb->len;
3921
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003922 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003923 goto drop;
3924
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003925 if (__is_sar_start(control))
3926 len -= 2;
3927
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003928 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003929 len -= 2;
3930
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003931 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003932 goto drop;
3933
3934 tx_seq = __get_txseq(control);
3935
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003936 if (chan->expected_tx_seq == tx_seq)
3937 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003938 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003939 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003940
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003941 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003942
3943 goto done;
3944
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003945 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003946 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003947 break;
3948 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949
3950drop:
3951 kfree_skb(skb);
3952
3953done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003954 if (sk)
3955 bh_unlock_sock(sk);
3956
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957 return 0;
3958}
3959
Al Viro8e036fc2007-07-29 00:16:36 -07003960static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003962 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003963 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003965 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3966 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967 goto drop;
3968
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003969 sk = chan->sk;
3970
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003971 bh_lock_sock(sk);
3972
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973 BT_DBG("sk %p, len %d", sk, skb->len);
3974
3975 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3976 goto drop;
3977
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003978 if (l2cap_pi(sk)->chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003979 goto drop;
3980
3981 if (!sock_queue_rcv_skb(sk, skb))
3982 goto done;
3983
3984drop:
3985 kfree_skb(skb);
3986
3987done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003988 if (sk)
3989 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990 return 0;
3991}
3992
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003993static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3994{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003995 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003996 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003997
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003998 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3999 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004000 goto drop;
4001
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004002 sk = chan->sk;
4003
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004004 bh_lock_sock(sk);
4005
4006 BT_DBG("sk %p, len %d", sk, skb->len);
4007
4008 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
4009 goto drop;
4010
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004011 if (l2cap_pi(sk)->chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004012 goto drop;
4013
4014 if (!sock_queue_rcv_skb(sk, skb))
4015 goto done;
4016
4017drop:
4018 kfree_skb(skb);
4019
4020done:
4021 if (sk)
4022 bh_unlock_sock(sk);
4023 return 0;
4024}
4025
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4027{
4028 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004029 u16 cid, len;
4030 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031
4032 skb_pull(skb, L2CAP_HDR_SIZE);
4033 cid = __le16_to_cpu(lh->cid);
4034 len = __le16_to_cpu(lh->len);
4035
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004036 if (len != skb->len) {
4037 kfree_skb(skb);
4038 return;
4039 }
4040
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4042
4043 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004044 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004045 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046 l2cap_sig_channel(conn, skb);
4047 break;
4048
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004049 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004050 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051 skb_pull(skb, 2);
4052 l2cap_conless_channel(conn, psm, skb);
4053 break;
4054
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004055 case L2CAP_CID_LE_DATA:
4056 l2cap_att_channel(conn, cid, skb);
4057 break;
4058
Linus Torvalds1da177e2005-04-16 15:20:36 -07004059 default:
4060 l2cap_data_channel(conn, cid, skb);
4061 break;
4062 }
4063}
4064
4065/* ---- L2CAP interface with lower layer (HCI) ---- */
4066
4067static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4068{
4069 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004070 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071
4072 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004073 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074
4075 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4076
4077 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004078 read_lock(&chan_list_lock);
4079 list_for_each_entry(c, &chan_list, global_l) {
4080 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004081
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082 if (sk->sk_state != BT_LISTEN)
4083 continue;
4084
4085 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004086 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004087 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004088 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004090 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4091 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004092 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004093 lm2 |= HCI_LM_MASTER;
4094 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004096 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097
4098 return exact ? lm1 : lm2;
4099}
4100
4101static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4102{
Marcel Holtmann01394182006-07-03 10:02:46 +02004103 struct l2cap_conn *conn;
4104
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4106
Ville Tervoacd7d372011-02-10 22:38:49 -03004107 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004108 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004109
4110 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111 conn = l2cap_conn_add(hcon, status);
4112 if (conn)
4113 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004114 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115 l2cap_conn_del(hcon, bt_err(status));
4116
4117 return 0;
4118}
4119
Marcel Holtmann2950f212009-02-12 14:02:50 +01004120static int l2cap_disconn_ind(struct hci_conn *hcon)
4121{
4122 struct l2cap_conn *conn = hcon->l2cap_data;
4123
4124 BT_DBG("hcon %p", hcon);
4125
4126 if (hcon->type != ACL_LINK || !conn)
4127 return 0x13;
4128
4129 return conn->disc_reason;
4130}
4131
4132static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133{
4134 BT_DBG("hcon %p reason %d", hcon, reason);
4135
Ville Tervoacd7d372011-02-10 22:38:49 -03004136 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004137 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138
4139 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004140
Linus Torvalds1da177e2005-04-16 15:20:36 -07004141 return 0;
4142}
4143
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004144static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004145{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004146 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004147 return;
4148
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004149 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004150 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanab078012011-05-02 18:25:01 -03004151 l2cap_chan_clear_timer(chan);
4152 l2cap_chan_set_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004153 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004154 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004155 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004156 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanab078012011-05-02 18:25:01 -03004157 l2cap_chan_clear_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004158 }
4159}
4160
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004161static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004163 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004164 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165
Marcel Holtmann01394182006-07-03 10:02:46 +02004166 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004167 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004168
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169 BT_DBG("conn %p", conn);
4170
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004171 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004173 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004174 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004175
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176 bh_lock_sock(sk);
4177
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03004178 if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004179 bh_unlock_sock(sk);
4180 continue;
4181 }
4182
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004183 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004184 sk->sk_state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004185 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004186 bh_unlock_sock(sk);
4187 continue;
4188 }
4189
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004190 if (sk->sk_state == BT_CONNECT) {
4191 if (!status) {
4192 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004193 req.scid = cpu_to_le16(chan->scid);
4194 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004195
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004196 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03004197 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004198
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004199 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004200 L2CAP_CONN_REQ, sizeof(req), &req);
4201 } else {
Gustavo F. Padovanab078012011-05-02 18:25:01 -03004202 l2cap_chan_clear_timer(chan);
4203 l2cap_chan_set_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004204 }
4205 } else if (sk->sk_state == BT_CONNECT2) {
4206 struct l2cap_conn_rsp rsp;
4207 __u16 result;
4208
4209 if (!status) {
4210 sk->sk_state = BT_CONFIG;
4211 result = L2CAP_CR_SUCCESS;
4212 } else {
4213 sk->sk_state = BT_DISCONN;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03004214 l2cap_chan_set_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004215 result = L2CAP_CR_SEC_BLOCK;
4216 }
4217
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004218 rsp.scid = cpu_to_le16(chan->dcid);
4219 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004220 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02004221 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004222 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4223 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004224 }
4225
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226 bh_unlock_sock(sk);
4227 }
4228
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004229 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004230
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231 return 0;
4232}
4233
4234static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4235{
4236 struct l2cap_conn *conn = hcon->l2cap_data;
4237
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004238 if (!conn)
4239 conn = l2cap_conn_add(hcon, 0);
4240
4241 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242 goto drop;
4243
4244 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4245
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004246 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004248 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004249 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250 int len;
4251
4252 if (conn->rx_len) {
4253 BT_ERR("Unexpected start frame (len %d)", skb->len);
4254 kfree_skb(conn->rx_skb);
4255 conn->rx_skb = NULL;
4256 conn->rx_len = 0;
4257 l2cap_conn_unreliable(conn, ECOMM);
4258 }
4259
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004260 /* Start fragment always begin with Basic L2CAP header */
4261 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262 BT_ERR("Frame is too short (len %d)", skb->len);
4263 l2cap_conn_unreliable(conn, ECOMM);
4264 goto drop;
4265 }
4266
4267 hdr = (struct l2cap_hdr *) skb->data;
4268 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004269 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004270
4271 if (len == skb->len) {
4272 /* Complete frame received */
4273 l2cap_recv_frame(conn, skb);
4274 return 0;
4275 }
4276
4277 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4278
4279 if (skb->len > len) {
4280 BT_ERR("Frame is too long (len %d, expected len %d)",
4281 skb->len, len);
4282 l2cap_conn_unreliable(conn, ECOMM);
4283 goto drop;
4284 }
4285
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004286 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004287
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004288 if (chan && chan->sk) {
4289 struct sock *sk = chan->sk;
4290
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004291 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004292 BT_ERR("Frame exceeding recv MTU (len %d, "
4293 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004294 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004295 bh_unlock_sock(sk);
4296 l2cap_conn_unreliable(conn, ECOMM);
4297 goto drop;
4298 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004299 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004300 }
4301
Linus Torvalds1da177e2005-04-16 15:20:36 -07004302 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004303 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4304 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305 goto drop;
4306
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004307 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004308 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309 conn->rx_len = len - skb->len;
4310 } else {
4311 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4312
4313 if (!conn->rx_len) {
4314 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4315 l2cap_conn_unreliable(conn, ECOMM);
4316 goto drop;
4317 }
4318
4319 if (skb->len > conn->rx_len) {
4320 BT_ERR("Fragment is too long (len %d, expected %d)",
4321 skb->len, conn->rx_len);
4322 kfree_skb(conn->rx_skb);
4323 conn->rx_skb = NULL;
4324 conn->rx_len = 0;
4325 l2cap_conn_unreliable(conn, ECOMM);
4326 goto drop;
4327 }
4328
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004329 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004330 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004331 conn->rx_len -= skb->len;
4332
4333 if (!conn->rx_len) {
4334 /* Complete frame received */
4335 l2cap_recv_frame(conn, conn->rx_skb);
4336 conn->rx_skb = NULL;
4337 }
4338 }
4339
4340drop:
4341 kfree_skb(skb);
4342 return 0;
4343}
4344
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004345static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004347 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004348
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004349 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004351 list_for_each_entry(c, &chan_list, global_l) {
4352 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004353
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004354 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 +01004355 batostr(&bt_sk(sk)->src),
4356 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004357 sk->sk_state, __le16_to_cpu(c->psm),
4358 c->scid, c->dcid, c->imtu, c->omtu,
4359 c->sec_level, c->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004360 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004361
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004362 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004363
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004364 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365}
4366
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004367static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4368{
4369 return single_open(file, l2cap_debugfs_show, inode->i_private);
4370}
4371
4372static const struct file_operations l2cap_debugfs_fops = {
4373 .open = l2cap_debugfs_open,
4374 .read = seq_read,
4375 .llseek = seq_lseek,
4376 .release = single_release,
4377};
4378
4379static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380
Linus Torvalds1da177e2005-04-16 15:20:36 -07004381static struct hci_proto l2cap_hci_proto = {
4382 .name = "L2CAP",
4383 .id = HCI_PROTO_L2CAP,
4384 .connect_ind = l2cap_connect_ind,
4385 .connect_cfm = l2cap_connect_cfm,
4386 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004387 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004388 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004389 .recv_acldata = l2cap_recv_acldata
4390};
4391
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004392int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004393{
4394 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004395
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004396 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397 if (err < 0)
4398 return err;
4399
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004400 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004401 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004402 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403 goto error;
4404 }
4405
4406 err = hci_register_proto(&l2cap_hci_proto);
4407 if (err < 0) {
4408 BT_ERR("L2CAP protocol registration failed");
4409 bt_sock_unregister(BTPROTO_L2CAP);
4410 goto error;
4411 }
4412
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004413 if (bt_debugfs) {
4414 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4415 bt_debugfs, NULL, &l2cap_debugfs_fops);
4416 if (!l2cap_debugfs)
4417 BT_ERR("Failed to create L2CAP debug file");
4418 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004419
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420 return 0;
4421
4422error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004423 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004424 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004425 return err;
4426}
4427
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004428void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004430 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004431
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004432 flush_workqueue(_busy_wq);
4433 destroy_workqueue(_busy_wq);
4434
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4436 BT_ERR("L2CAP protocol unregistration failed");
4437
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004438 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439}
4440
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004441module_param(disable_ertm, bool, 0644);
4442MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");