blob: d3b5d6489a80fd591c19de859d29fb3884b0058b [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. Padovanbb58f742011-02-03 20:50:35 -020065struct bt_sock_list l2cap_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070066 .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070067};
68
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030069static void l2cap_busy_work(struct work_struct *work);
70
Linus Torvalds1da177e2005-04-16 15:20:36 -070071static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
72 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030073static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030075static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
76
Marcel Holtmann01394182006-07-03 10:02:46 +020077/* ---- L2CAP channels ---- */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030078static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020079{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030080 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030081
82 list_for_each_entry(c, &conn->chan_l, list) {
83 struct sock *s = c->sk;
84 if (l2cap_pi(s)->dcid == cid)
85 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020086 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030087 return NULL;
88
Marcel Holtmann01394182006-07-03 10:02:46 +020089}
90
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030091static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020092{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030093 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030094
95 list_for_each_entry(c, &conn->chan_l, list) {
96 struct sock *s = c->sk;
97 if (l2cap_pi(s)->scid == cid)
98 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020099 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300100 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200101}
102
103/* Find channel with given SCID.
104 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300105static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200106{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300107 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300108
109 read_lock(&conn->chan_lock);
110 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300111 if (c)
112 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300113 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300114 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200115}
116
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300117static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200118{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300119 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300120
121 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300122 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300123 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200124 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300125 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200126}
127
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300128static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200129{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300130 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300131
132 read_lock(&conn->chan_lock);
133 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300134 if (c)
135 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300136 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300137 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200138}
139
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300140static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200141{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300142 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200143
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300144 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300145 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200146 return cid;
147 }
148
149 return 0;
150}
151
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300152static struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200153{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300154 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200155
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300156 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
157 if (!chan)
158 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200159
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300160 chan->sk = sk;
161
162 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200163}
164
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300165static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200166{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300167 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200168
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300169 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
170 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200171
Marcel Holtmann2950f212009-02-12 14:02:50 +0100172 conn->disc_reason = 0x13;
173
Marcel Holtmann01394182006-07-03 10:02:46 +0200174 l2cap_pi(sk)->conn = conn;
175
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300176 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Ville Tervob62f3282011-02-10 22:38:50 -0300177 if (conn->hcon->type == LE_LINK) {
178 /* LE connection */
179 l2cap_pi(sk)->omtu = L2CAP_LE_DEFAULT_MTU;
180 l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA;
181 l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA;
182 } else {
183 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300184 l2cap_pi(sk)->scid = l2cap_alloc_cid(conn);
Ville Tervob62f3282011-02-10 22:38:50 -0300185 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
186 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200187 } else if (sk->sk_type == SOCK_DGRAM) {
188 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300189 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
190 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200191 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
192 } else {
193 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300194 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
195 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200196 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
197 }
198
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300199 sock_hold(sk);
200
201 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200202}
203
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900204/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200205 * Must be called on the locked socket. */
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300206void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200207{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300208 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200209 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
210 struct sock *parent = bt_sk(sk)->parent;
211
212 l2cap_sock_clear_timer(sk);
213
214 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
215
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900216 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300217 /* Delete from channel list */
218 write_lock_bh(&conn->chan_lock);
219 list_del(&chan->list);
220 write_unlock_bh(&conn->chan_lock);
221 __sock_put(sk);
222
Marcel Holtmann01394182006-07-03 10:02:46 +0200223 l2cap_pi(sk)->conn = NULL;
224 hci_conn_put(conn->hcon);
225 }
226
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200227 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200228 sock_set_flag(sk, SOCK_ZAPPED);
229
230 if (err)
231 sk->sk_err = err;
232
233 if (parent) {
234 bt_accept_unlink(sk);
235 parent->sk_data_ready(parent, 0);
236 } else
237 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300238
239 skb_queue_purge(TX_QUEUE(sk));
240
241 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
242 struct srej_list *l, *tmp;
243
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300244 del_timer(&chan->retrans_timer);
245 del_timer(&chan->monitor_timer);
246 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300247
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300248 skb_queue_purge(&chan->srej_q);
249 skb_queue_purge(&chan->busy_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300250
251 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
252 list_del(&l->list);
253 kfree(l);
254 }
255 }
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300256
257 kfree(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200258}
259
Johan Hedberg8556edd32011-01-19 12:06:50 +0530260static inline u8 l2cap_get_auth_type(struct sock *sk)
261{
262 if (sk->sk_type == SOCK_RAW) {
263 switch (l2cap_pi(sk)->sec_level) {
264 case BT_SECURITY_HIGH:
265 return HCI_AT_DEDICATED_BONDING_MITM;
266 case BT_SECURITY_MEDIUM:
267 return HCI_AT_DEDICATED_BONDING;
268 default:
269 return HCI_AT_NO_BONDING;
270 }
271 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
272 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
273 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
274
275 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
276 return HCI_AT_NO_BONDING_MITM;
277 else
278 return HCI_AT_NO_BONDING;
279 } else {
280 switch (l2cap_pi(sk)->sec_level) {
281 case BT_SECURITY_HIGH:
282 return HCI_AT_GENERAL_BONDING_MITM;
283 case BT_SECURITY_MEDIUM:
284 return HCI_AT_GENERAL_BONDING;
285 default:
286 return HCI_AT_NO_BONDING;
287 }
288 }
289}
290
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200291/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100292static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200293{
294 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100295 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200296
Johan Hedberg8556edd32011-01-19 12:06:50 +0530297 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100298
299 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
300 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200301}
302
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200303u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200304{
305 u8 id;
306
307 /* Get next available identificator.
308 * 1 - 128 are used by kernel.
309 * 129 - 199 are reserved.
310 * 200 - 254 are used by utilities like l2ping, etc.
311 */
312
313 spin_lock_bh(&conn->lock);
314
315 if (++conn->tx_ident > 128)
316 conn->tx_ident = 1;
317
318 id = conn->tx_ident;
319
320 spin_unlock_bh(&conn->lock);
321
322 return id;
323}
324
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200325void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200326{
327 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200328 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200329
330 BT_DBG("code 0x%2.2x", code);
331
332 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300333 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200334
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200335 if (lmp_no_flush_capable(conn->hcon->hdev))
336 flags = ACL_START_NO_FLUSH;
337 else
338 flags = ACL_START;
339
340 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200341}
342
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300343static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300344{
345 struct sk_buff *skb;
346 struct l2cap_hdr *lh;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300347 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300348 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300349 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300350 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200351 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300352
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300353 if (sk->sk_state != BT_CONNECTED)
354 return;
355
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300356 if (pi->fcs == L2CAP_FCS_CRC16)
357 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300358
359 BT_DBG("pi %p, control 0x%2.2x", pi, control);
360
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300361 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300362 control |= L2CAP_CTRL_FRAME_TYPE;
363
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300364 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300365 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300366 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300367 }
368
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300369 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300370 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300371 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300372 }
373
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300374 skb = bt_skb_alloc(count, GFP_ATOMIC);
375 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300376 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300377
378 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300379 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300380 lh->cid = cpu_to_le16(pi->dcid);
381 put_unaligned_le16(control, skb_put(skb, 2));
382
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300383 if (pi->fcs == L2CAP_FCS_CRC16) {
384 u16 fcs = crc16(0, (u8 *)lh, count - 2);
385 put_unaligned_le16(fcs, skb_put(skb, 2));
386 }
387
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200388 if (lmp_no_flush_capable(conn->hcon->hdev))
389 flags = ACL_START_NO_FLUSH;
390 else
391 flags = ACL_START;
392
393 hci_send_acl(pi->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300394}
395
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300396static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300397{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300398 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300399 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300400 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300401 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300402 control |= L2CAP_SUPER_RCV_READY;
403
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300404 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300405
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300406 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300407}
408
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300409static inline int __l2cap_no_conn_pending(struct sock *sk)
410{
411 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
412}
413
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300414static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200415{
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300416 struct sock *sk = chan->sk;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200417 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
418
419 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100420 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
421 return;
422
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300423 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200424 struct l2cap_conn_req req;
425 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
426 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200427
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300428 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300429 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200430
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300431 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
432 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200433 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200434 } else {
435 struct l2cap_info_req req;
436 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
437
438 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
439 conn->info_ident = l2cap_get_ident(conn);
440
441 mod_timer(&conn->info_timer, jiffies +
442 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
443
444 l2cap_send_cmd(conn, conn->info_ident,
445 L2CAP_INFO_REQ, sizeof(req), &req);
446 }
447}
448
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300449static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
450{
451 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300452 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300453 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
454
455 switch (mode) {
456 case L2CAP_MODE_ERTM:
457 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
458 case L2CAP_MODE_STREAMING:
459 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
460 default:
461 return 0x00;
462 }
463}
464
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300465void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300466{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300467 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300468 struct l2cap_disconn_req req;
469
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300470 if (!conn)
471 return;
472
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300473 sk = chan->sk;
474
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300475 skb_queue_purge(TX_QUEUE(sk));
476
477 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300478 del_timer(&chan->retrans_timer);
479 del_timer(&chan->monitor_timer);
480 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300481 }
482
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300483 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
484 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
485 l2cap_send_cmd(conn, l2cap_get_ident(conn),
486 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300487
488 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300489 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300490}
491
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200493static void l2cap_conn_start(struct l2cap_conn *conn)
494{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300495 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200496
497 BT_DBG("conn %p", conn);
498
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300499 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200500
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300501 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300502 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300503
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200504 bh_lock_sock(sk);
505
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300506 if (sk->sk_type != SOCK_SEQPACKET &&
507 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200508 bh_unlock_sock(sk);
509 continue;
510 }
511
512 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300513 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300514
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300515 if (!l2cap_check_security(sk) ||
516 !__l2cap_no_conn_pending(sk)) {
517 bh_unlock_sock(sk);
518 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200519 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300520
521 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
522 conn->feat_mask)
523 && l2cap_pi(sk)->conf_state &
524 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300525 /* __l2cap_sock_close() calls list_del(chan)
526 * so release the lock */
527 read_unlock_bh(&conn->chan_lock);
528 __l2cap_sock_close(sk, ECONNRESET);
529 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300530 bh_unlock_sock(sk);
531 continue;
532 }
533
534 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
535 req.psm = l2cap_pi(sk)->psm;
536
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300537 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300538 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
539
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300540 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
541 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300542
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200543 } else if (sk->sk_state == BT_CONNECT2) {
544 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300545 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200546 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
547 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
548
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100549 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100550 if (bt_sk(sk)->defer_setup) {
551 struct sock *parent = bt_sk(sk)->parent;
552 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
553 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
554 parent->sk_data_ready(parent, 0);
555
556 } else {
557 sk->sk_state = BT_CONFIG;
558 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
559 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
560 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200561 } else {
562 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
563 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
564 }
565
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300566 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
567 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300568
569 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
570 rsp.result != L2CAP_CR_SUCCESS) {
571 bh_unlock_sock(sk);
572 continue;
573 }
574
575 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
576 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300577 l2cap_build_conf_req(chan, buf), buf);
578 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200579 }
580
581 bh_unlock_sock(sk);
582 }
583
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300584 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200585}
586
Ville Tervob62f3282011-02-10 22:38:50 -0300587/* Find socket with cid and source bdaddr.
588 * Returns closest match, locked.
589 */
590static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
591{
592 struct sock *s, *sk = NULL, *sk1 = NULL;
593 struct hlist_node *node;
594
595 read_lock(&l2cap_sk_list.lock);
596
597 sk_for_each(sk, node, &l2cap_sk_list.head) {
598 if (state && sk->sk_state != state)
599 continue;
600
601 if (l2cap_pi(sk)->scid == cid) {
602 /* Exact match. */
603 if (!bacmp(&bt_sk(sk)->src, src))
604 break;
605
606 /* Closest match */
607 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
608 sk1 = sk;
609 }
610 }
611 s = node ? sk : sk1;
612 if (s)
613 bh_lock_sock(s);
614 read_unlock(&l2cap_sk_list.lock);
615
616 return s;
617}
618
619static void l2cap_le_conn_ready(struct l2cap_conn *conn)
620{
Ville Tervob62f3282011-02-10 22:38:50 -0300621 struct sock *parent, *uninitialized_var(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300622 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300623
624 BT_DBG("");
625
626 /* Check if we have socket listening on cid */
627 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
628 conn->src);
629 if (!parent)
630 return;
631
632 /* Check for backlog size */
633 if (sk_acceptq_is_full(parent)) {
634 BT_DBG("backlog full %d", parent->sk_ack_backlog);
635 goto clean;
636 }
637
638 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
639 if (!sk)
640 goto clean;
641
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300642 chan = l2cap_chan_alloc(sk);
643 if (!chan) {
644 l2cap_sock_kill(sk);
645 goto clean;
646 }
647
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300648 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300649
650 hci_conn_hold(conn->hcon);
651
652 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300653
Ville Tervob62f3282011-02-10 22:38:50 -0300654 bacpy(&bt_sk(sk)->src, conn->src);
655 bacpy(&bt_sk(sk)->dst, conn->dst);
656
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300657 bt_accept_enqueue(parent, sk);
658
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300659 __l2cap_chan_add(conn, chan);
660
661 l2cap_pi(sk)->chan = chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300662
663 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
664
665 sk->sk_state = BT_CONNECTED;
666 parent->sk_data_ready(parent, 0);
667
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300668 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300669
670clean:
671 bh_unlock_sock(parent);
672}
673
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200674static void l2cap_conn_ready(struct l2cap_conn *conn)
675{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300676 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200677
678 BT_DBG("conn %p", conn);
679
Ville Tervob62f3282011-02-10 22:38:50 -0300680 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
681 l2cap_le_conn_ready(conn);
682
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300683 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200684
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300685 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300686 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300687
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200688 bh_lock_sock(sk);
689
Ville Tervoacd7d372011-02-10 22:38:49 -0300690 if (conn->hcon->type == LE_LINK) {
691 l2cap_sock_clear_timer(sk);
692 sk->sk_state = BT_CONNECTED;
693 sk->sk_state_change(sk);
694 }
695
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300696 if (sk->sk_type != SOCK_SEQPACKET &&
697 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200698 l2cap_sock_clear_timer(sk);
699 sk->sk_state = BT_CONNECTED;
700 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200701 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300702 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200703
704 bh_unlock_sock(sk);
705 }
706
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300707 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200708}
709
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200710/* Notify sockets that we cannot guaranty reliability anymore */
711static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
712{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300713 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200714
715 BT_DBG("conn %p", conn);
716
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300717 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200718
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300719 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300720 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300721
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100722 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200723 sk->sk_err = err;
724 }
725
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300726 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200727}
728
729static void l2cap_info_timeout(unsigned long arg)
730{
731 struct l2cap_conn *conn = (void *) arg;
732
Marcel Holtmann984947d2009-02-06 23:35:19 +0100733 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100734 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100735
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200736 l2cap_conn_start(conn);
737}
738
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
740{
Marcel Holtmann01394182006-07-03 10:02:46 +0200741 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742
Marcel Holtmann01394182006-07-03 10:02:46 +0200743 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 return conn;
745
Marcel Holtmann01394182006-07-03 10:02:46 +0200746 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
747 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749
750 hcon->l2cap_data = conn;
751 conn->hcon = hcon;
752
Marcel Holtmann01394182006-07-03 10:02:46 +0200753 BT_DBG("hcon %p conn %p", hcon, conn);
754
Ville Tervoacd7d372011-02-10 22:38:49 -0300755 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
756 conn->mtu = hcon->hdev->le_mtu;
757 else
758 conn->mtu = hcon->hdev->acl_mtu;
759
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 conn->src = &hcon->hdev->bdaddr;
761 conn->dst = &hcon->dst;
762
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200763 conn->feat_mask = 0;
764
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300766 rwlock_init(&conn->chan_lock);
767
768 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769
Ville Tervob62f3282011-02-10 22:38:50 -0300770 if (hcon->type != LE_LINK)
771 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000772 (unsigned long) conn);
773
Marcel Holtmann2950f212009-02-12 14:02:50 +0100774 conn->disc_reason = 0x13;
775
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 return conn;
777}
778
Marcel Holtmann01394182006-07-03 10:02:46 +0200779static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780{
Marcel Holtmann01394182006-07-03 10:02:46 +0200781 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300782 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 struct sock *sk;
784
Marcel Holtmann01394182006-07-03 10:02:46 +0200785 if (!conn)
786 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787
788 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
789
Wei Yongjun7585b972009-02-25 18:29:52 +0800790 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
792 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300793 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300794 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300796 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 bh_unlock_sock(sk);
798 l2cap_sock_kill(sk);
799 }
800
Dave Young8e8440f2008-03-03 12:18:55 -0800801 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
802 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800803
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 hcon->l2cap_data = NULL;
805 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806}
807
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300808static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300810 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300811 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300812 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813}
814
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816
817/* Find socket with psm and source bdaddr.
818 * Returns closest match.
819 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000820static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821{
822 struct sock *sk = NULL, *sk1 = NULL;
823 struct hlist_node *node;
824
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000825 read_lock(&l2cap_sk_list.lock);
826
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 sk_for_each(sk, node, &l2cap_sk_list.head) {
828 if (state && sk->sk_state != state)
829 continue;
830
831 if (l2cap_pi(sk)->psm == psm) {
832 /* Exact match. */
833 if (!bacmp(&bt_sk(sk)->src, src))
834 break;
835
836 /* Closest match */
837 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
838 sk1 = sk;
839 }
840 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000843
844 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845}
846
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200847int l2cap_do_connect(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848{
849 bdaddr_t *src = &bt_sk(sk)->src;
850 bdaddr_t *dst = &bt_sk(sk)->dst;
851 struct l2cap_conn *conn;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300852 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 struct hci_conn *hcon;
854 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200855 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200856 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100858 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
859 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300861 hdev = hci_get_route(dst, src);
862 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 return -EHOSTUNREACH;
864
865 hci_dev_lock_bh(hdev);
866
Johan Hedberg8556edd32011-01-19 12:06:50 +0530867 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200868
Ville Tervoacd7d372011-02-10 22:38:49 -0300869 if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
870 hcon = hci_connect(hdev, LE_LINK, dst,
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100871 l2cap_pi(sk)->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300872 else
873 hcon = hci_connect(hdev, ACL_LINK, dst,
874 l2cap_pi(sk)->sec_level, auth_type);
875
Ville Tervo30e76272011-02-22 16:10:53 -0300876 if (IS_ERR(hcon)) {
877 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300879 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880
881 conn = l2cap_conn_add(hcon, 0);
882 if (!conn) {
883 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300884 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 goto done;
886 }
887
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300888 chan = l2cap_chan_alloc(sk);
889 if (!chan) {
890 hci_conn_put(hcon);
891 err = -ENOMEM;
892 goto done;
893 }
894
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 /* Update source addr of the socket */
896 bacpy(src, conn->src);
897
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300898 l2cap_chan_add(conn, chan);
899
900 l2cap_pi(sk)->chan = chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901
902 sk->sk_state = BT_CONNECT;
903 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
904
905 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300906 if (sk->sk_type != SOCK_SEQPACKET &&
907 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530909 if (l2cap_check_security(sk))
910 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200911 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300912 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 }
914
Ville Tervo30e76272011-02-22 16:10:53 -0300915 err = 0;
916
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917done:
918 hci_dev_unlock_bh(hdev);
919 hci_dev_put(hdev);
920 return err;
921}
922
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200923int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300924{
925 DECLARE_WAITQUEUE(wait, current);
926 int err = 0;
927 int timeo = HZ/5;
928
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200929 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300930 while ((l2cap_pi(sk)->chan->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300931 set_current_state(TASK_INTERRUPTIBLE);
932
933 if (!timeo)
934 timeo = HZ/5;
935
936 if (signal_pending(current)) {
937 err = sock_intr_errno(timeo);
938 break;
939 }
940
941 release_sock(sk);
942 timeo = schedule_timeout(timeo);
943 lock_sock(sk);
944
945 err = sock_error(sk);
946 if (err)
947 break;
948 }
949 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200950 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300951 return err;
952}
953
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300954static void l2cap_monitor_timeout(unsigned long arg)
955{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300956 struct l2cap_chan *chan = (void *) arg;
957 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300958
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300959 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300960
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300961 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -0300962 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300963 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200964 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300965 return;
966 }
967
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300968 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300969 __mod_monitor_timer();
970
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300971 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300972 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300973}
974
975static void l2cap_retrans_timeout(unsigned long arg)
976{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300977 struct l2cap_chan *chan = (void *) arg;
978 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300979
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300980 BT_DBG("sk %p", sk);
981
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300982 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300983 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300984 __mod_monitor_timer();
985
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300986 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300987
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300988 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300989 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300990}
991
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300992static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300993{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300994 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300995 struct sk_buff *skb;
996
Gustavo F. Padovan812e7372010-05-01 16:15:42 -0300997 while ((skb = skb_peek(TX_QUEUE(sk))) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300998 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300999 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001000 break;
1001
1002 skb = skb_dequeue(TX_QUEUE(sk));
1003 kfree_skb(skb);
1004
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001005 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001006 }
1007
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001008 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001009 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001010}
1011
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001012void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001013{
1014 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001015 struct hci_conn *hcon = pi->conn->hcon;
1016 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001017
1018 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1019
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001020 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
1021 flags = ACL_START_NO_FLUSH;
1022 else
1023 flags = ACL_START;
1024
1025 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001026}
1027
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001028void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001029{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001030 struct sock *sk = chan->sk;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001031 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001032 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001033 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001034
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001035 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
1036 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001037 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001038 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001039
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001040 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001041 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1042 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001043 }
1044
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001045 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001046
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001047 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001048 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001049}
1050
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001051static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001052{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001053 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001054 struct l2cap_pinfo *pi = l2cap_pi(sk);
1055 struct sk_buff *skb, *tx_skb;
1056 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001057
1058 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001059 if (!skb)
1060 return;
1061
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001062 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001063 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001064 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001065
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001066 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1067 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001068
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001069 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001070
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001071 if (chan->remote_max_tx &&
1072 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001073 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001074 return;
1075 }
1076
1077 tx_skb = skb_clone(skb, GFP_ATOMIC);
1078 bt_cb(skb)->retries++;
1079 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001080
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001081 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001082 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001083 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001084 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001085
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001086 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001087 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001088
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001089 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1090
1091 if (pi->fcs == L2CAP_FCS_CRC16) {
1092 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1093 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1094 }
1095
1096 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001097}
1098
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001099int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001100{
1101 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001102 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001103 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001104 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001105 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001106
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001107 if (sk->sk_state != BT_CONNECTED)
1108 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001109
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001110 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001111
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001112 if (chan->remote_max_tx &&
1113 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001114 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001115 break;
1116 }
1117
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001118 tx_skb = skb_clone(skb, GFP_ATOMIC);
1119
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001120 bt_cb(skb)->retries++;
1121
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001122 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001123 control &= L2CAP_CTRL_SAR;
1124
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001125 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001126 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001127 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001128 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001129 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1130 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001131 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1132
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001133
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001134 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001135 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1136 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1137 }
1138
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001139 l2cap_do_send(sk, tx_skb);
1140
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001141 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001142
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001143 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1144 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001145
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301146 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001147 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301148
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001149 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001150
1151 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1152 sk->sk_send_head = NULL;
1153 else
1154 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001155
1156 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001157 }
1158
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001159 return nsent;
1160}
1161
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001162static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001163{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001164 struct sock *sk = chan->sk;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001165 int ret;
1166
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001167 if (!skb_queue_empty(TX_QUEUE(sk)))
1168 sk->sk_send_head = TX_QUEUE(sk)->next;
1169
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001170 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001171 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001172 return ret;
1173}
1174
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001175static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001176{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001177 u16 control = 0;
1178
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001179 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001180
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001181 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001182 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001183 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1184 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001185 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001186 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001187
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001188 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001189 return;
1190
1191 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001192 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001193}
1194
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001195static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001196{
1197 struct srej_list *tail;
1198 u16 control;
1199
1200 control = L2CAP_SUPER_SELECT_REJECT;
1201 control |= L2CAP_CTRL_FINAL;
1202
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001203 tail = list_entry(SREJ_LIST(chan->sk)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001204 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1205
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001206 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001207}
1208
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001209static 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 -07001210{
1211 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001212 struct sk_buff **frag;
1213 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001215 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001216 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217
1218 sent += count;
1219 len -= count;
1220
1221 /* Continuation fragments (no L2CAP header) */
1222 frag = &skb_shinfo(skb)->frag_list;
1223 while (len) {
1224 count = min_t(unsigned int, conn->mtu, len);
1225
1226 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1227 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001228 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001229 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1230 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231
1232 sent += count;
1233 len -= count;
1234
1235 frag = &(*frag)->next;
1236 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237
1238 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001239}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001241struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001242{
1243 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1244 struct sk_buff *skb;
1245 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1246 struct l2cap_hdr *lh;
1247
1248 BT_DBG("sk %p len %d", sk, (int)len);
1249
1250 count = min_t(unsigned int, (conn->mtu - hlen), len);
1251 skb = bt_skb_send_alloc(sk, count + hlen,
1252 msg->msg_flags & MSG_DONTWAIT, &err);
1253 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001254 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001255
1256 /* Create L2CAP header */
1257 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1258 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1259 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1260 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1261
1262 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1263 if (unlikely(err < 0)) {
1264 kfree_skb(skb);
1265 return ERR_PTR(err);
1266 }
1267 return skb;
1268}
1269
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001270struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001271{
1272 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1273 struct sk_buff *skb;
1274 int err, count, hlen = L2CAP_HDR_SIZE;
1275 struct l2cap_hdr *lh;
1276
1277 BT_DBG("sk %p len %d", sk, (int)len);
1278
1279 count = min_t(unsigned int, (conn->mtu - hlen), len);
1280 skb = bt_skb_send_alloc(sk, count + hlen,
1281 msg->msg_flags & MSG_DONTWAIT, &err);
1282 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001283 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001284
1285 /* Create L2CAP header */
1286 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1287 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1288 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1289
1290 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1291 if (unlikely(err < 0)) {
1292 kfree_skb(skb);
1293 return ERR_PTR(err);
1294 }
1295 return skb;
1296}
1297
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001298struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001299{
1300 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1301 struct sk_buff *skb;
1302 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1303 struct l2cap_hdr *lh;
1304
1305 BT_DBG("sk %p len %d", sk, (int)len);
1306
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001307 if (!conn)
1308 return ERR_PTR(-ENOTCONN);
1309
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001310 if (sdulen)
1311 hlen += 2;
1312
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001313 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1314 hlen += 2;
1315
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001316 count = min_t(unsigned int, (conn->mtu - hlen), len);
1317 skb = bt_skb_send_alloc(sk, count + hlen,
1318 msg->msg_flags & MSG_DONTWAIT, &err);
1319 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001320 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001321
1322 /* Create L2CAP header */
1323 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1324 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1325 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1326 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001327 if (sdulen)
1328 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001329
1330 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1331 if (unlikely(err < 0)) {
1332 kfree_skb(skb);
1333 return ERR_PTR(err);
1334 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001335
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001336 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1337 put_unaligned_le16(0, skb_put(skb, 2));
1338
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001339 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001340 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341}
1342
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001343int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001344{
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001345 struct sock *sk = chan->sk;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001346 struct sk_buff *skb;
1347 struct sk_buff_head sar_queue;
1348 u16 control;
1349 size_t size = 0;
1350
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001351 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001352 control = L2CAP_SDU_START;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001353 skb = l2cap_create_iframe_pdu(sk, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001354 if (IS_ERR(skb))
1355 return PTR_ERR(skb);
1356
1357 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001358 len -= chan->remote_mps;
1359 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001360
1361 while (len > 0) {
1362 size_t buflen;
1363
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001364 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001365 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001366 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001367 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001368 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001369 buflen = len;
1370 }
1371
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001372 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001373 if (IS_ERR(skb)) {
1374 skb_queue_purge(&sar_queue);
1375 return PTR_ERR(skb);
1376 }
1377
1378 __skb_queue_tail(&sar_queue, skb);
1379 len -= buflen;
1380 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001381 }
1382 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1383 if (sk->sk_send_head == NULL)
1384 sk->sk_send_head = sar_queue.next;
1385
1386 return size;
1387}
1388
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389static void l2cap_chan_ready(struct sock *sk)
1390{
1391 struct sock *parent = bt_sk(sk)->parent;
1392
1393 BT_DBG("sk %p, parent %p", sk, parent);
1394
1395 l2cap_pi(sk)->conf_state = 0;
1396 l2cap_sock_clear_timer(sk);
1397
1398 if (!parent) {
1399 /* Outgoing channel.
1400 * Wake up socket sleeping on connect.
1401 */
1402 sk->sk_state = BT_CONNECTED;
1403 sk->sk_state_change(sk);
1404 } else {
1405 /* Incoming channel.
1406 * Wake up socket sleeping on accept.
1407 */
1408 parent->sk_data_ready(parent, 0);
1409 }
1410}
1411
1412/* Copy frame to all raw sockets on that connection */
1413static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1414{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001416 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417
1418 BT_DBG("conn %p", conn);
1419
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001420 read_lock(&conn->chan_lock);
1421 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001422 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 if (sk->sk_type != SOCK_RAW)
1424 continue;
1425
1426 /* Don't send frame to the socket it came from */
1427 if (skb->sk == sk)
1428 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001429 nskb = skb_clone(skb, GFP_ATOMIC);
1430 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 continue;
1432
1433 if (sock_queue_rcv_skb(sk, nskb))
1434 kfree_skb(nskb);
1435 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001436 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437}
1438
1439/* ---- L2CAP signalling commands ---- */
1440static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1441 u8 code, u8 ident, u16 dlen, void *data)
1442{
1443 struct sk_buff *skb, **frag;
1444 struct l2cap_cmd_hdr *cmd;
1445 struct l2cap_hdr *lh;
1446 int len, count;
1447
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001448 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1449 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450
1451 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1452 count = min_t(unsigned int, conn->mtu, len);
1453
1454 skb = bt_skb_alloc(count, GFP_ATOMIC);
1455 if (!skb)
1456 return NULL;
1457
1458 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001459 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001460
1461 if (conn->hcon->type == LE_LINK)
1462 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1463 else
1464 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465
1466 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1467 cmd->code = code;
1468 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001469 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
1471 if (dlen) {
1472 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1473 memcpy(skb_put(skb, count), data, count);
1474 data += count;
1475 }
1476
1477 len -= skb->len;
1478
1479 /* Continuation fragments (no L2CAP header) */
1480 frag = &skb_shinfo(skb)->frag_list;
1481 while (len) {
1482 count = min_t(unsigned int, conn->mtu, len);
1483
1484 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1485 if (!*frag)
1486 goto fail;
1487
1488 memcpy(skb_put(*frag, count), data, count);
1489
1490 len -= count;
1491 data += count;
1492
1493 frag = &(*frag)->next;
1494 }
1495
1496 return skb;
1497
1498fail:
1499 kfree_skb(skb);
1500 return NULL;
1501}
1502
1503static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1504{
1505 struct l2cap_conf_opt *opt = *ptr;
1506 int len;
1507
1508 len = L2CAP_CONF_OPT_SIZE + opt->len;
1509 *ptr += len;
1510
1511 *type = opt->type;
1512 *olen = opt->len;
1513
1514 switch (opt->len) {
1515 case 1:
1516 *val = *((u8 *) opt->val);
1517 break;
1518
1519 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001520 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 break;
1522
1523 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001524 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 break;
1526
1527 default:
1528 *val = (unsigned long) opt->val;
1529 break;
1530 }
1531
1532 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1533 return len;
1534}
1535
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1537{
1538 struct l2cap_conf_opt *opt = *ptr;
1539
1540 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1541
1542 opt->type = type;
1543 opt->len = len;
1544
1545 switch (len) {
1546 case 1:
1547 *((u8 *) opt->val) = val;
1548 break;
1549
1550 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001551 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 break;
1553
1554 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001555 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 break;
1557
1558 default:
1559 memcpy(opt->val, (void *) val, len);
1560 break;
1561 }
1562
1563 *ptr += L2CAP_CONF_OPT_SIZE + len;
1564}
1565
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001566static void l2cap_ack_timeout(unsigned long arg)
1567{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001568 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001569
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001570 bh_lock_sock(chan->sk);
1571 l2cap_send_ack(chan);
1572 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001573}
1574
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001575static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001576{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001577 struct sock *sk = chan->sk;
1578
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001579 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001580 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001581 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001582 chan->num_acked = 0;
1583 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001584
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001585 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1586 (unsigned long) chan);
1587 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1588 (unsigned long) chan);
1589 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001590
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001591 skb_queue_head_init(&chan->srej_q);
1592 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001593
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001594 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001595
1596 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001597}
1598
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001599static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1600{
1601 switch (mode) {
1602 case L2CAP_MODE_STREAMING:
1603 case L2CAP_MODE_ERTM:
1604 if (l2cap_mode_supported(mode, remote_feat_mask))
1605 return mode;
1606 /* fall through */
1607 default:
1608 return L2CAP_MODE_BASIC;
1609 }
1610}
1611
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001612static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001614 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 struct l2cap_pinfo *pi = l2cap_pi(sk);
1616 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001617 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618 void *ptr = req->data;
1619
1620 BT_DBG("sk %p", sk);
1621
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001622 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001623 goto done;
1624
1625 switch (pi->mode) {
1626 case L2CAP_MODE_STREAMING:
1627 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001628 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001629 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001630
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001631 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001632 default:
1633 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1634 break;
1635 }
1636
1637done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001638 if (pi->imtu != L2CAP_DEFAULT_MTU)
1639 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1640
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001641 switch (pi->mode) {
1642 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001643 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1644 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1645 break;
1646
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001647 rfc.mode = L2CAP_MODE_BASIC;
1648 rfc.txwin_size = 0;
1649 rfc.max_transmit = 0;
1650 rfc.retrans_timeout = 0;
1651 rfc.monitor_timeout = 0;
1652 rfc.max_pdu_size = 0;
1653
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001654 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1655 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001656 break;
1657
1658 case L2CAP_MODE_ERTM:
1659 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001660 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001661 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001662 rfc.retrans_timeout = 0;
1663 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001664 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001665 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001666 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001667
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001668 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1669 (unsigned long) &rfc);
1670
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001671 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1672 break;
1673
1674 if (pi->fcs == L2CAP_FCS_NONE ||
1675 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1676 pi->fcs = L2CAP_FCS_NONE;
1677 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1678 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001679 break;
1680
1681 case L2CAP_MODE_STREAMING:
1682 rfc.mode = L2CAP_MODE_STREAMING;
1683 rfc.txwin_size = 0;
1684 rfc.max_transmit = 0;
1685 rfc.retrans_timeout = 0;
1686 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001687 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001688 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001689 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001690
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001691 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1692 (unsigned long) &rfc);
1693
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001694 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1695 break;
1696
1697 if (pi->fcs == L2CAP_FCS_NONE ||
1698 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1699 pi->fcs = L2CAP_FCS_NONE;
1700 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1701 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001702 break;
1703 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001705 req->dcid = cpu_to_le16(pi->dcid);
1706 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707
1708 return ptr - data;
1709}
1710
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001711static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001713 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001714 struct l2cap_conf_rsp *rsp = data;
1715 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001716 void *req = chan->conf_req;
1717 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001718 int type, hint, olen;
1719 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001720 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001721 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001722 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001724 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001725
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001726 while (len >= L2CAP_CONF_OPT_SIZE) {
1727 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001729 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001730 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001731
1732 switch (type) {
1733 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001734 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001735 break;
1736
1737 case L2CAP_CONF_FLUSH_TO:
1738 pi->flush_to = val;
1739 break;
1740
1741 case L2CAP_CONF_QOS:
1742 break;
1743
Marcel Holtmann6464f352007-10-20 13:39:51 +02001744 case L2CAP_CONF_RFC:
1745 if (olen == sizeof(rfc))
1746 memcpy(&rfc, (void *) val, olen);
1747 break;
1748
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001749 case L2CAP_CONF_FCS:
1750 if (val == L2CAP_FCS_NONE)
1751 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1752
1753 break;
1754
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001755 default:
1756 if (hint)
1757 break;
1758
1759 result = L2CAP_CONF_UNKNOWN;
1760 *((u8 *) ptr++) = type;
1761 break;
1762 }
1763 }
1764
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001765 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001766 goto done;
1767
1768 switch (pi->mode) {
1769 case L2CAP_MODE_STREAMING:
1770 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001771 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1772 pi->mode = l2cap_select_mode(rfc.mode,
1773 pi->conn->feat_mask);
1774 break;
1775 }
1776
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001777 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001778 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001779
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001780 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001781 }
1782
1783done:
1784 if (pi->mode != rfc.mode) {
1785 result = L2CAP_CONF_UNACCEPT;
1786 rfc.mode = pi->mode;
1787
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001788 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001789 return -ECONNREFUSED;
1790
1791 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1792 sizeof(rfc), (unsigned long) &rfc);
1793 }
1794
1795
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001796 if (result == L2CAP_CONF_SUCCESS) {
1797 /* Configure output options and let the other side know
1798 * which ones we don't like. */
1799
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001800 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1801 result = L2CAP_CONF_UNACCEPT;
1802 else {
1803 pi->omtu = mtu;
1804 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1805 }
1806 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001807
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001808 switch (rfc.mode) {
1809 case L2CAP_MODE_BASIC:
1810 pi->fcs = L2CAP_FCS_NONE;
1811 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1812 break;
1813
1814 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001815 chan->remote_tx_win = rfc.txwin_size;
1816 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001817
1818 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1819 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001820
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001821 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001822
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001823 rfc.retrans_timeout =
1824 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1825 rfc.monitor_timeout =
1826 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001827
1828 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001829
1830 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1831 sizeof(rfc), (unsigned long) &rfc);
1832
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001833 break;
1834
1835 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001836 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1837 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001838
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001839 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001840
1841 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001842
1843 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1844 sizeof(rfc), (unsigned long) &rfc);
1845
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001846 break;
1847
1848 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001849 result = L2CAP_CONF_UNACCEPT;
1850
1851 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001852 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001853 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001854
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001855 if (result == L2CAP_CONF_SUCCESS)
1856 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1857 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001858 rsp->scid = cpu_to_le16(pi->dcid);
1859 rsp->result = cpu_to_le16(result);
1860 rsp->flags = cpu_to_le16(0x0000);
1861
1862 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863}
1864
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001865static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1866{
1867 struct l2cap_pinfo *pi = l2cap_pi(sk);
1868 struct l2cap_conf_req *req = data;
1869 void *ptr = req->data;
1870 int type, olen;
1871 unsigned long val;
1872 struct l2cap_conf_rfc rfc;
1873
1874 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1875
1876 while (len >= L2CAP_CONF_OPT_SIZE) {
1877 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1878
1879 switch (type) {
1880 case L2CAP_CONF_MTU:
1881 if (val < L2CAP_DEFAULT_MIN_MTU) {
1882 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001883 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001884 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001885 pi->imtu = val;
1886 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001887 break;
1888
1889 case L2CAP_CONF_FLUSH_TO:
1890 pi->flush_to = val;
1891 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1892 2, pi->flush_to);
1893 break;
1894
1895 case L2CAP_CONF_RFC:
1896 if (olen == sizeof(rfc))
1897 memcpy(&rfc, (void *)val, olen);
1898
1899 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1900 rfc.mode != pi->mode)
1901 return -ECONNREFUSED;
1902
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001903 pi->fcs = 0;
1904
1905 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1906 sizeof(rfc), (unsigned long) &rfc);
1907 break;
1908 }
1909 }
1910
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001911 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1912 return -ECONNREFUSED;
1913
1914 pi->mode = rfc.mode;
1915
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001916 if (*result == L2CAP_CONF_SUCCESS) {
1917 switch (rfc.mode) {
1918 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001919 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1920 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001921 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001922 break;
1923 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001924 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001925 }
1926 }
1927
1928 req->dcid = cpu_to_le16(pi->dcid);
1929 req->flags = cpu_to_le16(0x0000);
1930
1931 return ptr - data;
1932}
1933
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001934static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935{
1936 struct l2cap_conf_rsp *rsp = data;
1937 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001939 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001941 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001942 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001943 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944
1945 return ptr - data;
1946}
1947
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001948void __l2cap_connect_rsp_defer(struct sock *sk)
1949{
1950 struct l2cap_conn_rsp rsp;
1951 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1952 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
1953 u8 buf[128];
1954
1955 sk->sk_state = BT_CONFIG;
1956
1957 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1958 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1959 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1960 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1961 l2cap_send_cmd(conn, chan->ident,
1962 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1963
1964 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
1965 return;
1966
1967 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
1968 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1969 l2cap_build_conf_req(chan, buf), buf);
1970 chan->num_conf_req++;
1971}
1972
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001973static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1974{
1975 struct l2cap_pinfo *pi = l2cap_pi(sk);
1976 int type, olen;
1977 unsigned long val;
1978 struct l2cap_conf_rfc rfc;
1979
1980 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1981
1982 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1983 return;
1984
1985 while (len >= L2CAP_CONF_OPT_SIZE) {
1986 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1987
1988 switch (type) {
1989 case L2CAP_CONF_RFC:
1990 if (olen == sizeof(rfc))
1991 memcpy(&rfc, (void *)val, olen);
1992 goto done;
1993 }
1994 }
1995
1996done:
1997 switch (rfc.mode) {
1998 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001999 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2000 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002001 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2002 break;
2003 case L2CAP_MODE_STREAMING:
2004 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2005 }
2006}
2007
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002008static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2009{
2010 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2011
2012 if (rej->reason != 0x0000)
2013 return 0;
2014
2015 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2016 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002017 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002018
2019 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002020 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002021
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002022 l2cap_conn_start(conn);
2023 }
2024
2025 return 0;
2026}
2027
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2029{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2031 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002032 struct l2cap_chan *chan = NULL;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002033 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002034 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035
2036 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002037 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038
2039 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2040
2041 /* Check if we have socket listening on psm */
2042 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2043 if (!parent) {
2044 result = L2CAP_CR_BAD_PSM;
2045 goto sendresp;
2046 }
2047
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002048 bh_lock_sock(parent);
2049
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002050 /* Check if the ACL is secure enough (if not SDP) */
2051 if (psm != cpu_to_le16(0x0001) &&
2052 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002053 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002054 result = L2CAP_CR_SEC_BLOCK;
2055 goto response;
2056 }
2057
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058 result = L2CAP_CR_NO_MEM;
2059
2060 /* Check for backlog size */
2061 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002062 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 goto response;
2064 }
2065
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002066 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 if (!sk)
2068 goto response;
2069
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002070 chan = l2cap_chan_alloc(sk);
2071 if (!chan) {
2072 l2cap_sock_kill(sk);
2073 goto response;
2074 }
2075
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002076 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077
2078 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002079 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2080 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 sock_set_flag(sk, SOCK_ZAPPED);
2082 l2cap_sock_kill(sk);
2083 goto response;
2084 }
2085
2086 hci_conn_hold(conn->hcon);
2087
2088 l2cap_sock_init(sk, parent);
2089 bacpy(&bt_sk(sk)->src, conn->src);
2090 bacpy(&bt_sk(sk)->dst, conn->dst);
2091 l2cap_pi(sk)->psm = psm;
2092 l2cap_pi(sk)->dcid = scid;
2093
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002094 bt_accept_enqueue(parent, sk);
2095
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002096 __l2cap_chan_add(conn, chan);
2097
2098 l2cap_pi(sk)->chan = chan;
2099
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 dcid = l2cap_pi(sk)->scid;
2101
2102 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2103
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002104 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105
Marcel Holtmann984947d2009-02-06 23:35:19 +01002106 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002107 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002108 if (bt_sk(sk)->defer_setup) {
2109 sk->sk_state = BT_CONNECT2;
2110 result = L2CAP_CR_PEND;
2111 status = L2CAP_CS_AUTHOR_PEND;
2112 parent->sk_data_ready(parent, 0);
2113 } else {
2114 sk->sk_state = BT_CONFIG;
2115 result = L2CAP_CR_SUCCESS;
2116 status = L2CAP_CS_NO_INFO;
2117 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002118 } else {
2119 sk->sk_state = BT_CONNECT2;
2120 result = L2CAP_CR_PEND;
2121 status = L2CAP_CS_AUTHEN_PEND;
2122 }
2123 } else {
2124 sk->sk_state = BT_CONNECT2;
2125 result = L2CAP_CR_PEND;
2126 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 }
2128
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002129 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130
2131response:
2132 bh_unlock_sock(parent);
2133
2134sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002135 rsp.scid = cpu_to_le16(scid);
2136 rsp.dcid = cpu_to_le16(dcid);
2137 rsp.result = cpu_to_le16(result);
2138 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002140
2141 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2142 struct l2cap_info_req info;
2143 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2144
2145 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2146 conn->info_ident = l2cap_get_ident(conn);
2147
2148 mod_timer(&conn->info_timer, jiffies +
2149 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2150
2151 l2cap_send_cmd(conn, conn->info_ident,
2152 L2CAP_INFO_REQ, sizeof(info), &info);
2153 }
2154
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002155 if (chan && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002156 result == L2CAP_CR_SUCCESS) {
2157 u8 buf[128];
2158 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2159 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002160 l2cap_build_conf_req(chan, buf), buf);
2161 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002162 }
2163
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 return 0;
2165}
2166
2167static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2168{
2169 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2170 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002171 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 struct sock *sk;
2173 u8 req[128];
2174
2175 scid = __le16_to_cpu(rsp->scid);
2176 dcid = __le16_to_cpu(rsp->dcid);
2177 result = __le16_to_cpu(rsp->result);
2178 status = __le16_to_cpu(rsp->status);
2179
2180 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2181
2182 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002183 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002184 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002185 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002187 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002188 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002189 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 }
2191
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002192 sk = chan->sk;
2193
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 switch (result) {
2195 case L2CAP_CR_SUCCESS:
2196 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002197 chan->ident = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002199 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2200
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002201 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2202 break;
2203
2204 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2205
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002207 l2cap_build_conf_req(chan, req), req);
2208 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 break;
2210
2211 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002212 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 break;
2214
2215 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002216 /* don't delete l2cap channel if sk is owned by user */
2217 if (sock_owned_by_user(sk)) {
2218 sk->sk_state = BT_DISCONN;
2219 l2cap_sock_clear_timer(sk);
2220 l2cap_sock_set_timer(sk, HZ / 5);
2221 break;
2222 }
2223
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002224 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 break;
2226 }
2227
2228 bh_unlock_sock(sk);
2229 return 0;
2230}
2231
Mat Martineau8c462b62010-08-24 15:35:42 -07002232static inline void set_default_fcs(struct l2cap_pinfo *pi)
2233{
2234 /* FCS is enabled only in ERTM or streaming mode, if one or both
2235 * sides request it.
2236 */
2237 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2238 pi->fcs = L2CAP_FCS_NONE;
2239 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2240 pi->fcs = L2CAP_FCS_CRC16;
2241}
2242
Al Viro88219a02007-07-29 00:17:25 -07002243static 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 -07002244{
2245 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2246 u16 dcid, flags;
2247 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002248 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002250 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251
2252 dcid = __le16_to_cpu(req->dcid);
2253 flags = __le16_to_cpu(req->flags);
2254
2255 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2256
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002257 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002258 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259 return -ENOENT;
2260
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002261 sk = chan->sk;
2262
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002263 if (sk->sk_state != BT_CONFIG) {
2264 struct l2cap_cmd_rej rej;
2265
2266 rej.reason = cpu_to_le16(0x0002);
2267 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2268 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002269 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002270 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002271
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002272 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002273 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002274 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002275 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2276 l2cap_build_conf_rsp(sk, rsp,
2277 L2CAP_CONF_REJECT, flags), rsp);
2278 goto unlock;
2279 }
2280
2281 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002282 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2283 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284
2285 if (flags & 0x0001) {
2286 /* Incomplete config. Send empty response. */
2287 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002288 l2cap_build_conf_rsp(sk, rsp,
2289 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290 goto unlock;
2291 }
2292
2293 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002294 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002295 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002296 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002298 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002300 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002301 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002302
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002303 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002304 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002305
Marcel Holtmann876d9482007-10-20 13:35:42 +02002306 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2307 goto unlock;
2308
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002310 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002311
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002313
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002314 chan->next_tx_seq = 0;
2315 chan->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002316 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002317 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002318 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002319
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002321 goto unlock;
2322 }
2323
2324 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002325 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002326 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002328 l2cap_build_conf_req(chan, buf), buf);
2329 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330 }
2331
2332unlock:
2333 bh_unlock_sock(sk);
2334 return 0;
2335}
2336
2337static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2338{
2339 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2340 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002341 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002343 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344
2345 scid = __le16_to_cpu(rsp->scid);
2346 flags = __le16_to_cpu(rsp->flags);
2347 result = __le16_to_cpu(rsp->result);
2348
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002349 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2350 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002352 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002353 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 return 0;
2355
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002356 sk = chan->sk;
2357
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 switch (result) {
2359 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002360 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 break;
2362
2363 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002364 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002365 char req[64];
2366
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002367 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002368 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002369 goto done;
2370 }
2371
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002372 /* throw out any old stored conf requests */
2373 result = L2CAP_CONF_SUCCESS;
2374 len = l2cap_parse_conf_rsp(sk, rsp->data,
2375 len, req, &result);
2376 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002377 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002378 goto done;
2379 }
2380
2381 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2382 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002383 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002384 if (result != L2CAP_CONF_SUCCESS)
2385 goto done;
2386 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 }
2388
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002389 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002390 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002392 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393 goto done;
2394 }
2395
2396 if (flags & 0x01)
2397 goto done;
2398
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2400
2401 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002402 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002403
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002405 chan->next_tx_seq = 0;
2406 chan->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002407 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002408 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002409 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002410
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 l2cap_chan_ready(sk);
2412 }
2413
2414done:
2415 bh_unlock_sock(sk);
2416 return 0;
2417}
2418
2419static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2420{
2421 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2422 struct l2cap_disconn_rsp rsp;
2423 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002424 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425 struct sock *sk;
2426
2427 scid = __le16_to_cpu(req->scid);
2428 dcid = __le16_to_cpu(req->dcid);
2429
2430 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2431
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002432 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002433 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434 return 0;
2435
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002436 sk = chan->sk;
2437
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002438 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2439 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2441
2442 sk->sk_shutdown = SHUTDOWN_MASK;
2443
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002444 /* don't delete l2cap channel if sk is owned by user */
2445 if (sock_owned_by_user(sk)) {
2446 sk->sk_state = BT_DISCONN;
2447 l2cap_sock_clear_timer(sk);
2448 l2cap_sock_set_timer(sk, HZ / 5);
2449 bh_unlock_sock(sk);
2450 return 0;
2451 }
2452
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002453 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 bh_unlock_sock(sk);
2455
2456 l2cap_sock_kill(sk);
2457 return 0;
2458}
2459
2460static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2461{
2462 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2463 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002464 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465 struct sock *sk;
2466
2467 scid = __le16_to_cpu(rsp->scid);
2468 dcid = __le16_to_cpu(rsp->dcid);
2469
2470 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2471
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002472 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002473 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 return 0;
2475
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002476 sk = chan->sk;
2477
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002478 /* don't delete l2cap channel if sk is owned by user */
2479 if (sock_owned_by_user(sk)) {
2480 sk->sk_state = BT_DISCONN;
2481 l2cap_sock_clear_timer(sk);
2482 l2cap_sock_set_timer(sk, HZ / 5);
2483 bh_unlock_sock(sk);
2484 return 0;
2485 }
2486
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002487 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 bh_unlock_sock(sk);
2489
2490 l2cap_sock_kill(sk);
2491 return 0;
2492}
2493
2494static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2495{
2496 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 u16 type;
2498
2499 type = __le16_to_cpu(req->type);
2500
2501 BT_DBG("type 0x%4.4x", type);
2502
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002503 if (type == L2CAP_IT_FEAT_MASK) {
2504 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002505 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002506 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2507 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2508 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002509 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002510 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2511 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002512 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002513 l2cap_send_cmd(conn, cmd->ident,
2514 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002515 } else if (type == L2CAP_IT_FIXED_CHAN) {
2516 u8 buf[12];
2517 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2518 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2519 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2520 memcpy(buf + 4, l2cap_fixed_chan, 8);
2521 l2cap_send_cmd(conn, cmd->ident,
2522 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002523 } else {
2524 struct l2cap_info_rsp rsp;
2525 rsp.type = cpu_to_le16(type);
2526 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2527 l2cap_send_cmd(conn, cmd->ident,
2528 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2529 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530
2531 return 0;
2532}
2533
2534static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2535{
2536 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2537 u16 type, result;
2538
2539 type = __le16_to_cpu(rsp->type);
2540 result = __le16_to_cpu(rsp->result);
2541
2542 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2543
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002544 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2545 if (cmd->ident != conn->info_ident ||
2546 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2547 return 0;
2548
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002549 del_timer(&conn->info_timer);
2550
Ville Tervoadb08ed2010-08-04 09:43:33 +03002551 if (result != L2CAP_IR_SUCCESS) {
2552 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2553 conn->info_ident = 0;
2554
2555 l2cap_conn_start(conn);
2556
2557 return 0;
2558 }
2559
Marcel Holtmann984947d2009-02-06 23:35:19 +01002560 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002561 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002562
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002563 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002564 struct l2cap_info_req req;
2565 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2566
2567 conn->info_ident = l2cap_get_ident(conn);
2568
2569 l2cap_send_cmd(conn, conn->info_ident,
2570 L2CAP_INFO_REQ, sizeof(req), &req);
2571 } else {
2572 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2573 conn->info_ident = 0;
2574
2575 l2cap_conn_start(conn);
2576 }
2577 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002578 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002579 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002580
2581 l2cap_conn_start(conn);
2582 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002583
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584 return 0;
2585}
2586
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002587static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002588 u16 to_multiplier)
2589{
2590 u16 max_latency;
2591
2592 if (min > max || min < 6 || max > 3200)
2593 return -EINVAL;
2594
2595 if (to_multiplier < 10 || to_multiplier > 3200)
2596 return -EINVAL;
2597
2598 if (max >= to_multiplier * 8)
2599 return -EINVAL;
2600
2601 max_latency = (to_multiplier * 8 / max) - 1;
2602 if (latency > 499 || latency > max_latency)
2603 return -EINVAL;
2604
2605 return 0;
2606}
2607
2608static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2609 struct l2cap_cmd_hdr *cmd, u8 *data)
2610{
2611 struct hci_conn *hcon = conn->hcon;
2612 struct l2cap_conn_param_update_req *req;
2613 struct l2cap_conn_param_update_rsp rsp;
2614 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002615 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002616
2617 if (!(hcon->link_mode & HCI_LM_MASTER))
2618 return -EINVAL;
2619
2620 cmd_len = __le16_to_cpu(cmd->len);
2621 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2622 return -EPROTO;
2623
2624 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002625 min = __le16_to_cpu(req->min);
2626 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002627 latency = __le16_to_cpu(req->latency);
2628 to_multiplier = __le16_to_cpu(req->to_multiplier);
2629
2630 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2631 min, max, latency, to_multiplier);
2632
2633 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002634
2635 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2636 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002637 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2638 else
2639 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2640
2641 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2642 sizeof(rsp), &rsp);
2643
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002644 if (!err)
2645 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2646
Claudio Takahaside731152011-02-11 19:28:55 -02002647 return 0;
2648}
2649
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002650static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2651 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2652{
2653 int err = 0;
2654
2655 switch (cmd->code) {
2656 case L2CAP_COMMAND_REJ:
2657 l2cap_command_rej(conn, cmd, data);
2658 break;
2659
2660 case L2CAP_CONN_REQ:
2661 err = l2cap_connect_req(conn, cmd, data);
2662 break;
2663
2664 case L2CAP_CONN_RSP:
2665 err = l2cap_connect_rsp(conn, cmd, data);
2666 break;
2667
2668 case L2CAP_CONF_REQ:
2669 err = l2cap_config_req(conn, cmd, cmd_len, data);
2670 break;
2671
2672 case L2CAP_CONF_RSP:
2673 err = l2cap_config_rsp(conn, cmd, data);
2674 break;
2675
2676 case L2CAP_DISCONN_REQ:
2677 err = l2cap_disconnect_req(conn, cmd, data);
2678 break;
2679
2680 case L2CAP_DISCONN_RSP:
2681 err = l2cap_disconnect_rsp(conn, cmd, data);
2682 break;
2683
2684 case L2CAP_ECHO_REQ:
2685 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2686 break;
2687
2688 case L2CAP_ECHO_RSP:
2689 break;
2690
2691 case L2CAP_INFO_REQ:
2692 err = l2cap_information_req(conn, cmd, data);
2693 break;
2694
2695 case L2CAP_INFO_RSP:
2696 err = l2cap_information_rsp(conn, cmd, data);
2697 break;
2698
2699 default:
2700 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2701 err = -EINVAL;
2702 break;
2703 }
2704
2705 return err;
2706}
2707
2708static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2709 struct l2cap_cmd_hdr *cmd, u8 *data)
2710{
2711 switch (cmd->code) {
2712 case L2CAP_COMMAND_REJ:
2713 return 0;
2714
2715 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002716 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002717
2718 case L2CAP_CONN_PARAM_UPDATE_RSP:
2719 return 0;
2720
2721 default:
2722 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2723 return -EINVAL;
2724 }
2725}
2726
2727static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2728 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729{
2730 u8 *data = skb->data;
2731 int len = skb->len;
2732 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002733 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734
2735 l2cap_raw_recv(conn, skb);
2736
2737 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002738 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2740 data += L2CAP_CMD_HDR_SIZE;
2741 len -= L2CAP_CMD_HDR_SIZE;
2742
Al Viro88219a02007-07-29 00:17:25 -07002743 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744
Al Viro88219a02007-07-29 00:17:25 -07002745 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 -07002746
Al Viro88219a02007-07-29 00:17:25 -07002747 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 BT_DBG("corrupted command");
2749 break;
2750 }
2751
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002752 if (conn->hcon->type == LE_LINK)
2753 err = l2cap_le_sig_cmd(conn, &cmd, data);
2754 else
2755 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756
2757 if (err) {
2758 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002759
2760 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761
2762 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002763 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2765 }
2766
Al Viro88219a02007-07-29 00:17:25 -07002767 data += cmd_len;
2768 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 }
2770
2771 kfree_skb(skb);
2772}
2773
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002774static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2775{
2776 u16 our_fcs, rcv_fcs;
2777 int hdr_size = L2CAP_HDR_SIZE + 2;
2778
2779 if (pi->fcs == L2CAP_FCS_CRC16) {
2780 skb_trim(skb, skb->len - 2);
2781 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2782 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2783
2784 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002785 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002786 }
2787 return 0;
2788}
2789
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002790static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002791{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002792 u16 control = 0;
2793
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002794 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002795
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002796 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002797
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002798 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002799 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002800 l2cap_send_sframe(chan, control);
2801 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002802 }
2803
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002804 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2805 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002806
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002807 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002808
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002809 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002810 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002811 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002812 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002813 }
2814}
2815
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002816static 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 -03002817{
2818 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002819 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002820
2821 bt_cb(skb)->tx_seq = tx_seq;
2822 bt_cb(skb)->sar = sar;
2823
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002824 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002825 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002826 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002827 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002828 }
2829
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002830 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002831 if (tx_seq_offset < 0)
2832 tx_seq_offset += 64;
2833
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002834 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002835 if (bt_cb(next_skb)->tx_seq == tx_seq)
2836 return -EINVAL;
2837
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002838 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002839 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002840 if (next_tx_seq_offset < 0)
2841 next_tx_seq_offset += 64;
2842
2843 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002844 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002845 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002846 }
2847
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002848 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002849 break;
2850
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002851 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002852
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002853 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002854
2855 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002856}
2857
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002858static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002859{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002860 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002861 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002862 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002863
2864 switch (control & L2CAP_CTRL_SAR) {
2865 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002866 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002867 goto drop;
2868
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002869 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002870 if (!err)
2871 return err;
2872
2873 break;
2874
2875 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002876 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002877 goto drop;
2878
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002879 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002880
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002881 if (chan->sdu_len > pi->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002882 goto disconnect;
2883
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002884 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
2885 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002886 return -ENOMEM;
2887
2888 /* pull sdu_len bytes only after alloc, because of Local Busy
2889 * condition we have to be sure that this will be executed
2890 * only once, i.e., when alloc does not fail */
2891 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002892
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002893 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002894
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002895 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002896 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002897 break;
2898
2899 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002900 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002901 goto disconnect;
2902
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002903 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002904 goto disconnect;
2905
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002906 chan->partial_sdu_len += skb->len;
2907 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002908 goto drop;
2909
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002910 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002911
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002912 break;
2913
2914 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002915 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002916 goto disconnect;
2917
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002918 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002919 goto disconnect;
2920
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002921 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002922 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002923
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002924 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002925 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002926
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002927 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002928 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002929
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002930 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002931 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002932
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002933 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002934 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002935 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002936 return -ENOMEM;
2937 }
2938
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002939 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002940 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002941 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002942 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002943 return err;
2944 }
2945
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002946 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2947 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002948
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002949 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002950 break;
2951 }
2952
2953 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002954 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002955
2956drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002957 kfree_skb(chan->sdu);
2958 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002959
2960disconnect:
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002961 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002962 kfree_skb(skb);
2963 return 0;
2964}
2965
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002966static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002967{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002968 struct sock *sk = chan->sk;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002969 struct sk_buff *skb;
2970 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002971 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002972
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002973 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002974 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002975 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002976 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002977 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002978 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002979 }
2980
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002981 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002982 }
2983
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002984 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002985 goto done;
2986
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002987 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002988 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002989 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002990 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002991
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002992 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002993 __mod_monitor_timer();
2994
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002995 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002996
2997done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002998 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2999 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003000
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003001 BT_DBG("sk %p, Exit local busy", sk);
3002
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003003 return 0;
3004}
3005
3006static void l2cap_busy_work(struct work_struct *work)
3007{
3008 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003009 struct l2cap_chan *chan =
3010 container_of(work, struct l2cap_chan, busy_work);
3011 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003012 int n_tries = 0, timeo = HZ/5, err;
3013 struct sk_buff *skb;
3014
3015 lock_sock(sk);
3016
3017 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003018 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003019 set_current_state(TASK_INTERRUPTIBLE);
3020
3021 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3022 err = -EBUSY;
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003023 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003024 break;
3025 }
3026
3027 if (!timeo)
3028 timeo = HZ/5;
3029
3030 if (signal_pending(current)) {
3031 err = sock_intr_errno(timeo);
3032 break;
3033 }
3034
3035 release_sock(sk);
3036 timeo = schedule_timeout(timeo);
3037 lock_sock(sk);
3038
3039 err = sock_error(sk);
3040 if (err)
3041 break;
3042
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003043 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003044 break;
3045 }
3046
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003047 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003048 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003049
3050 release_sock(sk);
3051}
3052
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003053static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003054{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003055 int sctrl, err;
3056
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003057 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003058 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003059 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003060 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003061
3062
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003063 }
3064
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003065 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003066 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003067 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003068 return err;
3069 }
3070
3071 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003072 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003073
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003074 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003075 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003076 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003077
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003078 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003079 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003080 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003081
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003082 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003083
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003084 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003085
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003086 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003087
3088 return err;
3089}
3090
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003091static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003092{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003093 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003094 struct sk_buff *_skb;
3095 int err = -EINVAL;
3096
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003097 /*
3098 * TODO: We have to notify the userland if some data is lost with the
3099 * Streaming Mode.
3100 */
3101
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003102 switch (control & L2CAP_CTRL_SAR) {
3103 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003104 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003105 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003106 break;
3107 }
3108
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003109 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003110 if (!err)
3111 return 0;
3112
3113 break;
3114
3115 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003116 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003117 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003118 break;
3119 }
3120
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003121 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003122 skb_pull(skb, 2);
3123
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003124 if (chan->sdu_len > pi->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003125 err = -EMSGSIZE;
3126 break;
3127 }
3128
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003129 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3130 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003131 err = -ENOMEM;
3132 break;
3133 }
3134
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003135 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003136
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003137 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003138 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003139 err = 0;
3140 break;
3141
3142 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003143 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003144 break;
3145
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003146 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003147
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003148 chan->partial_sdu_len += skb->len;
3149 if (chan->partial_sdu_len > chan->sdu_len)
3150 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003151 else
3152 err = 0;
3153
3154 break;
3155
3156 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003157 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003158 break;
3159
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003160 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003161
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003162 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003163 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003164
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003165 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003166 goto drop;
3167
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003168 if (chan->partial_sdu_len == chan->sdu_len) {
3169 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003170 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003171 if (err < 0)
3172 kfree_skb(_skb);
3173 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003174 err = 0;
3175
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003176drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003177 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003178 break;
3179 }
3180
3181 kfree_skb(skb);
3182 return err;
3183}
3184
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003185static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003186{
3187 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003188 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003189
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003190 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003191 if (bt_cb(skb)->tx_seq != tx_seq)
3192 break;
3193
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003194 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003195 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003196 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003197 chan->buffer_seq_srej =
3198 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003199 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003200 }
3201}
3202
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003203static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003204{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003205 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003206 struct srej_list *l, *tmp;
3207 u16 control;
3208
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003209 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003210 if (l->tx_seq == tx_seq) {
3211 list_del(&l->list);
3212 kfree(l);
3213 return;
3214 }
3215 control = L2CAP_SUPER_SELECT_REJECT;
3216 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003217 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003218 list_del(&l->list);
3219 list_add_tail(&l->list, SREJ_LIST(sk));
3220 }
3221}
3222
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003223static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003224{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003225 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003226 struct srej_list *new;
3227 u16 control;
3228
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003229 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003230 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003231 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003232 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003233
3234 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003235 new->tx_seq = chan->expected_tx_seq;
3236 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003237 list_add_tail(&new->list, SREJ_LIST(sk));
3238 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003239 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003240}
3241
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003242static 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 -03003243{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003244 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003245 struct l2cap_pinfo *pi = l2cap_pi(sk);
3246 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003247 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003248 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003249 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003250 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003251 int err = 0;
3252
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003253 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3254 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003255
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003256 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003257 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003258 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003259 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003260 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003261 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003262 }
3263
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003264 chan->expected_ack_seq = req_seq;
3265 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003266
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003267 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003268 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003269
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003270 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003271 if (tx_seq_offset < 0)
3272 tx_seq_offset += 64;
3273
3274 /* invalid tx_seq */
3275 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003276 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003277 goto drop;
3278 }
3279
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003280 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003281 goto drop;
3282
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003283 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003284 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003285
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003286 first = list_first_entry(SREJ_LIST(sk),
3287 struct srej_list, list);
3288 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003289 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003290 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003291
3292 list_del(&first->list);
3293 kfree(first);
3294
3295 if (list_empty(SREJ_LIST(sk))) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003296 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003297 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3298 l2cap_send_ack(chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003299 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003300 }
3301 } else {
3302 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003303
3304 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003305 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003306 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003307
3308 list_for_each_entry(l, SREJ_LIST(sk), list) {
3309 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003310 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003311 return 0;
3312 }
3313 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003314 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003315 }
3316 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003317 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003318 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003319 if (expected_tx_seq_offset < 0)
3320 expected_tx_seq_offset += 64;
3321
3322 /* duplicated tx_seq */
3323 if (tx_seq_offset < expected_tx_seq_offset)
3324 goto drop;
3325
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003326 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003327
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003328 BT_DBG("sk %p, Enter SREJ", sk);
3329
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003330 INIT_LIST_HEAD(SREJ_LIST(sk));
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003331 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003332
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003333 __skb_queue_head_init(&chan->srej_q);
3334 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003335 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003336
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003337 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003338
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003339 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003340
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003341 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003342 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003343 return 0;
3344
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003345expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003346 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003347
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003348 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003349 bt_cb(skb)->tx_seq = tx_seq;
3350 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003351 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003352 return 0;
3353 }
3354
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003355 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003356 if (err < 0)
3357 return 0;
3358
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003359 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003360 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3361 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003362 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003363 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003364 }
3365
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003366 __mod_ack_timer();
3367
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003368 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3369 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003370 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003371
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003372 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003373
3374drop:
3375 kfree_skb(skb);
3376 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003377}
3378
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003379static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003380{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003381 struct sock *sk = chan->sk;
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003382
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003383 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3384 rx_control);
3385
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003386 chan->expected_ack_seq = __get_reqseq(rx_control);
3387 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003388
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003389 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003390 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3391 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3392 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003393 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003394 __mod_retrans_timer();
3395
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003396 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3397 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003398 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003399 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003400 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003401
3402 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003403 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003404
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003405 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3406 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003407 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003408 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003409
3410 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003411 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003412 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003413 __mod_retrans_timer();
3414
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003415 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3416 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3417 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003418 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003419 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003420 }
3421}
3422
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003423static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003424{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003425 u8 tx_seq = __get_reqseq(rx_control);
3426
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003427 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003428
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003429 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003430
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003431 chan->expected_ack_seq = tx_seq;
3432 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003433
3434 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003435 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3436 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003437 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003438 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003439 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003440 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003441
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003442 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3443 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003444 }
3445}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003446static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003447{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003448 u8 tx_seq = __get_reqseq(rx_control);
3449
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003450 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003451
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003452 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003453
3454 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003455 chan->expected_ack_seq = tx_seq;
3456 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003457
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003458 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3459 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003460
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003461 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003462
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003463 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003464 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003465 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003466 }
3467 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003468 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003469 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003470 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003471 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003472 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003473 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003474 l2cap_retransmit_one_frame(chan, tx_seq);
3475 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003476 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003477 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003478 }
3479 }
3480}
3481
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003482static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003483{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003484 u8 tx_seq = __get_reqseq(rx_control);
3485
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003486 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003487
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003488 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003489 chan->expected_ack_seq = tx_seq;
3490 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003491
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003492 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003493 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003494
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003495 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003496 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003497 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003498 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003499 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003500 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003501
3502 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003503 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003504 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003505 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003506}
3507
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003508static 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 -03003509{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003510 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003511
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003512 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003513 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003514 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003515 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003516 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003517 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003518 }
3519
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003520 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3521 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003522 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003523 break;
3524
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003525 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003526 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003527 break;
3528
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003529 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003530 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003531 break;
3532
3533 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003534 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003535 break;
3536 }
3537
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003538 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003539 return 0;
3540}
3541
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003542static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3543{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003544 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003545 struct l2cap_pinfo *pi = l2cap_pi(sk);
3546 u16 control;
3547 u8 req_seq;
3548 int len, next_tx_seq_offset, req_seq_offset;
3549
3550 control = get_unaligned_le16(skb->data);
3551 skb_pull(skb, 2);
3552 len = skb->len;
3553
3554 /*
3555 * We can just drop the corrupted I-frame here.
3556 * Receiver will miss it and start proper recovery
3557 * procedures and ask retransmission.
3558 */
3559 if (l2cap_check_fcs(pi, skb))
3560 goto drop;
3561
3562 if (__is_sar_start(control) && __is_iframe(control))
3563 len -= 2;
3564
3565 if (pi->fcs == L2CAP_FCS_CRC16)
3566 len -= 2;
3567
3568 if (len > pi->mps) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003569 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003570 goto drop;
3571 }
3572
3573 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003574 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003575 if (req_seq_offset < 0)
3576 req_seq_offset += 64;
3577
3578 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003579 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003580 if (next_tx_seq_offset < 0)
3581 next_tx_seq_offset += 64;
3582
3583 /* check for invalid req-seq */
3584 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003585 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003586 goto drop;
3587 }
3588
3589 if (__is_iframe(control)) {
3590 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003591 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003592 goto drop;
3593 }
3594
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003595 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003596 } else {
3597 if (len != 0) {
3598 BT_ERR("%d", len);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003599 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003600 goto drop;
3601 }
3602
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003603 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003604 }
3605
3606 return 0;
3607
3608drop:
3609 kfree_skb(skb);
3610 return 0;
3611}
3612
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3614{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003615 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003617 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003618 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003619 u8 tx_seq;
3620 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003622 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003623 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624 BT_DBG("unknown cid 0x%4.4x", cid);
3625 goto drop;
3626 }
3627
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003628 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003629 pi = l2cap_pi(sk);
3630
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631 BT_DBG("sk %p, len %d", sk, skb->len);
3632
3633 if (sk->sk_state != BT_CONNECTED)
3634 goto drop;
3635
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003636 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003637 case L2CAP_MODE_BASIC:
3638 /* If socket recv buffers overflows we drop data here
3639 * which is *bad* because L2CAP has to be reliable.
3640 * But we don't have any other choice. L2CAP doesn't
3641 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003643 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003644 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003646 if (!sock_queue_rcv_skb(sk, skb))
3647 goto done;
3648 break;
3649
3650 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003651 if (!sock_owned_by_user(sk)) {
3652 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003653 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003654 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003655 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003656 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003657
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003658 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003659
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003660 case L2CAP_MODE_STREAMING:
3661 control = get_unaligned_le16(skb->data);
3662 skb_pull(skb, 2);
3663 len = skb->len;
3664
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003665 if (l2cap_check_fcs(pi, skb))
3666 goto drop;
3667
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003668 if (__is_sar_start(control))
3669 len -= 2;
3670
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003671 if (pi->fcs == L2CAP_FCS_CRC16)
3672 len -= 2;
3673
Nathan Holstein51893f82010-06-09 15:46:25 -04003674 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003675 goto drop;
3676
3677 tx_seq = __get_txseq(control);
3678
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003679 if (chan->expected_tx_seq == tx_seq)
3680 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003681 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003682 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003683
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003684 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003685
3686 goto done;
3687
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003688 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003689 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003690 break;
3691 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692
3693drop:
3694 kfree_skb(skb);
3695
3696done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003697 if (sk)
3698 bh_unlock_sock(sk);
3699
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700 return 0;
3701}
3702
Al Viro8e036fc2007-07-29 00:16:36 -07003703static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704{
3705 struct sock *sk;
3706
3707 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3708 if (!sk)
3709 goto drop;
3710
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003711 bh_lock_sock(sk);
3712
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713 BT_DBG("sk %p, len %d", sk, skb->len);
3714
3715 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3716 goto drop;
3717
3718 if (l2cap_pi(sk)->imtu < skb->len)
3719 goto drop;
3720
3721 if (!sock_queue_rcv_skb(sk, skb))
3722 goto done;
3723
3724drop:
3725 kfree_skb(skb);
3726
3727done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003728 if (sk)
3729 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730 return 0;
3731}
3732
3733static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3734{
3735 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003736 u16 cid, len;
3737 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003738
3739 skb_pull(skb, L2CAP_HDR_SIZE);
3740 cid = __le16_to_cpu(lh->cid);
3741 len = __le16_to_cpu(lh->len);
3742
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003743 if (len != skb->len) {
3744 kfree_skb(skb);
3745 return;
3746 }
3747
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3749
3750 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003751 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003752 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753 l2cap_sig_channel(conn, skb);
3754 break;
3755
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003756 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003757 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758 skb_pull(skb, 2);
3759 l2cap_conless_channel(conn, psm, skb);
3760 break;
3761
3762 default:
3763 l2cap_data_channel(conn, cid, skb);
3764 break;
3765 }
3766}
3767
3768/* ---- L2CAP interface with lower layer (HCI) ---- */
3769
3770static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3771{
3772 int exact = 0, lm1 = 0, lm2 = 0;
3773 register struct sock *sk;
3774 struct hlist_node *node;
3775
3776 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003777 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778
3779 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3780
3781 /* Find listening sockets and check their link_mode */
3782 read_lock(&l2cap_sk_list.lock);
3783 sk_for_each(sk, node, &l2cap_sk_list.head) {
3784 if (sk->sk_state != BT_LISTEN)
3785 continue;
3786
3787 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003788 lm1 |= HCI_LM_ACCEPT;
3789 if (l2cap_pi(sk)->role_switch)
3790 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003792 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3793 lm2 |= HCI_LM_ACCEPT;
3794 if (l2cap_pi(sk)->role_switch)
3795 lm2 |= HCI_LM_MASTER;
3796 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797 }
3798 read_unlock(&l2cap_sk_list.lock);
3799
3800 return exact ? lm1 : lm2;
3801}
3802
3803static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3804{
Marcel Holtmann01394182006-07-03 10:02:46 +02003805 struct l2cap_conn *conn;
3806
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3808
Ville Tervoacd7d372011-02-10 22:38:49 -03003809 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003810 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003811
3812 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813 conn = l2cap_conn_add(hcon, status);
3814 if (conn)
3815 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003816 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817 l2cap_conn_del(hcon, bt_err(status));
3818
3819 return 0;
3820}
3821
Marcel Holtmann2950f212009-02-12 14:02:50 +01003822static int l2cap_disconn_ind(struct hci_conn *hcon)
3823{
3824 struct l2cap_conn *conn = hcon->l2cap_data;
3825
3826 BT_DBG("hcon %p", hcon);
3827
3828 if (hcon->type != ACL_LINK || !conn)
3829 return 0x13;
3830
3831 return conn->disc_reason;
3832}
3833
3834static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835{
3836 BT_DBG("hcon %p reason %d", hcon, reason);
3837
Ville Tervoacd7d372011-02-10 22:38:49 -03003838 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003839 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840
3841 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003842
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843 return 0;
3844}
3845
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003846static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3847{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003848 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003849 return;
3850
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003851 if (encrypt == 0x00) {
3852 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3853 l2cap_sock_clear_timer(sk);
3854 l2cap_sock_set_timer(sk, HZ * 5);
3855 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3856 __l2cap_sock_close(sk, ECONNREFUSED);
3857 } else {
3858 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3859 l2cap_sock_clear_timer(sk);
3860 }
3861}
3862
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003863static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003865 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003866 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867
Marcel Holtmann01394182006-07-03 10:02:46 +02003868 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003870
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871 BT_DBG("conn %p", conn);
3872
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003873 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003875 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003876 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003877
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878 bh_lock_sock(sk);
3879
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003880 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3881 bh_unlock_sock(sk);
3882 continue;
3883 }
3884
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003885 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003886 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003887 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003888 bh_unlock_sock(sk);
3889 continue;
3890 }
3891
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003892 if (sk->sk_state == BT_CONNECT) {
3893 if (!status) {
3894 struct l2cap_conn_req req;
3895 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3896 req.psm = l2cap_pi(sk)->psm;
3897
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003898 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003899 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003900
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003901 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003902 L2CAP_CONN_REQ, sizeof(req), &req);
3903 } else {
3904 l2cap_sock_clear_timer(sk);
3905 l2cap_sock_set_timer(sk, HZ / 10);
3906 }
3907 } else if (sk->sk_state == BT_CONNECT2) {
3908 struct l2cap_conn_rsp rsp;
3909 __u16 result;
3910
3911 if (!status) {
3912 sk->sk_state = BT_CONFIG;
3913 result = L2CAP_CR_SUCCESS;
3914 } else {
3915 sk->sk_state = BT_DISCONN;
3916 l2cap_sock_set_timer(sk, HZ / 10);
3917 result = L2CAP_CR_SEC_BLOCK;
3918 }
3919
3920 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3921 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3922 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003923 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003924 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
3925 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926 }
3927
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928 bh_unlock_sock(sk);
3929 }
3930
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003931 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003932
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933 return 0;
3934}
3935
3936static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3937{
3938 struct l2cap_conn *conn = hcon->l2cap_data;
3939
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003940 if (!conn)
3941 conn = l2cap_conn_add(hcon, 0);
3942
3943 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944 goto drop;
3945
3946 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3947
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003948 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003950 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003951 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003952 int len;
3953
3954 if (conn->rx_len) {
3955 BT_ERR("Unexpected start frame (len %d)", skb->len);
3956 kfree_skb(conn->rx_skb);
3957 conn->rx_skb = NULL;
3958 conn->rx_len = 0;
3959 l2cap_conn_unreliable(conn, ECOMM);
3960 }
3961
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003962 /* Start fragment always begin with Basic L2CAP header */
3963 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964 BT_ERR("Frame is too short (len %d)", skb->len);
3965 l2cap_conn_unreliable(conn, ECOMM);
3966 goto drop;
3967 }
3968
3969 hdr = (struct l2cap_hdr *) skb->data;
3970 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003971 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972
3973 if (len == skb->len) {
3974 /* Complete frame received */
3975 l2cap_recv_frame(conn, skb);
3976 return 0;
3977 }
3978
3979 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3980
3981 if (skb->len > len) {
3982 BT_ERR("Frame is too long (len %d, expected len %d)",
3983 skb->len, len);
3984 l2cap_conn_unreliable(conn, ECOMM);
3985 goto drop;
3986 }
3987
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003988 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003989
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003990 if (chan && chan->sk) {
3991 struct sock *sk = chan->sk;
3992
3993 if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
3994 BT_ERR("Frame exceeding recv MTU (len %d, "
3995 "MTU %d)", len,
3996 l2cap_pi(sk)->imtu);
3997 bh_unlock_sock(sk);
3998 l2cap_conn_unreliable(conn, ECOMM);
3999 goto drop;
4000 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004001 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004002 }
4003
Linus Torvalds1da177e2005-04-16 15:20:36 -07004004 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004005 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4006 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007 goto drop;
4008
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004009 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004010 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011 conn->rx_len = len - skb->len;
4012 } else {
4013 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4014
4015 if (!conn->rx_len) {
4016 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4017 l2cap_conn_unreliable(conn, ECOMM);
4018 goto drop;
4019 }
4020
4021 if (skb->len > conn->rx_len) {
4022 BT_ERR("Fragment is too long (len %d, expected %d)",
4023 skb->len, conn->rx_len);
4024 kfree_skb(conn->rx_skb);
4025 conn->rx_skb = NULL;
4026 conn->rx_len = 0;
4027 l2cap_conn_unreliable(conn, ECOMM);
4028 goto drop;
4029 }
4030
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004031 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004032 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033 conn->rx_len -= skb->len;
4034
4035 if (!conn->rx_len) {
4036 /* Complete frame received */
4037 l2cap_recv_frame(conn, conn->rx_skb);
4038 conn->rx_skb = NULL;
4039 }
4040 }
4041
4042drop:
4043 kfree_skb(skb);
4044 return 0;
4045}
4046
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004047static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004048{
4049 struct sock *sk;
4050 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051
4052 read_lock_bh(&l2cap_sk_list.lock);
4053
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004054 sk_for_each(sk, node, &l2cap_sk_list.head) {
4055 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004057 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 +01004058 batostr(&bt_sk(sk)->src),
4059 batostr(&bt_sk(sk)->dst),
4060 sk->sk_state, __le16_to_cpu(pi->psm),
4061 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004062 pi->imtu, pi->omtu, pi->sec_level,
4063 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004064 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004067
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004068 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069}
4070
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004071static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4072{
4073 return single_open(file, l2cap_debugfs_show, inode->i_private);
4074}
4075
4076static const struct file_operations l2cap_debugfs_fops = {
4077 .open = l2cap_debugfs_open,
4078 .read = seq_read,
4079 .llseek = seq_lseek,
4080 .release = single_release,
4081};
4082
4083static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085static struct hci_proto l2cap_hci_proto = {
4086 .name = "L2CAP",
4087 .id = HCI_PROTO_L2CAP,
4088 .connect_ind = l2cap_connect_ind,
4089 .connect_cfm = l2cap_connect_cfm,
4090 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004091 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004092 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093 .recv_acldata = l2cap_recv_acldata
4094};
4095
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004096int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097{
4098 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004099
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004100 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101 if (err < 0)
4102 return err;
4103
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004104 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004105 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004106 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107 goto error;
4108 }
4109
4110 err = hci_register_proto(&l2cap_hci_proto);
4111 if (err < 0) {
4112 BT_ERR("L2CAP protocol registration failed");
4113 bt_sock_unregister(BTPROTO_L2CAP);
4114 goto error;
4115 }
4116
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004117 if (bt_debugfs) {
4118 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4119 bt_debugfs, NULL, &l2cap_debugfs_fops);
4120 if (!l2cap_debugfs)
4121 BT_ERR("Failed to create L2CAP debug file");
4122 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124 return 0;
4125
4126error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004127 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004128 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129 return err;
4130}
4131
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004132void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004134 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004136 flush_workqueue(_busy_wq);
4137 destroy_workqueue(_busy_wq);
4138
Linus Torvalds1da177e2005-04-16 15:20:36 -07004139 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4140 BT_ERR("L2CAP protocol unregistration failed");
4141
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004142 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143}
4144
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004145module_param(disable_ertm, bool, 0644);
4146MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");