blob: 248f68a9694bf798eb40547816f51d31e31446a3 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
7 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation;
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
16 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090017 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090022 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
23 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 SOFTWARE IS DISCLAIMED.
25*/
26
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020027/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30
31#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080032#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
34#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/poll.h>
38#include <linux/fcntl.h>
39#include <linux/init.h>
40#include <linux/interrupt.h>
41#include <linux/socket.h>
42#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080044#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010045#include <linux/debugfs.h>
46#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030047#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030048#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/sock.h>
50
51#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
57
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020058int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020059
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070060static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010061static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030063static struct workqueue_struct *_busy_wq;
64
Gustavo F. Padovan23691d72011-04-27 18:26:32 -030065LIST_HEAD(chan_list);
66DEFINE_RWLOCK(chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030068static void l2cap_busy_work(struct work_struct *work);
69
Linus Torvalds1da177e2005-04-16 15:20:36 -070070static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
71 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030072static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
73 void *data);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030074static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -030075static void l2cap_send_disconn_req(struct l2cap_conn *conn,
76 struct l2cap_chan *chan, int err);
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030078static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
79
Marcel Holtmann01394182006-07-03 10:02:46 +020080/* ---- L2CAP channels ---- */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030081static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020082{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030083 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030084
85 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030086 if (c->dcid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030087 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020088 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030089 return NULL;
90
Marcel Holtmann01394182006-07-03 10:02:46 +020091}
92
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030093static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020094{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030095 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030096
97 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -030098 if (c->scid == cid)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030099 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200100 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300101 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200102}
103
104/* Find channel with given SCID.
105 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300106static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200107{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300108 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300109
110 read_lock(&conn->chan_lock);
111 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300112 if (c)
113 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300114 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300115 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200116}
117
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300118static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200119{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300120 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300121
122 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300123 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300124 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200125 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300126 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200127}
128
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300129static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200130{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300131 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300132
133 read_lock(&conn->chan_lock);
134 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300135 if (c)
136 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300137 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300138 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200139}
140
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300141static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300142{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300143 struct l2cap_chan *c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300144
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300145 list_for_each_entry(c, &chan_list, global_l) {
146 if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300147 goto found;
148 }
149
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300150 c = NULL;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300151found:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300152 return c;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300153}
154
155int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
156{
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300157 int err;
158
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300159 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300160
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300161 if (psm && __l2cap_global_chan_by_addr(psm, src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300162 err = -EADDRINUSE;
163 goto done;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300164 }
165
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300166 if (psm) {
167 chan->psm = psm;
168 chan->sport = psm;
169 err = 0;
170 } else {
171 u16 p;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300172
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300173 err = -EINVAL;
174 for (p = 0x1001; p < 0x1100; p += 2)
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300175 if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300176 chan->psm = cpu_to_le16(p);
177 chan->sport = cpu_to_le16(p);
178 err = 0;
179 break;
180 }
181 }
182
183done:
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300184 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan73b2ec12011-04-18 19:36:44 -0300185 return err;
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300186}
187
188int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid)
189{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300190 write_lock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300191
192 chan->scid = scid;
193
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300194 write_unlock_bh(&chan_list_lock);
Gustavo F. Padovan9e4425f2011-04-18 18:38:43 -0300195
196 return 0;
197}
198
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300199static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200200{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300201 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200202
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300203 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300204 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200205 return cid;
206 }
207
208 return 0;
209}
210
Gustavo F. 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
253 __l2cap_chan_close(chan, reason);
254
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 -0300386/* Must be called on unlocked socket. */
387static void l2cap_chan_close(struct sock *sk)
388{
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300389 l2cap_chan_clear_timer(l2cap_pi(sk)->chan);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300390 lock_sock(sk);
391 __l2cap_chan_close(l2cap_pi(sk)->chan, ECONNRESET);
392 release_sock(sk);
393 l2cap_sock_kill(sk);
394}
395
396static void l2cap_chan_cleanup_listen(struct sock *parent)
397{
398 struct sock *sk;
399
400 BT_DBG("parent %p", parent);
401
402 /* Close not yet accepted channels */
403 while ((sk = bt_accept_dequeue(parent, NULL)))
404 l2cap_chan_close(sk);
405
406 parent->sk_state = BT_CLOSED;
407 sock_set_flag(parent, SOCK_ZAPPED);
408}
409
410void __l2cap_chan_close(struct l2cap_chan *chan, int reason)
411{
412 struct l2cap_conn *conn = chan->conn;
413 struct sock *sk = chan->sk;
414
415 BT_DBG("chan %p state %d socket %p", chan, sk->sk_state, sk->sk_socket);
416
417 switch (sk->sk_state) {
418 case BT_LISTEN:
419 l2cap_chan_cleanup_listen(sk);
420 break;
421
422 case BT_CONNECTED:
423 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300424 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300425 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovan500698d2011-05-04 19:35:27 -0300426 l2cap_chan_clear_timer(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300427 l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300428 l2cap_send_disconn_req(conn, chan, reason);
429 } else
430 l2cap_chan_del(chan, reason);
431 break;
432
433 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300434 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300435 conn->hcon->type == ACL_LINK) {
436 struct l2cap_conn_rsp rsp;
437 __u16 result;
438
439 if (bt_sk(sk)->defer_setup)
440 result = L2CAP_CR_SEC_BLOCK;
441 else
442 result = L2CAP_CR_BAD_PSM;
443
444 rsp.scid = cpu_to_le16(chan->dcid);
445 rsp.dcid = cpu_to_le16(chan->scid);
446 rsp.result = cpu_to_le16(result);
447 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
448 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
449 sizeof(rsp), &rsp);
450 }
451
452 l2cap_chan_del(chan, reason);
453 break;
454
455 case BT_CONNECT:
456 case BT_DISCONN:
457 l2cap_chan_del(chan, reason);
458 break;
459
460 default:
461 sock_set_flag(sk, SOCK_ZAPPED);
462 break;
463 }
464}
465
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300466static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530467{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300468 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300469 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530470 case BT_SECURITY_HIGH:
471 return HCI_AT_DEDICATED_BONDING_MITM;
472 case BT_SECURITY_MEDIUM:
473 return HCI_AT_DEDICATED_BONDING;
474 default:
475 return HCI_AT_NO_BONDING;
476 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300477 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300478 if (chan->sec_level == BT_SECURITY_LOW)
479 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530480
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300481 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530482 return HCI_AT_NO_BONDING_MITM;
483 else
484 return HCI_AT_NO_BONDING;
485 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300486 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530487 case BT_SECURITY_HIGH:
488 return HCI_AT_GENERAL_BONDING_MITM;
489 case BT_SECURITY_MEDIUM:
490 return HCI_AT_GENERAL_BONDING;
491 default:
492 return HCI_AT_NO_BONDING;
493 }
494 }
495}
496
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200497/* Service level security */
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300498static inline int l2cap_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200499{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300500 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100501 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200502
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300503 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100504
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300505 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200506}
507
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200508u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200509{
510 u8 id;
511
512 /* Get next available identificator.
513 * 1 - 128 are used by kernel.
514 * 129 - 199 are reserved.
515 * 200 - 254 are used by utilities like l2ping, etc.
516 */
517
518 spin_lock_bh(&conn->lock);
519
520 if (++conn->tx_ident > 128)
521 conn->tx_ident = 1;
522
523 id = conn->tx_ident;
524
525 spin_unlock_bh(&conn->lock);
526
527 return id;
528}
529
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300530static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200531{
532 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200533 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200534
535 BT_DBG("code 0x%2.2x", code);
536
537 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300538 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200539
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200540 if (lmp_no_flush_capable(conn->hcon->hdev))
541 flags = ACL_START_NO_FLUSH;
542 else
543 flags = ACL_START;
544
545 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200546}
547
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300548static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300549{
550 struct sk_buff *skb;
551 struct l2cap_hdr *lh;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300552 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300553 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300554 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300555 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200556 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300557
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300558 if (sk->sk_state != BT_CONNECTED)
559 return;
560
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300561 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300562 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300563
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300564 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300565
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300566 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300567 control |= L2CAP_CTRL_FRAME_TYPE;
568
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300569 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300570 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300571 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300572 }
573
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300574 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300575 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300576 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300577 }
578
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300579 skb = bt_skb_alloc(count, GFP_ATOMIC);
580 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300581 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300582
583 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300584 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300585 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300586 put_unaligned_le16(control, skb_put(skb, 2));
587
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300588 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300589 u16 fcs = crc16(0, (u8 *)lh, count - 2);
590 put_unaligned_le16(fcs, skb_put(skb, 2));
591 }
592
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200593 if (lmp_no_flush_capable(conn->hcon->hdev))
594 flags = ACL_START_NO_FLUSH;
595 else
596 flags = ACL_START;
597
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300598 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300599}
600
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300601static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300602{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300603 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300604 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300605 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300606 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300607 control |= L2CAP_SUPER_RCV_READY;
608
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300609 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300610
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300611 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300612}
613
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300614static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300615{
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300616 return !(chan->conf_state & L2CAP_CONF_CONNECT_PEND);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300617}
618
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300619static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200620{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300621 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200622
623 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100624 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
625 return;
626
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300627 if (l2cap_check_security(chan) &&
628 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200629 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300630 req.scid = cpu_to_le16(chan->scid);
631 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200632
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300633 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300634 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200635
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300636 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
637 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200638 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200639 } else {
640 struct l2cap_info_req req;
641 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
642
643 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
644 conn->info_ident = l2cap_get_ident(conn);
645
646 mod_timer(&conn->info_timer, jiffies +
647 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
648
649 l2cap_send_cmd(conn, conn->info_ident,
650 L2CAP_INFO_REQ, sizeof(req), &req);
651 }
652}
653
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300654static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
655{
656 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300657 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300658 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
659
660 switch (mode) {
661 case L2CAP_MODE_ERTM:
662 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
663 case L2CAP_MODE_STREAMING:
664 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
665 default:
666 return 0x00;
667 }
668}
669
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300670static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300671{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300672 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300673 struct l2cap_disconn_req req;
674
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300675 if (!conn)
676 return;
677
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300678 sk = chan->sk;
679
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300680 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300681 del_timer(&chan->retrans_timer);
682 del_timer(&chan->monitor_timer);
683 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300684 }
685
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300686 req.dcid = cpu_to_le16(chan->dcid);
687 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300688 l2cap_send_cmd(conn, l2cap_get_ident(conn),
689 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300690
691 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300692 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300693}
694
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200696static void l2cap_conn_start(struct l2cap_conn *conn)
697{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300698 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200699
700 BT_DBG("conn %p", conn);
701
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300702 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200703
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300704 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300705 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300706
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200707 bh_lock_sock(sk);
708
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300709 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200710 bh_unlock_sock(sk);
711 continue;
712 }
713
714 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300715 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300716
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300717 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300718 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300719 bh_unlock_sock(sk);
720 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200721 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300722
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300723 if (!l2cap_mode_supported(chan->mode,
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300724 conn->feat_mask)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300725 && chan->conf_state &
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300726 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300727 /* __l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300728 * so release the lock */
729 read_unlock_bh(&conn->chan_lock);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300730 __l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300731 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300732 bh_unlock_sock(sk);
733 continue;
734 }
735
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300736 req.scid = cpu_to_le16(chan->scid);
737 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300738
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300739 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300740 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300741
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300742 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
743 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300744
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200745 } else if (sk->sk_state == BT_CONNECT2) {
746 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300747 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300748 rsp.scid = cpu_to_le16(chan->dcid);
749 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200750
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300751 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100752 if (bt_sk(sk)->defer_setup) {
753 struct sock *parent = bt_sk(sk)->parent;
754 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
755 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
756 parent->sk_data_ready(parent, 0);
757
758 } else {
759 sk->sk_state = BT_CONFIG;
760 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
761 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
762 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200763 } else {
764 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
765 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
766 }
767
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300768 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
769 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300770
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300771 if (chan->conf_state & L2CAP_CONF_REQ_SENT ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300772 rsp.result != L2CAP_CR_SUCCESS) {
773 bh_unlock_sock(sk);
774 continue;
775 }
776
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300777 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300778 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300779 l2cap_build_conf_req(chan, buf), buf);
780 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200781 }
782
783 bh_unlock_sock(sk);
784 }
785
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300786 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200787}
788
Ville Tervob62f3282011-02-10 22:38:50 -0300789/* Find socket with cid and source bdaddr.
790 * Returns closest match, locked.
791 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300792static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300793{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300794 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300795
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300796 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300797
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300798 list_for_each_entry(c, &chan_list, global_l) {
799 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300800
Ville Tervob62f3282011-02-10 22:38:50 -0300801 if (state && sk->sk_state != state)
802 continue;
803
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300804 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300805 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300806 if (!bacmp(&bt_sk(sk)->src, src)) {
807 read_unlock(&chan_list_lock);
808 return c;
809 }
Ville Tervob62f3282011-02-10 22:38:50 -0300810
811 /* Closest match */
812 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300813 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300814 }
815 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300816
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300817 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300818
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300819 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300820}
821
822static void l2cap_le_conn_ready(struct l2cap_conn *conn)
823{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300824 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300825 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300826
827 BT_DBG("");
828
829 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300830 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300831 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300832 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300833 return;
834
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300835 parent = pchan->sk;
836
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300837 bh_lock_sock(parent);
838
Ville Tervob62f3282011-02-10 22:38:50 -0300839 /* Check for backlog size */
840 if (sk_acceptq_is_full(parent)) {
841 BT_DBG("backlog full %d", parent->sk_ack_backlog);
842 goto clean;
843 }
844
845 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
846 if (!sk)
847 goto clean;
848
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300849 chan = l2cap_chan_create(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300850 if (!chan) {
851 l2cap_sock_kill(sk);
852 goto clean;
853 }
854
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300855 l2cap_pi(sk)->chan = chan;
856
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300857 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300858
859 hci_conn_hold(conn->hcon);
860
861 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300862
Ville Tervob62f3282011-02-10 22:38:50 -0300863 bacpy(&bt_sk(sk)->src, conn->src);
864 bacpy(&bt_sk(sk)->dst, conn->dst);
865
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300866 bt_accept_enqueue(parent, sk);
867
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300868 __l2cap_chan_add(conn, chan);
869
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300870 l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300871
872 sk->sk_state = BT_CONNECTED;
873 parent->sk_data_ready(parent, 0);
874
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300875 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300876
877clean:
878 bh_unlock_sock(parent);
879}
880
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200881static void l2cap_conn_ready(struct l2cap_conn *conn)
882{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300883 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200884
885 BT_DBG("conn %p", conn);
886
Ville Tervob62f3282011-02-10 22:38:50 -0300887 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
888 l2cap_le_conn_ready(conn);
889
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300890 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200891
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300892 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300893 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300894
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200895 bh_lock_sock(sk);
896
Ville Tervoacd7d372011-02-10 22:38:49 -0300897 if (conn->hcon->type == LE_LINK) {
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300898 l2cap_chan_clear_timer(chan);
Ville Tervoacd7d372011-02-10 22:38:49 -0300899 sk->sk_state = BT_CONNECTED;
900 sk->sk_state_change(sk);
901 }
902
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300903 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300904 l2cap_chan_clear_timer(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200905 sk->sk_state = BT_CONNECTED;
906 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200907 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300908 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200909
910 bh_unlock_sock(sk);
911 }
912
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300913 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200914}
915
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200916/* Notify sockets that we cannot guaranty reliability anymore */
917static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
918{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300919 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200920
921 BT_DBG("conn %p", conn);
922
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300923 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200924
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300925 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300926 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300927
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300928 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200929 sk->sk_err = err;
930 }
931
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300932 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200933}
934
935static void l2cap_info_timeout(unsigned long arg)
936{
937 struct l2cap_conn *conn = (void *) arg;
938
Marcel Holtmann984947d2009-02-06 23:35:19 +0100939 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100940 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100941
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200942 l2cap_conn_start(conn);
943}
944
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
946{
Marcel Holtmann01394182006-07-03 10:02:46 +0200947 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948
Marcel Holtmann01394182006-07-03 10:02:46 +0200949 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 return conn;
951
Marcel Holtmann01394182006-07-03 10:02:46 +0200952 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
953 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955
956 hcon->l2cap_data = conn;
957 conn->hcon = hcon;
958
Marcel Holtmann01394182006-07-03 10:02:46 +0200959 BT_DBG("hcon %p conn %p", hcon, conn);
960
Ville Tervoacd7d372011-02-10 22:38:49 -0300961 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
962 conn->mtu = hcon->hdev->le_mtu;
963 else
964 conn->mtu = hcon->hdev->acl_mtu;
965
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 conn->src = &hcon->hdev->bdaddr;
967 conn->dst = &hcon->dst;
968
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200969 conn->feat_mask = 0;
970
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300972 rwlock_init(&conn->chan_lock);
973
974 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975
Ville Tervob62f3282011-02-10 22:38:50 -0300976 if (hcon->type != LE_LINK)
977 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000978 (unsigned long) conn);
979
Marcel Holtmann2950f212009-02-12 14:02:50 +0100980 conn->disc_reason = 0x13;
981
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 return conn;
983}
984
Marcel Holtmann01394182006-07-03 10:02:46 +0200985static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986{
Marcel Holtmann01394182006-07-03 10:02:46 +0200987 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300988 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 struct sock *sk;
990
Marcel Holtmann01394182006-07-03 10:02:46 +0200991 if (!conn)
992 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993
994 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
995
Wei Yongjun7585b972009-02-25 18:29:52 +0800996 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997
998 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300999 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001000 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001002 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 bh_unlock_sock(sk);
1004 l2cap_sock_kill(sk);
1005 }
1006
Dave Young8e8440f2008-03-03 12:18:55 -08001007 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1008 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -08001009
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 hcon->l2cap_data = NULL;
1011 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012}
1013
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001014static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001016 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001017 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001018 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019}
1020
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022
1023/* Find socket with psm and source bdaddr.
1024 * Returns closest match.
1025 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001026static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001028 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001030 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001031
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001032 list_for_each_entry(c, &chan_list, global_l) {
1033 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001034
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 if (state && sk->sk_state != state)
1036 continue;
1037
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001038 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001040 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001041 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001042 return c;
1043 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044
1045 /* Closest match */
1046 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001047 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 }
1049 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001051 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001052
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001053 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054}
1055
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001056int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001058 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 bdaddr_t *src = &bt_sk(sk)->src;
1060 bdaddr_t *dst = &bt_sk(sk)->dst;
1061 struct l2cap_conn *conn;
1062 struct hci_conn *hcon;
1063 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001064 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001065 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001067 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001068 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001070 hdev = hci_get_route(dst, src);
1071 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 return -EHOSTUNREACH;
1073
1074 hci_dev_lock_bh(hdev);
1075
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001076 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001077
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001078 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001079 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001080 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001081 else
1082 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001083 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001084
Ville Tervo30e76272011-02-22 16:10:53 -03001085 if (IS_ERR(hcon)) {
1086 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001088 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
1090 conn = l2cap_conn_add(hcon, 0);
1091 if (!conn) {
1092 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001093 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 goto done;
1095 }
1096
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 /* Update source addr of the socket */
1098 bacpy(src, conn->src);
1099
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001100 l2cap_chan_add(conn, chan);
1101
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 sk->sk_state = BT_CONNECT;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03001103 l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104
1105 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001106 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanab078012011-05-02 18:25:01 -03001107 l2cap_chan_clear_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001108 if (l2cap_check_security(chan))
Johan Hedbergd00ef242011-01-19 12:06:51 +05301109 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001110 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001111 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 }
1113
Ville Tervo30e76272011-02-22 16:10:53 -03001114 err = 0;
1115
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116done:
1117 hci_dev_unlock_bh(hdev);
1118 hci_dev_put(hdev);
1119 return err;
1120}
1121
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001122int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001123{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001124 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001125 DECLARE_WAITQUEUE(wait, current);
1126 int err = 0;
1127 int timeo = HZ/5;
1128
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001129 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001130 while ((chan->unacked_frames > 0 && chan->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001131 set_current_state(TASK_INTERRUPTIBLE);
1132
1133 if (!timeo)
1134 timeo = HZ/5;
1135
1136 if (signal_pending(current)) {
1137 err = sock_intr_errno(timeo);
1138 break;
1139 }
1140
1141 release_sock(sk);
1142 timeo = schedule_timeout(timeo);
1143 lock_sock(sk);
1144
1145 err = sock_error(sk);
1146 if (err)
1147 break;
1148 }
1149 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001150 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001151 return err;
1152}
1153
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001154static void l2cap_monitor_timeout(unsigned long arg)
1155{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001156 struct l2cap_chan *chan = (void *) arg;
1157 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001158
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001159 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001160
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001161 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001162 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001163 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001164 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001165 return;
1166 }
1167
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001168 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001169 __mod_monitor_timer();
1170
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001171 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001172 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001173}
1174
1175static void l2cap_retrans_timeout(unsigned long arg)
1176{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001177 struct l2cap_chan *chan = (void *) arg;
1178 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001179
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001180 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001181
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001182 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001183 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001184 __mod_monitor_timer();
1185
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001186 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001187
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001188 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001189 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001190}
1191
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001192static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001193{
1194 struct sk_buff *skb;
1195
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001196 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001197 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001198 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001199 break;
1200
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001201 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001202 kfree_skb(skb);
1203
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001204 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001205 }
1206
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001207 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001208 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001209}
1210
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001211void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001212{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001213 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001214 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001215
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001216 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001217
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001218 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001219 flags = ACL_START_NO_FLUSH;
1220 else
1221 flags = ACL_START;
1222
1223 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 Vitabfbacc112010-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 Vitabfbacc112010-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 Vitabfbacc112010-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 Vitabfbacc112010-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. Padovan4519de92011-04-28 17:55:53 -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");