blob: c630a0e8c5f9d2fcf52f98bc21b52138b17885f2 [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
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300253 l2cap_chan_close(chan, reason);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300254
255 bh_unlock_sock(sk);
256
257 l2cap_sock_kill(sk);
258 sock_put(sk);
259}
260
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300261struct l2cap_chan *l2cap_chan_create(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200262{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300263 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200264
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300265 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
266 if (!chan)
267 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200268
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300269 chan->sk = sk;
270
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300271 write_lock_bh(&chan_list_lock);
272 list_add(&chan->global_l, &chan_list);
273 write_unlock_bh(&chan_list_lock);
274
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300275 setup_timer(&chan->chan_timer, l2cap_chan_timeout, (unsigned long) chan);
276
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300277 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200278}
279
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300280void l2cap_chan_destroy(struct l2cap_chan *chan)
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300281{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300282 write_lock_bh(&chan_list_lock);
283 list_del(&chan->global_l);
284 write_unlock_bh(&chan_list_lock);
285
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300286 kfree(chan);
287}
288
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300289static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200290{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300291 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200292
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300293 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300294 chan->psm, chan->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200295
Marcel Holtmann2950f212009-02-12 14:02:50 +0100296 conn->disc_reason = 0x13;
297
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300298 chan->conn = conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200299
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300300 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
Ville Tervob62f3282011-02-10 22:38:50 -0300301 if (conn->hcon->type == LE_LINK) {
302 /* LE connection */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300303 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300304 chan->scid = L2CAP_CID_LE_DATA;
305 chan->dcid = L2CAP_CID_LE_DATA;
Ville Tervob62f3282011-02-10 22:38:50 -0300306 } else {
307 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300308 chan->scid = l2cap_alloc_cid(conn);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300309 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300310 }
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300311 } else if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200312 /* Connectionless socket */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300313 chan->scid = L2CAP_CID_CONN_LESS;
314 chan->dcid = L2CAP_CID_CONN_LESS;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300315 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200316 } else {
317 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300318 chan->scid = L2CAP_CID_SIGNALING;
319 chan->dcid = L2CAP_CID_SIGNALING;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300320 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200321 }
322
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300323 sock_hold(sk);
324
325 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200326}
327
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900328/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200329 * Must be called on the locked socket. */
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300330static void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200331{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300332 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300333 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann01394182006-07-03 10:02:46 +0200334 struct sock *parent = bt_sk(sk)->parent;
335
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300336 l2cap_chan_clear_timer(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200337
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300338 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200339
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900340 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300341 /* Delete from channel list */
342 write_lock_bh(&conn->chan_lock);
343 list_del(&chan->list);
344 write_unlock_bh(&conn->chan_lock);
345 __sock_put(sk);
346
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300347 chan->conn = NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200348 hci_conn_put(conn->hcon);
349 }
350
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200351 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200352 sock_set_flag(sk, SOCK_ZAPPED);
353
354 if (err)
355 sk->sk_err = err;
356
357 if (parent) {
358 bt_accept_unlink(sk);
359 parent->sk_data_ready(parent, 0);
360 } else
361 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300362
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300363 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE &&
364 chan->conf_state & L2CAP_CONF_INPUT_DONE))
Gustavo F. Padovan6ff5abb2011-04-25 15:10:41 -0300365 return;
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300366
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300367 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300368
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300369 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300370 struct srej_list *l, *tmp;
371
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300372 del_timer(&chan->retrans_timer);
373 del_timer(&chan->monitor_timer);
374 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300375
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300376 skb_queue_purge(&chan->srej_q);
377 skb_queue_purge(&chan->busy_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300378
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300379 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300380 list_del(&l->list);
381 kfree(l);
382 }
383 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200384}
385
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300386static void l2cap_chan_cleanup_listen(struct sock *parent)
387{
388 struct sock *sk;
389
390 BT_DBG("parent %p", parent);
391
392 /* Close not yet accepted channels */
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300393 while ((sk = bt_accept_dequeue(parent, NULL))) {
394 l2cap_chan_clear_timer(l2cap_pi(sk)->chan);
395 lock_sock(sk);
396 l2cap_chan_close(l2cap_pi(sk)->chan, ECONNRESET);
397 release_sock(sk);
398 l2cap_sock_kill(sk);
399 }
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300400
401 parent->sk_state = BT_CLOSED;
402 sock_set_flag(parent, SOCK_ZAPPED);
403}
404
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300405void l2cap_chan_close(struct l2cap_chan *chan, int reason)
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300406{
407 struct l2cap_conn *conn = chan->conn;
408 struct sock *sk = chan->sk;
409
410 BT_DBG("chan %p state %d socket %p", chan, sk->sk_state, sk->sk_socket);
411
412 switch (sk->sk_state) {
413 case BT_LISTEN:
414 l2cap_chan_cleanup_listen(sk);
415 break;
416
417 case BT_CONNECTED:
418 case BT_CONFIG:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300419 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300420 conn->hcon->type == ACL_LINK) {
Gustavo F. Padovan500698d2011-05-04 19:35:27 -0300421 l2cap_chan_clear_timer(chan);
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300422 l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300423 l2cap_send_disconn_req(conn, chan, reason);
424 } else
425 l2cap_chan_del(chan, reason);
426 break;
427
428 case BT_CONNECT2:
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300429 if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300430 conn->hcon->type == ACL_LINK) {
431 struct l2cap_conn_rsp rsp;
432 __u16 result;
433
434 if (bt_sk(sk)->defer_setup)
435 result = L2CAP_CR_SEC_BLOCK;
436 else
437 result = L2CAP_CR_BAD_PSM;
438
439 rsp.scid = cpu_to_le16(chan->dcid);
440 rsp.dcid = cpu_to_le16(chan->scid);
441 rsp.result = cpu_to_le16(result);
442 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
443 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
444 sizeof(rsp), &rsp);
445 }
446
447 l2cap_chan_del(chan, reason);
448 break;
449
450 case BT_CONNECT:
451 case BT_DISCONN:
452 l2cap_chan_del(chan, reason);
453 break;
454
455 default:
456 sock_set_flag(sk, SOCK_ZAPPED);
457 break;
458 }
459}
460
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300461static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530462{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300463 if (chan->chan_type == L2CAP_CHAN_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300464 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530465 case BT_SECURITY_HIGH:
466 return HCI_AT_DEDICATED_BONDING_MITM;
467 case BT_SECURITY_MEDIUM:
468 return HCI_AT_DEDICATED_BONDING;
469 default:
470 return HCI_AT_NO_BONDING;
471 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300472 } else if (chan->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300473 if (chan->sec_level == BT_SECURITY_LOW)
474 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530475
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300476 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530477 return HCI_AT_NO_BONDING_MITM;
478 else
479 return HCI_AT_NO_BONDING;
480 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300481 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530482 case BT_SECURITY_HIGH:
483 return HCI_AT_GENERAL_BONDING_MITM;
484 case BT_SECURITY_MEDIUM:
485 return HCI_AT_GENERAL_BONDING;
486 default:
487 return HCI_AT_NO_BONDING;
488 }
489 }
490}
491
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200492/* Service level security */
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300493static inline int l2cap_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200494{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300495 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100496 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200497
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300498 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100499
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300500 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200501}
502
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200503u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200504{
505 u8 id;
506
507 /* Get next available identificator.
508 * 1 - 128 are used by kernel.
509 * 129 - 199 are reserved.
510 * 200 - 254 are used by utilities like l2ping, etc.
511 */
512
513 spin_lock_bh(&conn->lock);
514
515 if (++conn->tx_ident > 128)
516 conn->tx_ident = 1;
517
518 id = conn->tx_ident;
519
520 spin_unlock_bh(&conn->lock);
521
522 return id;
523}
524
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300525static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200526{
527 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200528 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200529
530 BT_DBG("code 0x%2.2x", code);
531
532 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300533 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200534
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200535 if (lmp_no_flush_capable(conn->hcon->hdev))
536 flags = ACL_START_NO_FLUSH;
537 else
538 flags = ACL_START;
539
540 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200541}
542
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300543static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300544{
545 struct sk_buff *skb;
546 struct l2cap_hdr *lh;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300547 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300548 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300549 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300550 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200551 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300552
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300553 if (sk->sk_state != BT_CONNECTED)
554 return;
555
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300556 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300557 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300558
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300559 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300560
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300561 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300562 control |= L2CAP_CTRL_FRAME_TYPE;
563
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300564 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300565 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300566 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300567 }
568
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300569 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300570 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300571 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300572 }
573
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300574 skb = bt_skb_alloc(count, GFP_ATOMIC);
575 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300576 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300577
578 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300579 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300580 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300581 put_unaligned_le16(control, skb_put(skb, 2));
582
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -0300583 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300584 u16 fcs = crc16(0, (u8 *)lh, count - 2);
585 put_unaligned_le16(fcs, skb_put(skb, 2));
586 }
587
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200588 if (lmp_no_flush_capable(conn->hcon->hdev))
589 flags = ACL_START_NO_FLUSH;
590 else
591 flags = ACL_START;
592
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300593 hci_send_acl(chan->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300594}
595
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300596static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300597{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300598 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300599 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300600 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300601 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300602 control |= L2CAP_SUPER_RCV_READY;
603
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300604 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300605
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300606 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300607}
608
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300609static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300610{
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300611 return !(chan->conf_state & L2CAP_CONF_CONNECT_PEND);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300612}
613
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300614static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200615{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -0300616 struct l2cap_conn *conn = chan->conn;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200617
618 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100619 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
620 return;
621
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300622 if (l2cap_check_security(chan) &&
623 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200624 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300625 req.scid = cpu_to_le16(chan->scid);
626 req.psm = chan->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200627
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300628 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300629 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200630
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300631 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
632 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200633 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200634 } else {
635 struct l2cap_info_req req;
636 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
637
638 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
639 conn->info_ident = l2cap_get_ident(conn);
640
641 mod_timer(&conn->info_timer, jiffies +
642 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
643
644 l2cap_send_cmd(conn, conn->info_ident,
645 L2CAP_INFO_REQ, sizeof(req), &req);
646 }
647}
648
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300649static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
650{
651 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300652 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300653 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
654
655 switch (mode) {
656 case L2CAP_MODE_ERTM:
657 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
658 case L2CAP_MODE_STREAMING:
659 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
660 default:
661 return 0x00;
662 }
663}
664
Gustavo F. Padovan4519de92011-04-28 17:55:53 -0300665static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300666{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300667 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300668 struct l2cap_disconn_req req;
669
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300670 if (!conn)
671 return;
672
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300673 sk = chan->sk;
674
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300675 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300676 del_timer(&chan->retrans_timer);
677 del_timer(&chan->monitor_timer);
678 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300679 }
680
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300681 req.dcid = cpu_to_le16(chan->dcid);
682 req.scid = cpu_to_le16(chan->scid);
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300683 l2cap_send_cmd(conn, l2cap_get_ident(conn),
684 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300685
686 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300687 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300688}
689
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200691static void l2cap_conn_start(struct l2cap_conn *conn)
692{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300693 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200694
695 BT_DBG("conn %p", conn);
696
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300697 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200698
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300699 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300700 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300701
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200702 bh_lock_sock(sk);
703
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300704 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200705 bh_unlock_sock(sk);
706 continue;
707 }
708
709 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300710 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300711
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300712 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300713 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300714 bh_unlock_sock(sk);
715 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200716 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300717
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300718 if (!l2cap_mode_supported(chan->mode,
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300719 conn->feat_mask)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300720 && chan->conf_state &
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300721 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300722 /* l2cap_chan_close() calls list_del(chan)
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300723 * so release the lock */
724 read_unlock_bh(&conn->chan_lock);
Gustavo F. Padovan0f852722011-05-04 19:42:50 -0300725 l2cap_chan_close(chan, ECONNRESET);
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300726 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300727 bh_unlock_sock(sk);
728 continue;
729 }
730
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300731 req.scid = cpu_to_le16(chan->scid);
732 req.psm = chan->psm;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300733
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300734 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300735 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300736
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300737 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
738 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300739
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200740 } else if (sk->sk_state == BT_CONNECT2) {
741 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300742 char buf[128];
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300743 rsp.scid = cpu_to_le16(chan->dcid);
744 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200745
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300746 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100747 if (bt_sk(sk)->defer_setup) {
748 struct sock *parent = bt_sk(sk)->parent;
749 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
750 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
751 parent->sk_data_ready(parent, 0);
752
753 } else {
754 sk->sk_state = BT_CONFIG;
755 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
756 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
757 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200758 } else {
759 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
760 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
761 }
762
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300763 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
764 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300765
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300766 if (chan->conf_state & L2CAP_CONF_REQ_SENT ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300767 rsp.result != L2CAP_CR_SUCCESS) {
768 bh_unlock_sock(sk);
769 continue;
770 }
771
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300772 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300773 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300774 l2cap_build_conf_req(chan, buf), buf);
775 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200776 }
777
778 bh_unlock_sock(sk);
779 }
780
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300781 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200782}
783
Ville Tervob62f3282011-02-10 22:38:50 -0300784/* Find socket with cid and source bdaddr.
785 * Returns closest match, locked.
786 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300787static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
Ville Tervob62f3282011-02-10 22:38:50 -0300788{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300789 struct l2cap_chan *c, *c1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300790
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300791 read_lock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300792
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300793 list_for_each_entry(c, &chan_list, global_l) {
794 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -0300795
Ville Tervob62f3282011-02-10 22:38:50 -0300796 if (state && sk->sk_state != state)
797 continue;
798
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300799 if (c->scid == cid) {
Ville Tervob62f3282011-02-10 22:38:50 -0300800 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300801 if (!bacmp(&bt_sk(sk)->src, src)) {
802 read_unlock(&chan_list_lock);
803 return c;
804 }
Ville Tervob62f3282011-02-10 22:38:50 -0300805
806 /* Closest match */
807 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300808 c1 = c;
Ville Tervob62f3282011-02-10 22:38:50 -0300809 }
810 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300811
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300812 read_unlock(&chan_list_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300813
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300814 return c1;
Ville Tervob62f3282011-02-10 22:38:50 -0300815}
816
817static void l2cap_le_conn_ready(struct l2cap_conn *conn)
818{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300819 struct sock *parent, *sk;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300820 struct l2cap_chan *chan, *pchan;
Ville Tervob62f3282011-02-10 22:38:50 -0300821
822 BT_DBG("");
823
824 /* Check if we have socket listening on cid */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300825 pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
Ville Tervob62f3282011-02-10 22:38:50 -0300826 conn->src);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300827 if (!pchan)
Ville Tervob62f3282011-02-10 22:38:50 -0300828 return;
829
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300830 parent = pchan->sk;
831
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300832 bh_lock_sock(parent);
833
Ville Tervob62f3282011-02-10 22:38:50 -0300834 /* Check for backlog size */
835 if (sk_acceptq_is_full(parent)) {
836 BT_DBG("backlog full %d", parent->sk_ack_backlog);
837 goto clean;
838 }
839
840 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
841 if (!sk)
842 goto clean;
843
Gustavo F. Padovan23691d72011-04-27 18:26:32 -0300844 chan = l2cap_chan_create(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300845 if (!chan) {
846 l2cap_sock_kill(sk);
847 goto clean;
848 }
849
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300850 l2cap_pi(sk)->chan = chan;
851
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300852 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300853
854 hci_conn_hold(conn->hcon);
855
856 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300857
Ville Tervob62f3282011-02-10 22:38:50 -0300858 bacpy(&bt_sk(sk)->src, conn->src);
859 bacpy(&bt_sk(sk)->dst, conn->dst);
860
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300861 bt_accept_enqueue(parent, sk);
862
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300863 __l2cap_chan_add(conn, chan);
864
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300865 l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
Ville Tervob62f3282011-02-10 22:38:50 -0300866
867 sk->sk_state = BT_CONNECTED;
868 parent->sk_data_ready(parent, 0);
869
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300870 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300871
872clean:
873 bh_unlock_sock(parent);
874}
875
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200876static void l2cap_conn_ready(struct l2cap_conn *conn)
877{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300878 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200879
880 BT_DBG("conn %p", conn);
881
Ville Tervob62f3282011-02-10 22:38:50 -0300882 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
883 l2cap_le_conn_ready(conn);
884
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300885 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200886
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300887 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300888 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300889
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200890 bh_lock_sock(sk);
891
Ville Tervoacd7d372011-02-10 22:38:49 -0300892 if (conn->hcon->type == LE_LINK) {
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300893 l2cap_chan_clear_timer(chan);
Ville Tervoacd7d372011-02-10 22:38:49 -0300894 sk->sk_state = BT_CONNECTED;
895 sk->sk_state_change(sk);
896 }
897
Gustavo F. Padovan715ec002011-05-02 17:13:55 -0300898 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanab078012011-05-02 18:25:01 -0300899 l2cap_chan_clear_timer(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200900 sk->sk_state = BT_CONNECTED;
901 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200902 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300903 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200904
905 bh_unlock_sock(sk);
906 }
907
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300908 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200909}
910
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200911/* Notify sockets that we cannot guaranty reliability anymore */
912static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
913{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300914 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200915
916 BT_DBG("conn %p", conn);
917
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300918 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200919
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300920 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300921 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300922
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300923 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200924 sk->sk_err = err;
925 }
926
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300927 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200928}
929
930static void l2cap_info_timeout(unsigned long arg)
931{
932 struct l2cap_conn *conn = (void *) arg;
933
Marcel Holtmann984947d2009-02-06 23:35:19 +0100934 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100935 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100936
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200937 l2cap_conn_start(conn);
938}
939
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
941{
Marcel Holtmann01394182006-07-03 10:02:46 +0200942 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943
Marcel Holtmann01394182006-07-03 10:02:46 +0200944 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 return conn;
946
Marcel Holtmann01394182006-07-03 10:02:46 +0200947 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
948 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950
951 hcon->l2cap_data = conn;
952 conn->hcon = hcon;
953
Marcel Holtmann01394182006-07-03 10:02:46 +0200954 BT_DBG("hcon %p conn %p", hcon, conn);
955
Ville Tervoacd7d372011-02-10 22:38:49 -0300956 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
957 conn->mtu = hcon->hdev->le_mtu;
958 else
959 conn->mtu = hcon->hdev->acl_mtu;
960
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 conn->src = &hcon->hdev->bdaddr;
962 conn->dst = &hcon->dst;
963
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200964 conn->feat_mask = 0;
965
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300967 rwlock_init(&conn->chan_lock);
968
969 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970
Ville Tervob62f3282011-02-10 22:38:50 -0300971 if (hcon->type != LE_LINK)
972 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000973 (unsigned long) conn);
974
Marcel Holtmann2950f212009-02-12 14:02:50 +0100975 conn->disc_reason = 0x13;
976
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 return conn;
978}
979
Marcel Holtmann01394182006-07-03 10:02:46 +0200980static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981{
Marcel Holtmann01394182006-07-03 10:02:46 +0200982 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300983 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 struct sock *sk;
985
Marcel Holtmann01394182006-07-03 10:02:46 +0200986 if (!conn)
987 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988
989 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
990
Wei Yongjun7585b972009-02-25 18:29:52 +0800991 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992
993 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300994 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300995 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300997 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 bh_unlock_sock(sk);
999 l2cap_sock_kill(sk);
1000 }
1001
Dave Young8e8440f2008-03-03 12:18:55 -08001002 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1003 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -08001004
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 hcon->l2cap_data = NULL;
1006 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007}
1008
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001009static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001011 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001012 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001013 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014}
1015
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017
1018/* Find socket with psm and source bdaddr.
1019 * Returns closest match.
1020 */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001021static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001023 struct l2cap_chan *c, *c1 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001025 read_lock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001026
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001027 list_for_each_entry(c, &chan_list, global_l) {
1028 struct sock *sk = c->sk;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001029
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 if (state && sk->sk_state != state)
1031 continue;
1032
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001033 if (c->psm == psm) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 /* Exact match. */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001035 if (!bacmp(&bt_sk(sk)->src, src)) {
Johannes Berga7567b22011-06-01 08:29:54 +02001036 read_unlock(&chan_list_lock);
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001037 return c;
1038 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039
1040 /* Closest match */
1041 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001042 c1 = c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 }
1044 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001046 read_unlock(&chan_list_lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001047
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03001048 return c1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049}
1050
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -03001051int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03001053 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 bdaddr_t *src = &bt_sk(sk)->src;
1055 bdaddr_t *dst = &bt_sk(sk)->dst;
1056 struct l2cap_conn *conn;
1057 struct hci_conn *hcon;
1058 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001059 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +02001060 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061
Marcel Holtmannf29972d2009-02-12 05:07:45 +01001062 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001063 chan->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001065 hdev = hci_get_route(dst, src);
1066 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 return -EHOSTUNREACH;
1068
1069 hci_dev_lock_bh(hdev);
1070
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001071 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +02001072
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001073 if (chan->dcid == L2CAP_CID_LE_DATA)
Ville Tervoacd7d372011-02-10 22:38:49 -03001074 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001075 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001076 else
1077 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001078 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -03001079
Ville Tervo30e76272011-02-22 16:10:53 -03001080 if (IS_ERR(hcon)) {
1081 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -03001083 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084
1085 conn = l2cap_conn_add(hcon, 0);
1086 if (!conn) {
1087 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -03001088 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 goto done;
1090 }
1091
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 /* Update source addr of the socket */
1093 bacpy(src, conn->src);
1094
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001095 l2cap_chan_add(conn, chan);
1096
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 sk->sk_state = BT_CONNECT;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03001098 l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
1100 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001101 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
Gustavo F. Padovanab078012011-05-02 18:25:01 -03001102 l2cap_chan_clear_timer(chan);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001103 if (l2cap_check_security(chan))
Johan Hedbergd00ef242011-01-19 12:06:51 +05301104 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001105 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03001106 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 }
1108
Ville Tervo30e76272011-02-22 16:10:53 -03001109 err = 0;
1110
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111done:
1112 hci_dev_unlock_bh(hdev);
1113 hci_dev_put(hdev);
1114 return err;
1115}
1116
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -02001117int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001118{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001119 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001120 DECLARE_WAITQUEUE(wait, current);
1121 int err = 0;
1122 int timeo = HZ/5;
1123
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001124 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001125 while ((chan->unacked_frames > 0 && chan->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001126 set_current_state(TASK_INTERRUPTIBLE);
1127
1128 if (!timeo)
1129 timeo = HZ/5;
1130
1131 if (signal_pending(current)) {
1132 err = sock_intr_errno(timeo);
1133 break;
1134 }
1135
1136 release_sock(sk);
1137 timeo = schedule_timeout(timeo);
1138 lock_sock(sk);
1139
1140 err = sock_error(sk);
1141 if (err)
1142 break;
1143 }
1144 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02001145 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -03001146 return err;
1147}
1148
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001149static void l2cap_monitor_timeout(unsigned long arg)
1150{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001151 struct l2cap_chan *chan = (void *) arg;
1152 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001153
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001154 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001155
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001156 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001157 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001158 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +02001159 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001160 return;
1161 }
1162
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001163 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001164 __mod_monitor_timer();
1165
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001166 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001167 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001168}
1169
1170static void l2cap_retrans_timeout(unsigned long arg)
1171{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001172 struct l2cap_chan *chan = (void *) arg;
1173 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001174
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001175 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03001176
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001177 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001178 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001179 __mod_monitor_timer();
1180
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001181 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001182
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001183 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001184 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001185}
1186
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001187static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001188{
1189 struct sk_buff *skb;
1190
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001191 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001192 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001193 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001194 break;
1195
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001196 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001197 kfree_skb(skb);
1198
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001199 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001200 }
1201
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001202 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001203 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001204}
1205
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001206void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001207{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001208 struct hci_conn *hcon = chan->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001209 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001210
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001211 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001212
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001213 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001214 flags = ACL_START_NO_FLUSH;
1215 else
1216 flags = ACL_START;
1217
1218 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001219}
1220
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001221void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001222{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001223 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001224 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001225
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001226 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001227 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001228 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001229 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001230
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001231 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001232 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1233 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001234 }
1235
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001236 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001237
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001238 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001239 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001240}
1241
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001242static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001243{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001244 struct sk_buff *skb, *tx_skb;
1245 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001246
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001247 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001248 if (!skb)
1249 return;
1250
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001251 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001252 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001253 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001254
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001255 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001256 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001257
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001258 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001259
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001260 if (chan->remote_max_tx &&
1261 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001262 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001263 return;
1264 }
1265
1266 tx_skb = skb_clone(skb, GFP_ATOMIC);
1267 bt_cb(skb)->retries++;
1268 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001269 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001270
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001271 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001272 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001273 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001274 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001275
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001276 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001277 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001278
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001279 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1280
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001281 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001282 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1283 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1284 }
1285
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001286 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001287}
1288
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001289int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001290{
1291 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001292 struct sock *sk = chan->sk;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001293 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001294 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001295
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001296 if (sk->sk_state != BT_CONNECTED)
1297 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001298
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001299 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001300
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001301 if (chan->remote_max_tx &&
1302 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001303 l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001304 break;
1305 }
1306
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001307 tx_skb = skb_clone(skb, GFP_ATOMIC);
1308
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001309 bt_cb(skb)->retries++;
1310
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001311 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001312 control &= L2CAP_CTRL_SAR;
1313
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001314 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001315 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001316 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001317 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001318 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1319 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001320 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1321
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001322
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001323 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001324 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1325 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1326 }
1327
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001328 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001329
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001330 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001331
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001332 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1333 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001334
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301335 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001336 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301337
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001338 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001339
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001340 if (skb_queue_is_last(&chan->tx_q, skb))
1341 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001342 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001343 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001344
1345 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001346 }
1347
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001348 return nsent;
1349}
1350
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001351static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001352{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001353 int ret;
1354
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001355 if (!skb_queue_empty(&chan->tx_q))
1356 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001357
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001358 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001359 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001360 return ret;
1361}
1362
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001363static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001364{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001365 u16 control = 0;
1366
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001367 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001368
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001369 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001370 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001371 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1372 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001373 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001374 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001375
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001376 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001377 return;
1378
1379 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001380 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001381}
1382
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001383static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001384{
1385 struct srej_list *tail;
1386 u16 control;
1387
1388 control = L2CAP_SUPER_SELECT_REJECT;
1389 control |= L2CAP_CTRL_FINAL;
1390
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001391 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001392 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1393
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001394 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001395}
1396
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001397static 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 -07001398{
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001399 struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001400 struct sk_buff **frag;
1401 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001403 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001404 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405
1406 sent += count;
1407 len -= count;
1408
1409 /* Continuation fragments (no L2CAP header) */
1410 frag = &skb_shinfo(skb)->frag_list;
1411 while (len) {
1412 count = min_t(unsigned int, conn->mtu, len);
1413
1414 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1415 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001416 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001417 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1418 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419
1420 sent += count;
1421 len -= count;
1422
1423 frag = &(*frag)->next;
1424 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425
1426 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001427}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001429struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001430{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001431 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001432 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001433 struct sk_buff *skb;
1434 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1435 struct l2cap_hdr *lh;
1436
1437 BT_DBG("sk %p len %d", sk, (int)len);
1438
1439 count = min_t(unsigned int, (conn->mtu - hlen), len);
1440 skb = bt_skb_send_alloc(sk, count + hlen,
1441 msg->msg_flags & MSG_DONTWAIT, &err);
1442 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001443 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001444
1445 /* Create L2CAP header */
1446 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001447 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001448 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001449 put_unaligned_le16(chan->psm, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001450
1451 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1452 if (unlikely(err < 0)) {
1453 kfree_skb(skb);
1454 return ERR_PTR(err);
1455 }
1456 return skb;
1457}
1458
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001459struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001460{
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001461 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001462 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001463 struct sk_buff *skb;
1464 int err, count, hlen = L2CAP_HDR_SIZE;
1465 struct l2cap_hdr *lh;
1466
1467 BT_DBG("sk %p len %d", sk, (int)len);
1468
1469 count = min_t(unsigned int, (conn->mtu - hlen), len);
1470 skb = bt_skb_send_alloc(sk, count + hlen,
1471 msg->msg_flags & MSG_DONTWAIT, &err);
1472 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001473 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001474
1475 /* Create L2CAP header */
1476 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001477 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001478 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1479
1480 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1481 if (unlikely(err < 0)) {
1482 kfree_skb(skb);
1483 return ERR_PTR(err);
1484 }
1485 return skb;
1486}
1487
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001488struct 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 -03001489{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001490 struct sock *sk = chan->sk;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001491 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001492 struct sk_buff *skb;
1493 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1494 struct l2cap_hdr *lh;
1495
1496 BT_DBG("sk %p len %d", sk, (int)len);
1497
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001498 if (!conn)
1499 return ERR_PTR(-ENOTCONN);
1500
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001501 if (sdulen)
1502 hlen += 2;
1503
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001504 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001505 hlen += 2;
1506
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001507 count = min_t(unsigned int, (conn->mtu - hlen), len);
1508 skb = bt_skb_send_alloc(sk, count + hlen,
1509 msg->msg_flags & MSG_DONTWAIT, &err);
1510 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001511 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001512
1513 /* Create L2CAP header */
1514 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001515 lh->cid = cpu_to_le16(chan->dcid);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001516 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1517 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001518 if (sdulen)
1519 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001520
1521 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1522 if (unlikely(err < 0)) {
1523 kfree_skb(skb);
1524 return ERR_PTR(err);
1525 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001526
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001527 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001528 put_unaligned_le16(0, skb_put(skb, 2));
1529
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001530 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001531 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532}
1533
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001534int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001535{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001536 struct sk_buff *skb;
1537 struct sk_buff_head sar_queue;
1538 u16 control;
1539 size_t size = 0;
1540
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001541 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001542 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001543 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001544 if (IS_ERR(skb))
1545 return PTR_ERR(skb);
1546
1547 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001548 len -= chan->remote_mps;
1549 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001550
1551 while (len > 0) {
1552 size_t buflen;
1553
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001554 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001555 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001556 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001557 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001558 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001559 buflen = len;
1560 }
1561
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001562 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001563 if (IS_ERR(skb)) {
1564 skb_queue_purge(&sar_queue);
1565 return PTR_ERR(skb);
1566 }
1567
1568 __skb_queue_tail(&sar_queue, skb);
1569 len -= buflen;
1570 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001571 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001572 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1573 if (chan->tx_send_head == NULL)
1574 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001575
1576 return size;
1577}
1578
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001579int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1580{
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001581 struct sk_buff *skb;
1582 u16 control;
1583 int err;
1584
1585 /* Connectionless channel */
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001586 if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
Gustavo F. Padovan9a91a042011-04-28 18:50:17 -03001587 skb = l2cap_create_connless_pdu(chan, msg, len);
1588 if (IS_ERR(skb))
1589 return PTR_ERR(skb);
1590
1591 l2cap_do_send(chan, skb);
1592 return len;
1593 }
1594
1595 switch (chan->mode) {
1596 case L2CAP_MODE_BASIC:
1597 /* Check outgoing MTU */
1598 if (len > chan->omtu)
1599 return -EMSGSIZE;
1600
1601 /* Create a basic PDU */
1602 skb = l2cap_create_basic_pdu(chan, msg, len);
1603 if (IS_ERR(skb))
1604 return PTR_ERR(skb);
1605
1606 l2cap_do_send(chan, skb);
1607 err = len;
1608 break;
1609
1610 case L2CAP_MODE_ERTM:
1611 case L2CAP_MODE_STREAMING:
1612 /* Entire SDU fits into one PDU */
1613 if (len <= chan->remote_mps) {
1614 control = L2CAP_SDU_UNSEGMENTED;
1615 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1616 0);
1617 if (IS_ERR(skb))
1618 return PTR_ERR(skb);
1619
1620 __skb_queue_tail(&chan->tx_q, skb);
1621
1622 if (chan->tx_send_head == NULL)
1623 chan->tx_send_head = skb;
1624
1625 } else {
1626 /* Segment SDU into multiples PDUs */
1627 err = l2cap_sar_segment_sdu(chan, msg, len);
1628 if (err < 0)
1629 return err;
1630 }
1631
1632 if (chan->mode == L2CAP_MODE_STREAMING) {
1633 l2cap_streaming_send(chan);
1634 err = len;
1635 break;
1636 }
1637
1638 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
1639 (chan->conn_state & L2CAP_CONN_WAIT_F)) {
1640 err = len;
1641 break;
1642 }
1643
1644 err = l2cap_ertm_send(chan);
1645 if (err >= 0)
1646 err = len;
1647
1648 break;
1649
1650 default:
1651 BT_DBG("bad state %1.1x", chan->mode);
1652 err = -EBADFD;
1653 }
1654
1655 return err;
1656}
1657
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658static void l2cap_chan_ready(struct sock *sk)
1659{
1660 struct sock *parent = bt_sk(sk)->parent;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001661 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662
1663 BT_DBG("sk %p, parent %p", sk, parent);
1664
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001665 chan->conf_state = 0;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03001666 l2cap_chan_clear_timer(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667
1668 if (!parent) {
1669 /* Outgoing channel.
1670 * Wake up socket sleeping on connect.
1671 */
1672 sk->sk_state = BT_CONNECTED;
1673 sk->sk_state_change(sk);
1674 } else {
1675 /* Incoming channel.
1676 * Wake up socket sleeping on accept.
1677 */
1678 parent->sk_data_ready(parent, 0);
1679 }
1680}
1681
1682/* Copy frame to all raw sockets on that connection */
1683static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1684{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001686 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687
1688 BT_DBG("conn %p", conn);
1689
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001690 read_lock(&conn->chan_lock);
1691 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001692 struct sock *sk = chan->sk;
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03001693 if (chan->chan_type != L2CAP_CHAN_RAW)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 continue;
1695
1696 /* Don't send frame to the socket it came from */
1697 if (skb->sk == sk)
1698 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001699 nskb = skb_clone(skb, GFP_ATOMIC);
1700 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701 continue;
1702
1703 if (sock_queue_rcv_skb(sk, nskb))
1704 kfree_skb(nskb);
1705 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001706 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707}
1708
1709/* ---- L2CAP signalling commands ---- */
1710static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1711 u8 code, u8 ident, u16 dlen, void *data)
1712{
1713 struct sk_buff *skb, **frag;
1714 struct l2cap_cmd_hdr *cmd;
1715 struct l2cap_hdr *lh;
1716 int len, count;
1717
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001718 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1719 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720
1721 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1722 count = min_t(unsigned int, conn->mtu, len);
1723
1724 skb = bt_skb_alloc(count, GFP_ATOMIC);
1725 if (!skb)
1726 return NULL;
1727
1728 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001729 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001730
1731 if (conn->hcon->type == LE_LINK)
1732 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1733 else
1734 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735
1736 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1737 cmd->code = code;
1738 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001739 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740
1741 if (dlen) {
1742 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1743 memcpy(skb_put(skb, count), data, count);
1744 data += count;
1745 }
1746
1747 len -= skb->len;
1748
1749 /* Continuation fragments (no L2CAP header) */
1750 frag = &skb_shinfo(skb)->frag_list;
1751 while (len) {
1752 count = min_t(unsigned int, conn->mtu, len);
1753
1754 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1755 if (!*frag)
1756 goto fail;
1757
1758 memcpy(skb_put(*frag, count), data, count);
1759
1760 len -= count;
1761 data += count;
1762
1763 frag = &(*frag)->next;
1764 }
1765
1766 return skb;
1767
1768fail:
1769 kfree_skb(skb);
1770 return NULL;
1771}
1772
1773static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1774{
1775 struct l2cap_conf_opt *opt = *ptr;
1776 int len;
1777
1778 len = L2CAP_CONF_OPT_SIZE + opt->len;
1779 *ptr += len;
1780
1781 *type = opt->type;
1782 *olen = opt->len;
1783
1784 switch (opt->len) {
1785 case 1:
1786 *val = *((u8 *) opt->val);
1787 break;
1788
1789 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001790 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 break;
1792
1793 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001794 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795 break;
1796
1797 default:
1798 *val = (unsigned long) opt->val;
1799 break;
1800 }
1801
1802 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1803 return len;
1804}
1805
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1807{
1808 struct l2cap_conf_opt *opt = *ptr;
1809
1810 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1811
1812 opt->type = type;
1813 opt->len = len;
1814
1815 switch (len) {
1816 case 1:
1817 *((u8 *) opt->val) = val;
1818 break;
1819
1820 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001821 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 break;
1823
1824 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001825 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826 break;
1827
1828 default:
1829 memcpy(opt->val, (void *) val, len);
1830 break;
1831 }
1832
1833 *ptr += L2CAP_CONF_OPT_SIZE + len;
1834}
1835
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001836static void l2cap_ack_timeout(unsigned long arg)
1837{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001838 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001839
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001840 bh_lock_sock(chan->sk);
1841 l2cap_send_ack(chan);
1842 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001843}
1844
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001845static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001846{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001847 struct sock *sk = chan->sk;
1848
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001849 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001850 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001851 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001852 chan->num_acked = 0;
1853 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001854
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001855 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1856 (unsigned long) chan);
1857 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1858 (unsigned long) chan);
1859 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001860
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001861 skb_queue_head_init(&chan->srej_q);
1862 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001863
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001864 INIT_LIST_HEAD(&chan->srej_l);
1865
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001866 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001867
1868 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001869}
1870
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001871static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1872{
1873 switch (mode) {
1874 case L2CAP_MODE_STREAMING:
1875 case L2CAP_MODE_ERTM:
1876 if (l2cap_mode_supported(mode, remote_feat_mask))
1877 return mode;
1878 /* fall through */
1879 default:
1880 return L2CAP_MODE_BASIC;
1881 }
1882}
1883
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001884static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001887 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 void *ptr = req->data;
1889
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001890 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001892 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001893 goto done;
1894
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001895 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001896 case L2CAP_MODE_STREAMING:
1897 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001898 if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001899 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001900
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001901 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001902 default:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001903 chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001904 break;
1905 }
1906
1907done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001908 if (chan->imtu != L2CAP_DEFAULT_MTU)
1909 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001910
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001911 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001912 case L2CAP_MODE_BASIC:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001913 if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1914 !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001915 break;
1916
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001917 rfc.mode = L2CAP_MODE_BASIC;
1918 rfc.txwin_size = 0;
1919 rfc.max_transmit = 0;
1920 rfc.retrans_timeout = 0;
1921 rfc.monitor_timeout = 0;
1922 rfc.max_pdu_size = 0;
1923
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001924 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1925 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001926 break;
1927
1928 case L2CAP_MODE_ERTM:
1929 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001930 rfc.txwin_size = chan->tx_win;
1931 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001932 rfc.retrans_timeout = 0;
1933 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001934 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001935 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1936 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001937
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001938 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1939 (unsigned long) &rfc);
1940
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001941 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001942 break;
1943
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001944 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001945 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001946 chan->fcs = L2CAP_FCS_NONE;
1947 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001948 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001949 break;
1950
1951 case L2CAP_MODE_STREAMING:
1952 rfc.mode = L2CAP_MODE_STREAMING;
1953 rfc.txwin_size = 0;
1954 rfc.max_transmit = 0;
1955 rfc.retrans_timeout = 0;
1956 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001957 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001958 if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
1959 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001960
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001961 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1962 (unsigned long) &rfc);
1963
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03001964 if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001965 break;
1966
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001967 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001968 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001969 chan->fcs = L2CAP_FCS_NONE;
1970 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001971 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001972 break;
1973 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03001975 req->dcid = cpu_to_le16(chan->dcid);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001976 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977
1978 return ptr - data;
1979}
1980
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001981static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982{
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001983 struct l2cap_conf_rsp *rsp = data;
1984 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001985 void *req = chan->conf_req;
1986 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001987 int type, hint, olen;
1988 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001989 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001990 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001991 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001993 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001994
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001995 while (len >= L2CAP_CONF_OPT_SIZE) {
1996 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001998 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001999 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002000
2001 switch (type) {
2002 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02002003 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002004 break;
2005
2006 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002007 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002008 break;
2009
2010 case L2CAP_CONF_QOS:
2011 break;
2012
Marcel Holtmann6464f352007-10-20 13:39:51 +02002013 case L2CAP_CONF_RFC:
2014 if (olen == sizeof(rfc))
2015 memcpy(&rfc, (void *) val, olen);
2016 break;
2017
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002018 case L2CAP_CONF_FCS:
2019 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002020 chan->conf_state |= L2CAP_CONF_NO_FCS_RECV;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002021
2022 break;
2023
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002024 default:
2025 if (hint)
2026 break;
2027
2028 result = L2CAP_CONF_UNKNOWN;
2029 *((u8 *) ptr++) = type;
2030 break;
2031 }
2032 }
2033
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002034 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002035 goto done;
2036
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002037 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002038 case L2CAP_MODE_STREAMING:
2039 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002040 if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002041 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002042 chan->conn->feat_mask);
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03002043 break;
2044 }
2045
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002046 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002047 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03002048
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002049 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002050 }
2051
2052done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002053 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002054 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002055 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002056
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002057 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002058 return -ECONNREFUSED;
2059
2060 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2061 sizeof(rfc), (unsigned long) &rfc);
2062 }
2063
2064
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002065 if (result == L2CAP_CONF_SUCCESS) {
2066 /* Configure output options and let the other side know
2067 * which ones we don't like. */
2068
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002069 if (mtu < L2CAP_DEFAULT_MIN_MTU)
2070 result = L2CAP_CONF_UNACCEPT;
2071 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002072 chan->omtu = mtu;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002073 chan->conf_state |= L2CAP_CONF_MTU_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002074 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002075 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002076
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002077 switch (rfc.mode) {
2078 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002079 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002080 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002081 break;
2082
2083 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002084 chan->remote_tx_win = rfc.txwin_size;
2085 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07002086
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002087 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2088 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002089
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002090 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002091
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03002092 rfc.retrans_timeout =
2093 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
2094 rfc.monitor_timeout =
2095 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002096
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002097 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002098
2099 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2100 sizeof(rfc), (unsigned long) &rfc);
2101
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002102 break;
2103
2104 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002105 if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
2106 rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03002107
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03002108 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002109
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002110 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03002111
2112 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2113 sizeof(rfc), (unsigned long) &rfc);
2114
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002115 break;
2116
2117 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02002118 result = L2CAP_CONF_UNACCEPT;
2119
2120 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002121 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02002122 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002123
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002124 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002125 chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002126 }
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002127 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002128 rsp->result = cpu_to_le16(result);
2129 rsp->flags = cpu_to_le16(0x0000);
2130
2131 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132}
2133
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002134static 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 -03002135{
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002136 struct l2cap_conf_req *req = data;
2137 void *ptr = req->data;
2138 int type, olen;
2139 unsigned long val;
2140 struct l2cap_conf_rfc rfc;
2141
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002142 BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002143
2144 while (len >= L2CAP_CONF_OPT_SIZE) {
2145 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2146
2147 switch (type) {
2148 case L2CAP_CONF_MTU:
2149 if (val < L2CAP_DEFAULT_MIN_MTU) {
2150 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002151 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002152 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002153 chan->imtu = val;
2154 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002155 break;
2156
2157 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002158 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002159 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002160 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002161 break;
2162
2163 case L2CAP_CONF_RFC:
2164 if (olen == sizeof(rfc))
2165 memcpy(&rfc, (void *)val, olen);
2166
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002167 if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002168 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002169 return -ECONNREFUSED;
2170
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002171 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002172
2173 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
2174 sizeof(rfc), (unsigned long) &rfc);
2175 break;
2176 }
2177 }
2178
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002179 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002180 return -ECONNREFUSED;
2181
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002182 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03002183
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002184 if (*result == L2CAP_CONF_SUCCESS) {
2185 switch (rfc.mode) {
2186 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002187 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2188 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2189 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002190 break;
2191 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002192 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002193 }
2194 }
2195
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002196 req->dcid = cpu_to_le16(chan->dcid);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002197 req->flags = cpu_to_le16(0x0000);
2198
2199 return ptr - data;
2200}
2201
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002202static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203{
2204 struct l2cap_conf_rsp *rsp = data;
2205 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002207 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002209 rsp->scid = cpu_to_le16(chan->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002210 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002211 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212
2213 return ptr - data;
2214}
2215
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002216void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002217{
2218 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03002219 struct l2cap_conn *conn = chan->conn;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002220 u8 buf[128];
2221
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002222 rsp.scid = cpu_to_le16(chan->dcid);
2223 rsp.dcid = cpu_to_le16(chan->scid);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002224 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2225 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2226 l2cap_send_cmd(conn, chan->ident,
2227 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2228
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002229 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002230 return;
2231
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002232 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03002233 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2234 l2cap_build_conf_req(chan, buf), buf);
2235 chan->num_conf_req++;
2236}
2237
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002238static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002239{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002240 int type, olen;
2241 unsigned long val;
2242 struct l2cap_conf_rfc rfc;
2243
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002244 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002245
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002246 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002247 return;
2248
2249 while (len >= L2CAP_CONF_OPT_SIZE) {
2250 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
2251
2252 switch (type) {
2253 case L2CAP_CONF_RFC:
2254 if (olen == sizeof(rfc))
2255 memcpy(&rfc, (void *)val, olen);
2256 goto done;
2257 }
2258 }
2259
2260done:
2261 switch (rfc.mode) {
2262 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002263 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2264 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
2265 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002266 break;
2267 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002268 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002269 }
2270}
2271
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002272static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2273{
2274 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2275
2276 if (rej->reason != 0x0000)
2277 return 0;
2278
2279 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2280 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002281 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002282
2283 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002284 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002285
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002286 l2cap_conn_start(conn);
2287 }
2288
2289 return 0;
2290}
2291
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2293{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2295 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002296 struct l2cap_chan *chan = NULL, *pchan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002297 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002298 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299
2300 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002301 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302
2303 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2304
2305 /* Check if we have socket listening on psm */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002306 pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
2307 if (!pchan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308 result = L2CAP_CR_BAD_PSM;
2309 goto sendresp;
2310 }
2311
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002312 parent = pchan->sk;
2313
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002314 bh_lock_sock(parent);
2315
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002316 /* Check if the ACL is secure enough (if not SDP) */
2317 if (psm != cpu_to_le16(0x0001) &&
2318 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002319 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002320 result = L2CAP_CR_SEC_BLOCK;
2321 goto response;
2322 }
2323
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 result = L2CAP_CR_NO_MEM;
2325
2326 /* Check for backlog size */
2327 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002328 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 goto response;
2330 }
2331
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002332 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 if (!sk)
2334 goto response;
2335
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03002336 chan = l2cap_chan_create(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002337 if (!chan) {
2338 l2cap_sock_kill(sk);
2339 goto response;
2340 }
2341
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03002342 l2cap_pi(sk)->chan = chan;
2343
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002344 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345
2346 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002347 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2348 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 sock_set_flag(sk, SOCK_ZAPPED);
2350 l2cap_sock_kill(sk);
2351 goto response;
2352 }
2353
2354 hci_conn_hold(conn->hcon);
2355
2356 l2cap_sock_init(sk, parent);
2357 bacpy(&bt_sk(sk)->src, conn->src);
2358 bacpy(&bt_sk(sk)->dst, conn->dst);
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002359 chan->psm = psm;
2360 chan->dcid = scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002362 bt_accept_enqueue(parent, sk);
2363
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002364 __l2cap_chan_add(conn, chan);
2365
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002366 dcid = chan->scid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002368 l2cap_chan_set_timer(chan, sk->sk_sndtimeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002370 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371
Marcel Holtmann984947d2009-02-06 23:35:19 +01002372 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002373 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002374 if (bt_sk(sk)->defer_setup) {
2375 sk->sk_state = BT_CONNECT2;
2376 result = L2CAP_CR_PEND;
2377 status = L2CAP_CS_AUTHOR_PEND;
2378 parent->sk_data_ready(parent, 0);
2379 } else {
2380 sk->sk_state = BT_CONFIG;
2381 result = L2CAP_CR_SUCCESS;
2382 status = L2CAP_CS_NO_INFO;
2383 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002384 } else {
2385 sk->sk_state = BT_CONNECT2;
2386 result = L2CAP_CR_PEND;
2387 status = L2CAP_CS_AUTHEN_PEND;
2388 }
2389 } else {
2390 sk->sk_state = BT_CONNECT2;
2391 result = L2CAP_CR_PEND;
2392 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393 }
2394
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002395 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396
2397response:
2398 bh_unlock_sock(parent);
2399
2400sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002401 rsp.scid = cpu_to_le16(scid);
2402 rsp.dcid = cpu_to_le16(dcid);
2403 rsp.result = cpu_to_le16(result);
2404 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002406
2407 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2408 struct l2cap_info_req info;
2409 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2410
2411 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2412 conn->info_ident = l2cap_get_ident(conn);
2413
2414 mod_timer(&conn->info_timer, jiffies +
2415 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2416
2417 l2cap_send_cmd(conn, conn->info_ident,
2418 L2CAP_INFO_REQ, sizeof(info), &info);
2419 }
2420
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002421 if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002422 result == L2CAP_CR_SUCCESS) {
2423 u8 buf[128];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002424 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002425 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002426 l2cap_build_conf_req(chan, buf), buf);
2427 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002428 }
2429
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 return 0;
2431}
2432
2433static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2434{
2435 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2436 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002437 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438 struct sock *sk;
2439 u8 req[128];
2440
2441 scid = __le16_to_cpu(rsp->scid);
2442 dcid = __le16_to_cpu(rsp->dcid);
2443 result = __le16_to_cpu(rsp->result);
2444 status = __le16_to_cpu(rsp->status);
2445
2446 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2447
2448 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002449 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002450 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002451 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002453 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002454 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002455 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456 }
2457
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002458 sk = chan->sk;
2459
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460 switch (result) {
2461 case L2CAP_CR_SUCCESS:
2462 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002463 chan->ident = 0;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002464 chan->dcid = dcid;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002465 chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002466
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002467 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002468 break;
2469
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002470 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002471
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002473 l2cap_build_conf_req(chan, req), req);
2474 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475 break;
2476
2477 case L2CAP_CR_PEND:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002478 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 break;
2480
2481 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002482 /* don't delete l2cap channel if sk is owned by user */
2483 if (sock_owned_by_user(sk)) {
2484 sk->sk_state = BT_DISCONN;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002485 l2cap_chan_clear_timer(chan);
2486 l2cap_chan_set_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002487 break;
2488 }
2489
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002490 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491 break;
2492 }
2493
2494 bh_unlock_sock(sk);
2495 return 0;
2496}
2497
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002498static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002499{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002500 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
2501
Mat Martineau8c462b62010-08-24 15:35:42 -07002502 /* FCS is enabled only in ERTM or streaming mode, if one or both
2503 * sides request it.
2504 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002505 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002506 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002507 else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002508 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002509}
2510
Al Viro88219a02007-07-29 00:17:25 -07002511static 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 -07002512{
2513 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2514 u16 dcid, flags;
2515 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002516 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002518 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519
2520 dcid = __le16_to_cpu(req->dcid);
2521 flags = __le16_to_cpu(req->flags);
2522
2523 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2524
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002525 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002526 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527 return -ENOENT;
2528
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002529 sk = chan->sk;
2530
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002531 if (sk->sk_state != BT_CONFIG) {
2532 struct l2cap_cmd_rej rej;
2533
2534 rej.reason = cpu_to_le16(0x0002);
2535 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2536 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002537 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002538 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002539
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002540 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002541 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002542 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002543 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002544 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002545 L2CAP_CONF_REJECT, flags), rsp);
2546 goto unlock;
2547 }
2548
2549 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002550 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2551 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002552
2553 if (flags & 0x0001) {
2554 /* Incomplete config. Send empty response. */
2555 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002556 l2cap_build_conf_rsp(chan, rsp,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002557 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558 goto unlock;
2559 }
2560
2561 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002562 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002563 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002564 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002566 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002568 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002569 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002570
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002571 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002572 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002573
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002574 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002575 goto unlock;
2576
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002577 if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002578 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002579
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002581
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002582 chan->next_tx_seq = 0;
2583 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002584 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002585 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002586 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002587
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002589 goto unlock;
2590 }
2591
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002592 if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002593 u8 buf[64];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002594 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002596 l2cap_build_conf_req(chan, buf), buf);
2597 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598 }
2599
2600unlock:
2601 bh_unlock_sock(sk);
2602 return 0;
2603}
2604
2605static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2606{
2607 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2608 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002609 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002611 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612
2613 scid = __le16_to_cpu(rsp->scid);
2614 flags = __le16_to_cpu(rsp->flags);
2615 result = __le16_to_cpu(rsp->result);
2616
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002617 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2618 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002620 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002621 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 return 0;
2623
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002624 sk = chan->sk;
2625
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626 switch (result) {
2627 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002628 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629 break;
2630
2631 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002632 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002633 char req[64];
2634
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002635 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002636 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002637 goto done;
2638 }
2639
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002640 /* throw out any old stored conf requests */
2641 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002642 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2643 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002644 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002645 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002646 goto done;
2647 }
2648
2649 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2650 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002651 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002652 if (result != L2CAP_CONF_SUCCESS)
2653 goto done;
2654 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655 }
2656
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002657 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002658 sk->sk_err = ECONNRESET;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002659 l2cap_chan_set_timer(chan, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002660 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661 goto done;
2662 }
2663
2664 if (flags & 0x01)
2665 goto done;
2666
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002667 chan->conf_state |= L2CAP_CONF_INPUT_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002669 if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002670 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002671
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002673 chan->next_tx_seq = 0;
2674 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002675 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002676 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002677 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002678
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679 l2cap_chan_ready(sk);
2680 }
2681
2682done:
2683 bh_unlock_sock(sk);
2684 return 0;
2685}
2686
2687static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2688{
2689 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2690 struct l2cap_disconn_rsp rsp;
2691 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002692 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693 struct sock *sk;
2694
2695 scid = __le16_to_cpu(req->scid);
2696 dcid = __le16_to_cpu(req->dcid);
2697
2698 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2699
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002700 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002701 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 return 0;
2703
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002704 sk = chan->sk;
2705
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03002706 rsp.dcid = cpu_to_le16(chan->scid);
2707 rsp.scid = cpu_to_le16(chan->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2709
2710 sk->sk_shutdown = SHUTDOWN_MASK;
2711
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002712 /* don't delete l2cap channel if sk is owned by user */
2713 if (sock_owned_by_user(sk)) {
2714 sk->sk_state = BT_DISCONN;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002715 l2cap_chan_clear_timer(chan);
2716 l2cap_chan_set_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002717 bh_unlock_sock(sk);
2718 return 0;
2719 }
2720
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002721 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 bh_unlock_sock(sk);
2723
2724 l2cap_sock_kill(sk);
2725 return 0;
2726}
2727
2728static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2729{
2730 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2731 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002732 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 struct sock *sk;
2734
2735 scid = __le16_to_cpu(rsp->scid);
2736 dcid = __le16_to_cpu(rsp->dcid);
2737
2738 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2739
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002740 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002741 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742 return 0;
2743
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002744 sk = chan->sk;
2745
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002746 /* don't delete l2cap channel if sk is owned by user */
2747 if (sock_owned_by_user(sk)) {
2748 sk->sk_state = BT_DISCONN;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03002749 l2cap_chan_clear_timer(chan);
2750 l2cap_chan_set_timer(chan, HZ / 5);
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002751 bh_unlock_sock(sk);
2752 return 0;
2753 }
2754
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002755 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756 bh_unlock_sock(sk);
2757
2758 l2cap_sock_kill(sk);
2759 return 0;
2760}
2761
2762static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2763{
2764 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 u16 type;
2766
2767 type = __le16_to_cpu(req->type);
2768
2769 BT_DBG("type 0x%4.4x", type);
2770
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002771 if (type == L2CAP_IT_FEAT_MASK) {
2772 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002773 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002774 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2775 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2776 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002777 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002778 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2779 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002780 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002781 l2cap_send_cmd(conn, cmd->ident,
2782 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002783 } else if (type == L2CAP_IT_FIXED_CHAN) {
2784 u8 buf[12];
2785 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2786 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2787 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2788 memcpy(buf + 4, l2cap_fixed_chan, 8);
2789 l2cap_send_cmd(conn, cmd->ident,
2790 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002791 } else {
2792 struct l2cap_info_rsp rsp;
2793 rsp.type = cpu_to_le16(type);
2794 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2795 l2cap_send_cmd(conn, cmd->ident,
2796 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2797 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798
2799 return 0;
2800}
2801
2802static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2803{
2804 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2805 u16 type, result;
2806
2807 type = __le16_to_cpu(rsp->type);
2808 result = __le16_to_cpu(rsp->result);
2809
2810 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2811
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002812 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2813 if (cmd->ident != conn->info_ident ||
2814 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2815 return 0;
2816
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002817 del_timer(&conn->info_timer);
2818
Ville Tervoadb08ed2010-08-04 09:43:33 +03002819 if (result != L2CAP_IR_SUCCESS) {
2820 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2821 conn->info_ident = 0;
2822
2823 l2cap_conn_start(conn);
2824
2825 return 0;
2826 }
2827
Marcel Holtmann984947d2009-02-06 23:35:19 +01002828 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002829 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002830
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002831 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002832 struct l2cap_info_req req;
2833 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2834
2835 conn->info_ident = l2cap_get_ident(conn);
2836
2837 l2cap_send_cmd(conn, conn->info_ident,
2838 L2CAP_INFO_REQ, sizeof(req), &req);
2839 } else {
2840 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2841 conn->info_ident = 0;
2842
2843 l2cap_conn_start(conn);
2844 }
2845 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002846 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002847 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002848
2849 l2cap_conn_start(conn);
2850 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002851
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852 return 0;
2853}
2854
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002855static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002856 u16 to_multiplier)
2857{
2858 u16 max_latency;
2859
2860 if (min > max || min < 6 || max > 3200)
2861 return -EINVAL;
2862
2863 if (to_multiplier < 10 || to_multiplier > 3200)
2864 return -EINVAL;
2865
2866 if (max >= to_multiplier * 8)
2867 return -EINVAL;
2868
2869 max_latency = (to_multiplier * 8 / max) - 1;
2870 if (latency > 499 || latency > max_latency)
2871 return -EINVAL;
2872
2873 return 0;
2874}
2875
2876static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2877 struct l2cap_cmd_hdr *cmd, u8 *data)
2878{
2879 struct hci_conn *hcon = conn->hcon;
2880 struct l2cap_conn_param_update_req *req;
2881 struct l2cap_conn_param_update_rsp rsp;
2882 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002883 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002884
2885 if (!(hcon->link_mode & HCI_LM_MASTER))
2886 return -EINVAL;
2887
2888 cmd_len = __le16_to_cpu(cmd->len);
2889 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2890 return -EPROTO;
2891
2892 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002893 min = __le16_to_cpu(req->min);
2894 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002895 latency = __le16_to_cpu(req->latency);
2896 to_multiplier = __le16_to_cpu(req->to_multiplier);
2897
2898 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2899 min, max, latency, to_multiplier);
2900
2901 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002902
2903 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2904 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002905 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2906 else
2907 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2908
2909 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2910 sizeof(rsp), &rsp);
2911
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002912 if (!err)
2913 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2914
Claudio Takahaside731152011-02-11 19:28:55 -02002915 return 0;
2916}
2917
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002918static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2919 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2920{
2921 int err = 0;
2922
2923 switch (cmd->code) {
2924 case L2CAP_COMMAND_REJ:
2925 l2cap_command_rej(conn, cmd, data);
2926 break;
2927
2928 case L2CAP_CONN_REQ:
2929 err = l2cap_connect_req(conn, cmd, data);
2930 break;
2931
2932 case L2CAP_CONN_RSP:
2933 err = l2cap_connect_rsp(conn, cmd, data);
2934 break;
2935
2936 case L2CAP_CONF_REQ:
2937 err = l2cap_config_req(conn, cmd, cmd_len, data);
2938 break;
2939
2940 case L2CAP_CONF_RSP:
2941 err = l2cap_config_rsp(conn, cmd, data);
2942 break;
2943
2944 case L2CAP_DISCONN_REQ:
2945 err = l2cap_disconnect_req(conn, cmd, data);
2946 break;
2947
2948 case L2CAP_DISCONN_RSP:
2949 err = l2cap_disconnect_rsp(conn, cmd, data);
2950 break;
2951
2952 case L2CAP_ECHO_REQ:
2953 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2954 break;
2955
2956 case L2CAP_ECHO_RSP:
2957 break;
2958
2959 case L2CAP_INFO_REQ:
2960 err = l2cap_information_req(conn, cmd, data);
2961 break;
2962
2963 case L2CAP_INFO_RSP:
2964 err = l2cap_information_rsp(conn, cmd, data);
2965 break;
2966
2967 default:
2968 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2969 err = -EINVAL;
2970 break;
2971 }
2972
2973 return err;
2974}
2975
2976static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2977 struct l2cap_cmd_hdr *cmd, u8 *data)
2978{
2979 switch (cmd->code) {
2980 case L2CAP_COMMAND_REJ:
2981 return 0;
2982
2983 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002984 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002985
2986 case L2CAP_CONN_PARAM_UPDATE_RSP:
2987 return 0;
2988
2989 default:
2990 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2991 return -EINVAL;
2992 }
2993}
2994
2995static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2996 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997{
2998 u8 *data = skb->data;
2999 int len = skb->len;
3000 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003001 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002
3003 l2cap_raw_recv(conn, skb);
3004
3005 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07003006 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
3008 data += L2CAP_CMD_HDR_SIZE;
3009 len -= L2CAP_CMD_HDR_SIZE;
3010
Al Viro88219a02007-07-29 00:17:25 -07003011 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012
Al Viro88219a02007-07-29 00:17:25 -07003013 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 -07003014
Al Viro88219a02007-07-29 00:17:25 -07003015 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016 BT_DBG("corrupted command");
3017 break;
3018 }
3019
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003020 if (conn->hcon->type == LE_LINK)
3021 err = l2cap_le_sig_cmd(conn, &cmd, data);
3022 else
3023 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024
3025 if (err) {
3026 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03003027
3028 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029
3030 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07003031 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
3033 }
3034
Al Viro88219a02007-07-29 00:17:25 -07003035 data += cmd_len;
3036 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037 }
3038
3039 kfree_skb(skb);
3040}
3041
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003042static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003043{
3044 u16 our_fcs, rcv_fcs;
3045 int hdr_size = L2CAP_HDR_SIZE + 2;
3046
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003047 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003048 skb_trim(skb, skb->len - 2);
3049 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
3050 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
3051
3052 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03003053 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003054 }
3055 return 0;
3056}
3057
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003058static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003059{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003060 u16 control = 0;
3061
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003062 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003063
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003064 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003065
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003066 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03003067 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003068 l2cap_send_sframe(chan, control);
3069 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003070 }
3071
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003072 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
3073 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003074
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003075 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003076
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003077 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003078 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003079 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003080 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03003081 }
3082}
3083
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003084static 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 -03003085{
3086 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003087 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003088
3089 bt_cb(skb)->tx_seq = tx_seq;
3090 bt_cb(skb)->sar = sar;
3091
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003092 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003093 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003094 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003095 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003096 }
3097
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003098 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003099 if (tx_seq_offset < 0)
3100 tx_seq_offset += 64;
3101
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003102 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003103 if (bt_cb(next_skb)->tx_seq == tx_seq)
3104 return -EINVAL;
3105
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003106 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003107 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03003108 if (next_tx_seq_offset < 0)
3109 next_tx_seq_offset += 64;
3110
3111 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003112 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003113 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003114 }
3115
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003116 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003117 break;
3118
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003119 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003120
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003121 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003122
3123 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003124}
3125
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003126static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003127{
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003128 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003129 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003130
3131 switch (control & L2CAP_CTRL_SAR) {
3132 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003133 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003134 goto drop;
3135
Ruiyi Zhang224f8af2011-05-13 13:07:52 +08003136 return sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003137
3138 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003139 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003140 goto drop;
3141
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003142 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003143
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003144 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003145 goto disconnect;
3146
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003147 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3148 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003149 return -ENOMEM;
3150
3151 /* pull sdu_len bytes only after alloc, because of Local Busy
3152 * condition we have to be sure that this will be executed
3153 * only once, i.e., when alloc does not fail */
3154 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003155
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003156 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003157
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003158 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003159 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003160 break;
3161
3162 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003163 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003164 goto disconnect;
3165
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003166 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003167 goto disconnect;
3168
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003169 chan->partial_sdu_len += skb->len;
3170 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003171 goto drop;
3172
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003173 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003174
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003175 break;
3176
3177 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003178 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003179 goto disconnect;
3180
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003181 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003182 goto disconnect;
3183
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003184 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003185 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003186
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003187 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003188 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003189
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003190 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003191 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03003192
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003193 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003194 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003195
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003196 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003197 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003198 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003199 return -ENOMEM;
3200 }
3201
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003202 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003203 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003204 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003205 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003206 return err;
3207 }
3208
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003209 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
3210 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003211
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003212 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003213 break;
3214 }
3215
3216 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003217 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003218
3219drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003220 kfree_skb(chan->sdu);
3221 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003222
3223disconnect:
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003224 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003225 kfree_skb(skb);
3226 return 0;
3227}
3228
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003229static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003230{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003231 struct sk_buff *skb;
3232 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003233 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003234
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003235 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003236 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003237 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003238 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003239 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003240 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003241 }
3242
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003243 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003244 }
3245
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003246 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003247 goto done;
3248
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003249 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003250 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003251 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003252 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003253
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003254 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003255 __mod_monitor_timer();
3256
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003257 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003258
3259done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003260 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3261 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003262
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003263 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003264
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003265 return 0;
3266}
3267
3268static void l2cap_busy_work(struct work_struct *work)
3269{
3270 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003271 struct l2cap_chan *chan =
3272 container_of(work, struct l2cap_chan, busy_work);
3273 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003274 int n_tries = 0, timeo = HZ/5, err;
3275 struct sk_buff *skb;
3276
3277 lock_sock(sk);
3278
3279 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003280 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003281 set_current_state(TASK_INTERRUPTIBLE);
3282
3283 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3284 err = -EBUSY;
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003285 l2cap_send_disconn_req(chan->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003286 break;
3287 }
3288
3289 if (!timeo)
3290 timeo = HZ/5;
3291
3292 if (signal_pending(current)) {
3293 err = sock_intr_errno(timeo);
3294 break;
3295 }
3296
3297 release_sock(sk);
3298 timeo = schedule_timeout(timeo);
3299 lock_sock(sk);
3300
3301 err = sock_error(sk);
3302 if (err)
3303 break;
3304
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003305 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003306 break;
3307 }
3308
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003309 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003310 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003311
3312 release_sock(sk);
3313}
3314
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003315static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003316{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003317 int sctrl, err;
3318
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003319 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003320 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003321 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003322 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003323
3324
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003325 }
3326
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003327 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003328 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003329 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003330 return err;
3331 }
3332
3333 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003334 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003335
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003336 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003337 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003338 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003339
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003340 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003341 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003342 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003343
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003344 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003345
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003346 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003347
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003348 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003349
3350 return err;
3351}
3352
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003353static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003354{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003355 struct sk_buff *_skb;
3356 int err = -EINVAL;
3357
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003358 /*
3359 * TODO: We have to notify the userland if some data is lost with the
3360 * Streaming Mode.
3361 */
3362
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003363 switch (control & L2CAP_CTRL_SAR) {
3364 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003365 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003366 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003367 break;
3368 }
3369
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003370 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003371 if (!err)
3372 return 0;
3373
3374 break;
3375
3376 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003377 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003378 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003379 break;
3380 }
3381
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003382 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003383 skb_pull(skb, 2);
3384
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003385 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003386 err = -EMSGSIZE;
3387 break;
3388 }
3389
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003390 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3391 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003392 err = -ENOMEM;
3393 break;
3394 }
3395
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003396 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003397
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003398 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003399 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003400 err = 0;
3401 break;
3402
3403 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003404 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003405 break;
3406
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003407 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003408
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003409 chan->partial_sdu_len += skb->len;
3410 if (chan->partial_sdu_len > chan->sdu_len)
3411 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003412 else
3413 err = 0;
3414
3415 break;
3416
3417 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003418 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003419 break;
3420
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003421 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003422
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003423 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003424 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003425
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003426 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003427 goto drop;
3428
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003429 if (chan->partial_sdu_len == chan->sdu_len) {
3430 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003431 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003432 if (err < 0)
3433 kfree_skb(_skb);
3434 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003435 err = 0;
3436
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003437drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003438 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003439 break;
3440 }
3441
3442 kfree_skb(skb);
3443 return err;
3444}
3445
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003446static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003447{
3448 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003449 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003450
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003451 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003452 if (bt_cb(skb)->tx_seq != tx_seq)
3453 break;
3454
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003455 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003456 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003457 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003458 chan->buffer_seq_srej =
3459 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003460 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003461 }
3462}
3463
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003464static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003465{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003466 struct srej_list *l, *tmp;
3467 u16 control;
3468
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003469 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003470 if (l->tx_seq == tx_seq) {
3471 list_del(&l->list);
3472 kfree(l);
3473 return;
3474 }
3475 control = L2CAP_SUPER_SELECT_REJECT;
3476 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003477 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003478 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003479 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003480 }
3481}
3482
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003483static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003484{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003485 struct srej_list *new;
3486 u16 control;
3487
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003488 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003489 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003490 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003491 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003492
3493 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003494 new->tx_seq = chan->expected_tx_seq;
3495 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003496 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003497 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003498 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003499}
3500
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003501static 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 -03003502{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003503 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003504 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003505 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003506 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003507 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003508 int err = 0;
3509
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003510 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3511 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003512
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003513 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003514 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003515 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003516 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003517 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003518 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003519 }
3520
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003521 chan->expected_ack_seq = req_seq;
3522 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003523
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003524 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003525 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003526
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003527 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003528 if (tx_seq_offset < 0)
3529 tx_seq_offset += 64;
3530
3531 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003532 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003533 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003534 goto drop;
3535 }
3536
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003537 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003538 goto drop;
3539
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003540 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003541 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003542
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003543 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003544 struct srej_list, list);
3545 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003546 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003547 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003548
3549 list_del(&first->list);
3550 kfree(first);
3551
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003552 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003553 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003554 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3555 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003556 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003557 }
3558 } else {
3559 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003560
3561 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003562 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003563 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003564
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003565 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003566 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003567 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003568 return 0;
3569 }
3570 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003571 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003572 }
3573 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003574 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003575 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003576 if (expected_tx_seq_offset < 0)
3577 expected_tx_seq_offset += 64;
3578
3579 /* duplicated tx_seq */
3580 if (tx_seq_offset < expected_tx_seq_offset)
3581 goto drop;
3582
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003583 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003584
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003585 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003586
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003587 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003588 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003589
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003590 __skb_queue_head_init(&chan->srej_q);
3591 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003592 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003593
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003594 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003595
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003596 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003597
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003598 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003599 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003600 return 0;
3601
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003602expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003603 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003604
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003605 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003606 bt_cb(skb)->tx_seq = tx_seq;
3607 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003608 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003609 return 0;
3610 }
3611
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003612 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003613 if (err < 0)
3614 return 0;
3615
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003616 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003617 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3618 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003619 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003620 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003621 }
3622
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003623 __mod_ack_timer();
3624
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003625 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3626 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003627 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003628
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003629 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003630
3631drop:
3632 kfree_skb(skb);
3633 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003634}
3635
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003636static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003637{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003638 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003639 rx_control);
3640
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003641 chan->expected_ack_seq = __get_reqseq(rx_control);
3642 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003643
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003644 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003645 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3646 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3647 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003648 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003649 __mod_retrans_timer();
3650
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003651 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3652 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003653 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003654 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003655 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003656
3657 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003658 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003659
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003660 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3661 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003662 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003663 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003664
3665 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003666 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003667 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003668 __mod_retrans_timer();
3669
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003670 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3671 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3672 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003673 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003674 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003675 }
3676}
3677
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003678static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003679{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003680 u8 tx_seq = __get_reqseq(rx_control);
3681
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003682 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003683
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003684 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003685
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003686 chan->expected_ack_seq = tx_seq;
3687 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003688
3689 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003690 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3691 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003692 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003693 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003694 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003695 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003696
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003697 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3698 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003699 }
3700}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003701static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003702{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003703 u8 tx_seq = __get_reqseq(rx_control);
3704
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003705 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003706
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003707 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003708
3709 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003710 chan->expected_ack_seq = tx_seq;
3711 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003712
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003713 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3714 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003715
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003716 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003717
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003718 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003719 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003720 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003721 }
3722 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003723 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
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 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003727 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003728 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003729 l2cap_retransmit_one_frame(chan, tx_seq);
3730 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003731 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003732 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003733 }
3734 }
3735}
3736
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003737static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003738{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003739 u8 tx_seq = __get_reqseq(rx_control);
3740
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003741 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003742
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003743 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003744 chan->expected_ack_seq = tx_seq;
3745 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003746
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003747 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003748 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003749
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003750 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003751 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003752 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003753 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003754 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003755 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003756
3757 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003758 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003759 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003760 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003761}
3762
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003763static 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 -03003764{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003765 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003766
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003767 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003768 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003769 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003770 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003771 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003772 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003773 }
3774
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003775 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3776 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003777 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003778 break;
3779
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003780 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003781 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003782 break;
3783
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003784 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003785 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003786 break;
3787
3788 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003789 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003790 break;
3791 }
3792
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003793 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003794 return 0;
3795}
3796
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003797static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3798{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003799 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003800 u16 control;
3801 u8 req_seq;
3802 int len, next_tx_seq_offset, req_seq_offset;
3803
3804 control = get_unaligned_le16(skb->data);
3805 skb_pull(skb, 2);
3806 len = skb->len;
3807
3808 /*
3809 * We can just drop the corrupted I-frame here.
3810 * Receiver will miss it and start proper recovery
3811 * procedures and ask retransmission.
3812 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003813 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003814 goto drop;
3815
3816 if (__is_sar_start(control) && __is_iframe(control))
3817 len -= 2;
3818
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003819 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003820 len -= 2;
3821
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003822 if (len > chan->mps) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003823 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003824 goto drop;
3825 }
3826
3827 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003828 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003829 if (req_seq_offset < 0)
3830 req_seq_offset += 64;
3831
3832 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003833 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003834 if (next_tx_seq_offset < 0)
3835 next_tx_seq_offset += 64;
3836
3837 /* check for invalid req-seq */
3838 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003839 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003840 goto drop;
3841 }
3842
3843 if (__is_iframe(control)) {
3844 if (len < 0) {
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003845 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003846 goto drop;
3847 }
3848
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003849 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003850 } else {
3851 if (len != 0) {
3852 BT_ERR("%d", len);
Gustavo F. Padovan8c1d7872011-04-13 20:23:55 -03003853 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003854 goto drop;
3855 }
3856
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003857 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003858 }
3859
3860 return 0;
3861
3862drop:
3863 kfree_skb(skb);
3864 return 0;
3865}
3866
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3868{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003869 struct l2cap_chan *chan;
David S. Millerbf734842011-04-25 13:03:02 -07003870 struct sock *sk = NULL;
Nathan Holstein51893f82010-06-09 15:46:25 -04003871 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003872 u8 tx_seq;
3873 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003875 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003876 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877 BT_DBG("unknown cid 0x%4.4x", cid);
3878 goto drop;
3879 }
3880
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003881 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003882
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003883 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003884
3885 if (sk->sk_state != BT_CONNECTED)
3886 goto drop;
3887
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003888 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003889 case L2CAP_MODE_BASIC:
3890 /* If socket recv buffers overflows we drop data here
3891 * which is *bad* because L2CAP has to be reliable.
3892 * But we don't have any other choice. L2CAP doesn't
3893 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003895 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003896 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003898 if (!sock_queue_rcv_skb(sk, skb))
3899 goto done;
3900 break;
3901
3902 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003903 if (!sock_owned_by_user(sk)) {
3904 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003905 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003906 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003907 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003908 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003909
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003910 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003911
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003912 case L2CAP_MODE_STREAMING:
3913 control = get_unaligned_le16(skb->data);
3914 skb_pull(skb, 2);
3915 len = skb->len;
3916
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003917 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003918 goto drop;
3919
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003920 if (__is_sar_start(control))
3921 len -= 2;
3922
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003923 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003924 len -= 2;
3925
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003926 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003927 goto drop;
3928
3929 tx_seq = __get_txseq(control);
3930
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003931 if (chan->expected_tx_seq == tx_seq)
3932 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003933 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003934 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003935
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003936 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003937
3938 goto done;
3939
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003940 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003941 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003942 break;
3943 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944
3945drop:
3946 kfree_skb(skb);
3947
3948done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003949 if (sk)
3950 bh_unlock_sock(sk);
3951
Linus Torvalds1da177e2005-04-16 15:20:36 -07003952 return 0;
3953}
3954
Al Viro8e036fc2007-07-29 00:16:36 -07003955static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003957 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003958 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003960 chan = l2cap_global_chan_by_psm(0, psm, conn->src);
3961 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962 goto drop;
3963
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003964 sk = chan->sk;
3965
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003966 bh_lock_sock(sk);
3967
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968 BT_DBG("sk %p, len %d", sk, skb->len);
3969
3970 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3971 goto drop;
3972
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003973 if (l2cap_pi(sk)->chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974 goto drop;
3975
3976 if (!sock_queue_rcv_skb(sk, skb))
3977 goto done;
3978
3979drop:
3980 kfree_skb(skb);
3981
3982done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003983 if (sk)
3984 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985 return 0;
3986}
3987
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003988static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3989{
David S. Miller6dcae1e2011-05-16 23:09:26 -04003990 struct sock *sk = NULL;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003991 struct l2cap_chan *chan;
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003992
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003993 chan = l2cap_global_chan_by_scid(0, cid, conn->src);
3994 if (!chan)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003995 goto drop;
3996
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03003997 sk = chan->sk;
3998
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003999 bh_lock_sock(sk);
4000
4001 BT_DBG("sk %p, len %d", sk, skb->len);
4002
4003 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
4004 goto drop;
4005
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004006 if (l2cap_pi(sk)->chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004007 goto drop;
4008
4009 if (!sock_queue_rcv_skb(sk, skb))
4010 goto done;
4011
4012drop:
4013 kfree_skb(skb);
4014
4015done:
4016 if (sk)
4017 bh_unlock_sock(sk);
4018 return 0;
4019}
4020
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
4022{
4023 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07004024 u16 cid, len;
4025 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026
4027 skb_pull(skb, L2CAP_HDR_SIZE);
4028 cid = __le16_to_cpu(lh->cid);
4029 len = __le16_to_cpu(lh->len);
4030
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03004031 if (len != skb->len) {
4032 kfree_skb(skb);
4033 return;
4034 }
4035
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036 BT_DBG("len %d, cid 0x%4.4x", len, cid);
4037
4038 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02004039 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004040 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041 l2cap_sig_channel(conn, skb);
4042 break;
4043
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03004044 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03004045 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046 skb_pull(skb, 2);
4047 l2cap_conless_channel(conn, psm, skb);
4048 break;
4049
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03004050 case L2CAP_CID_LE_DATA:
4051 l2cap_att_channel(conn, cid, skb);
4052 break;
4053
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054 default:
4055 l2cap_data_channel(conn, cid, skb);
4056 break;
4057 }
4058}
4059
4060/* ---- L2CAP interface with lower layer (HCI) ---- */
4061
4062static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
4063{
4064 int exact = 0, lm1 = 0, lm2 = 0;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004065 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066
4067 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004068 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069
4070 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
4071
4072 /* Find listening sockets and check their link_mode */
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004073 read_lock(&chan_list_lock);
4074 list_for_each_entry(c, &chan_list, global_l) {
4075 struct sock *sk = c->sk;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004076
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077 if (sk->sk_state != BT_LISTEN)
4078 continue;
4079
4080 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004081 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004082 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004083 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004085 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
4086 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004087 if (c->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01004088 lm2 |= HCI_LM_MASTER;
4089 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090 }
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004091 read_unlock(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092
4093 return exact ? lm1 : lm2;
4094}
4095
4096static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
4097{
Marcel Holtmann01394182006-07-03 10:02:46 +02004098 struct l2cap_conn *conn;
4099
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
4101
Ville Tervoacd7d372011-02-10 22:38:49 -03004102 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004103 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104
4105 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106 conn = l2cap_conn_add(hcon, status);
4107 if (conn)
4108 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02004109 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110 l2cap_conn_del(hcon, bt_err(status));
4111
4112 return 0;
4113}
4114
Marcel Holtmann2950f212009-02-12 14:02:50 +01004115static int l2cap_disconn_ind(struct hci_conn *hcon)
4116{
4117 struct l2cap_conn *conn = hcon->l2cap_data;
4118
4119 BT_DBG("hcon %p", hcon);
4120
4121 if (hcon->type != ACL_LINK || !conn)
4122 return 0x13;
4123
4124 return conn->disc_reason;
4125}
4126
4127static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128{
4129 BT_DBG("hcon %p reason %d", hcon, reason);
4130
Ville Tervoacd7d372011-02-10 22:38:49 -03004131 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03004132 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133
4134 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02004135
Linus Torvalds1da177e2005-04-16 15:20:36 -07004136 return 0;
4137}
4138
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004139static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004140{
Gustavo F. Padovan715ec002011-05-02 17:13:55 -03004141 if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
Marcel Holtmann255c7602009-02-04 21:07:19 +01004142 return;
4143
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004144 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004145 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Gustavo F. Padovanab078012011-05-02 18:25:01 -03004146 l2cap_chan_clear_timer(chan);
4147 l2cap_chan_set_timer(chan, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004148 } else if (chan->sec_level == BT_SECURITY_HIGH)
Gustavo F. Padovan0f852722011-05-04 19:42:50 -03004149 l2cap_chan_close(chan, ECONNREFUSED);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004150 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004151 if (chan->sec_level == BT_SECURITY_MEDIUM)
Gustavo F. Padovanab078012011-05-02 18:25:01 -03004152 l2cap_chan_clear_timer(chan);
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004153 }
4154}
4155
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004156static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157{
Marcel Holtmann40be4922008-07-14 20:13:50 +02004158 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004159 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160
Marcel Holtmann01394182006-07-03 10:02:46 +02004161 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02004163
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164 BT_DBG("conn %p", conn);
4165
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004166 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004167
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004168 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004169 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004170
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171 bh_lock_sock(sk);
4172
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03004173 if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01004174 bh_unlock_sock(sk);
4175 continue;
4176 }
4177
Marcel Holtmannf62e4322009-01-15 21:58:44 +01004178 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004179 sk->sk_state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004180 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02004181 bh_unlock_sock(sk);
4182 continue;
4183 }
4184
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004185 if (sk->sk_state == BT_CONNECT) {
4186 if (!status) {
4187 struct l2cap_conn_req req;
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004188 req.scid = cpu_to_le16(chan->scid);
4189 req.psm = chan->psm;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004190
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004191 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03004192 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004193
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004194 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004195 L2CAP_CONN_REQ, sizeof(req), &req);
4196 } else {
Gustavo F. Padovanab078012011-05-02 18:25:01 -03004197 l2cap_chan_clear_timer(chan);
4198 l2cap_chan_set_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004199 }
4200 } else if (sk->sk_state == BT_CONNECT2) {
4201 struct l2cap_conn_rsp rsp;
4202 __u16 result;
4203
4204 if (!status) {
4205 sk->sk_state = BT_CONFIG;
4206 result = L2CAP_CR_SUCCESS;
4207 } else {
4208 sk->sk_state = BT_DISCONN;
Gustavo F. Padovanab078012011-05-02 18:25:01 -03004209 l2cap_chan_set_timer(chan, HZ / 10);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004210 result = L2CAP_CR_SEC_BLOCK;
4211 }
4212
Gustavo F. Padovanfe4128e2011-04-13 19:50:45 -03004213 rsp.scid = cpu_to_le16(chan->dcid);
4214 rsp.dcid = cpu_to_le16(chan->scid);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004215 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02004216 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03004217 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4218 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004219 }
4220
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221 bh_unlock_sock(sk);
4222 }
4223
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004224 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02004225
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226 return 0;
4227}
4228
4229static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
4230{
4231 struct l2cap_conn *conn = hcon->l2cap_data;
4232
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02004233 if (!conn)
4234 conn = l2cap_conn_add(hcon, 0);
4235
4236 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004237 goto drop;
4238
4239 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
4240
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02004241 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004243 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004244 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245 int len;
4246
4247 if (conn->rx_len) {
4248 BT_ERR("Unexpected start frame (len %d)", skb->len);
4249 kfree_skb(conn->rx_skb);
4250 conn->rx_skb = NULL;
4251 conn->rx_len = 0;
4252 l2cap_conn_unreliable(conn, ECOMM);
4253 }
4254
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03004255 /* Start fragment always begin with Basic L2CAP header */
4256 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257 BT_ERR("Frame is too short (len %d)", skb->len);
4258 l2cap_conn_unreliable(conn, ECOMM);
4259 goto drop;
4260 }
4261
4262 hdr = (struct l2cap_hdr *) skb->data;
4263 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004264 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265
4266 if (len == skb->len) {
4267 /* Complete frame received */
4268 l2cap_recv_frame(conn, skb);
4269 return 0;
4270 }
4271
4272 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4273
4274 if (skb->len > len) {
4275 BT_ERR("Frame is too long (len %d, expected len %d)",
4276 skb->len, len);
4277 l2cap_conn_unreliable(conn, ECOMM);
4278 goto drop;
4279 }
4280
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004281 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004282
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004283 if (chan && chan->sk) {
4284 struct sock *sk = chan->sk;
4285
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004286 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004287 BT_ERR("Frame exceeding recv MTU (len %d, "
4288 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004289 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004290 bh_unlock_sock(sk);
4291 l2cap_conn_unreliable(conn, ECOMM);
4292 goto drop;
4293 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004294 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004295 }
4296
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004298 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4299 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300 goto drop;
4301
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004302 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004303 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004304 conn->rx_len = len - skb->len;
4305 } else {
4306 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4307
4308 if (!conn->rx_len) {
4309 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4310 l2cap_conn_unreliable(conn, ECOMM);
4311 goto drop;
4312 }
4313
4314 if (skb->len > conn->rx_len) {
4315 BT_ERR("Fragment is too long (len %d, expected %d)",
4316 skb->len, conn->rx_len);
4317 kfree_skb(conn->rx_skb);
4318 conn->rx_skb = NULL;
4319 conn->rx_len = 0;
4320 l2cap_conn_unreliable(conn, ECOMM);
4321 goto drop;
4322 }
4323
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004324 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004325 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326 conn->rx_len -= skb->len;
4327
4328 if (!conn->rx_len) {
4329 /* Complete frame received */
4330 l2cap_recv_frame(conn, conn->rx_skb);
4331 conn->rx_skb = NULL;
4332 }
4333 }
4334
4335drop:
4336 kfree_skb(skb);
4337 return 0;
4338}
4339
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004340static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341{
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004342 struct l2cap_chan *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004344 read_lock_bh(&chan_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004346 list_for_each_entry(c, &chan_list, global_l) {
4347 struct sock *sk = c->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004348
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004349 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 +01004350 batostr(&bt_sk(sk)->src),
4351 batostr(&bt_sk(sk)->dst),
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004352 sk->sk_state, __le16_to_cpu(c->psm),
4353 c->scid, c->dcid, c->imtu, c->omtu,
4354 c->sec_level, c->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004355 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004356
Gustavo F. Padovan23691d72011-04-27 18:26:32 -03004357 read_unlock_bh(&chan_list_lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004358
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004359 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004360}
4361
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004362static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4363{
4364 return single_open(file, l2cap_debugfs_show, inode->i_private);
4365}
4366
4367static const struct file_operations l2cap_debugfs_fops = {
4368 .open = l2cap_debugfs_open,
4369 .read = seq_read,
4370 .llseek = seq_lseek,
4371 .release = single_release,
4372};
4373
4374static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376static struct hci_proto l2cap_hci_proto = {
4377 .name = "L2CAP",
4378 .id = HCI_PROTO_L2CAP,
4379 .connect_ind = l2cap_connect_ind,
4380 .connect_cfm = l2cap_connect_cfm,
4381 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004382 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004383 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384 .recv_acldata = l2cap_recv_acldata
4385};
4386
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004387int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004388{
4389 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004390
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004391 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392 if (err < 0)
4393 return err;
4394
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004395 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004396 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004397 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398 goto error;
4399 }
4400
4401 err = hci_register_proto(&l2cap_hci_proto);
4402 if (err < 0) {
4403 BT_ERR("L2CAP protocol registration failed");
4404 bt_sock_unregister(BTPROTO_L2CAP);
4405 goto error;
4406 }
4407
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004408 if (bt_debugfs) {
4409 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4410 bt_debugfs, NULL, &l2cap_debugfs_fops);
4411 if (!l2cap_debugfs)
4412 BT_ERR("Failed to create L2CAP debug file");
4413 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415 return 0;
4416
4417error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004418 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004419 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420 return err;
4421}
4422
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004423void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004425 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004426
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004427 flush_workqueue(_busy_wq);
4428 destroy_workqueue(_busy_wq);
4429
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4431 BT_ERR("L2CAP protocol unregistration failed");
4432
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004433 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434}
4435
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004436module_param(disable_ertm, bool, 0644);
4437MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");