blob: b41e21f462311a84e917da0bb6fec77b09e61e32 [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
244 del_timer(&l2cap_pi(sk)->retrans_timer);
245 del_timer(&l2cap_pi(sk)->monitor_timer);
246 del_timer(&l2cap_pi(sk)->ack_timer);
247
248 skb_queue_purge(SREJ_QUEUE(sk));
249 skb_queue_purge(BUSY_QUEUE(sk));
250
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. Padovan9a9c6a32010-05-01 16:15:43 -0300343static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300344{
345 struct sk_buff *skb;
346 struct l2cap_hdr *lh;
347 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300348 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300349 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200350 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300351
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300352 if (sk->sk_state != BT_CONNECTED)
353 return;
354
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300355 if (pi->fcs == L2CAP_FCS_CRC16)
356 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300357
358 BT_DBG("pi %p, control 0x%2.2x", pi, control);
359
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300360 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300361 control |= L2CAP_CTRL_FRAME_TYPE;
362
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300363 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
364 control |= L2CAP_CTRL_FINAL;
365 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
366 }
367
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300368 if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
369 control |= L2CAP_CTRL_POLL;
370 pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
371 }
372
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300373 skb = bt_skb_alloc(count, GFP_ATOMIC);
374 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300375 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300376
377 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300378 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300379 lh->cid = cpu_to_le16(pi->dcid);
380 put_unaligned_le16(control, skb_put(skb, 2));
381
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300382 if (pi->fcs == L2CAP_FCS_CRC16) {
383 u16 fcs = crc16(0, (u8 *)lh, count - 2);
384 put_unaligned_le16(fcs, skb_put(skb, 2));
385 }
386
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200387 if (lmp_no_flush_capable(conn->hcon->hdev))
388 flags = ACL_START_NO_FLUSH;
389 else
390 flags = ACL_START;
391
392 hci_send_acl(pi->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300393}
394
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300395static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300396{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300397 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300398 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300399 pi->conn_state |= L2CAP_CONN_RNR_SENT;
400 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300401 control |= L2CAP_SUPER_RCV_READY;
402
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300403 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
404
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300405 l2cap_send_sframe(pi, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300406}
407
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300408static inline int __l2cap_no_conn_pending(struct sock *sk)
409{
410 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
411}
412
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300413static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200414{
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300415 struct sock *sk = chan->sk;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200416 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
417
418 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100419 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
420 return;
421
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300422 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200423 struct l2cap_conn_req req;
424 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
425 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200426
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300427 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300428 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200429
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300430 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
431 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200432 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200433 } else {
434 struct l2cap_info_req req;
435 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
436
437 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
438 conn->info_ident = l2cap_get_ident(conn);
439
440 mod_timer(&conn->info_timer, jiffies +
441 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
442
443 l2cap_send_cmd(conn, conn->info_ident,
444 L2CAP_INFO_REQ, sizeof(req), &req);
445 }
446}
447
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300448static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
449{
450 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300451 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300452 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
453
454 switch (mode) {
455 case L2CAP_MODE_ERTM:
456 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
457 case L2CAP_MODE_STREAMING:
458 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
459 default:
460 return 0x00;
461 }
462}
463
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200464void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300465{
466 struct l2cap_disconn_req req;
467
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300468 if (!conn)
469 return;
470
471 skb_queue_purge(TX_QUEUE(sk));
472
473 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
474 del_timer(&l2cap_pi(sk)->retrans_timer);
475 del_timer(&l2cap_pi(sk)->monitor_timer);
476 del_timer(&l2cap_pi(sk)->ack_timer);
477 }
478
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300479 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
480 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
481 l2cap_send_cmd(conn, l2cap_get_ident(conn),
482 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300483
484 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300485 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300486}
487
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200489static void l2cap_conn_start(struct l2cap_conn *conn)
490{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300491 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200492
493 BT_DBG("conn %p", conn);
494
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300495 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200496
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300497 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300498 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300499
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200500 bh_lock_sock(sk);
501
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300502 if (sk->sk_type != SOCK_SEQPACKET &&
503 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200504 bh_unlock_sock(sk);
505 continue;
506 }
507
508 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300509 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300510
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300511 if (!l2cap_check_security(sk) ||
512 !__l2cap_no_conn_pending(sk)) {
513 bh_unlock_sock(sk);
514 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200515 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300516
517 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
518 conn->feat_mask)
519 && l2cap_pi(sk)->conf_state &
520 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300521 /* __l2cap_sock_close() calls list_del(chan)
522 * so release the lock */
523 read_unlock_bh(&conn->chan_lock);
524 __l2cap_sock_close(sk, ECONNRESET);
525 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300526 bh_unlock_sock(sk);
527 continue;
528 }
529
530 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
531 req.psm = l2cap_pi(sk)->psm;
532
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300533 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300534 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
535
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300536 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
537 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300538
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200539 } else if (sk->sk_state == BT_CONNECT2) {
540 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300541 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200542 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
543 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
544
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100545 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100546 if (bt_sk(sk)->defer_setup) {
547 struct sock *parent = bt_sk(sk)->parent;
548 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
549 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
550 parent->sk_data_ready(parent, 0);
551
552 } else {
553 sk->sk_state = BT_CONFIG;
554 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
555 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
556 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200557 } else {
558 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
559 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
560 }
561
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300562 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
563 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300564
565 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
566 rsp.result != L2CAP_CR_SUCCESS) {
567 bh_unlock_sock(sk);
568 continue;
569 }
570
571 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
572 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300573 l2cap_build_conf_req(chan, buf), buf);
574 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200575 }
576
577 bh_unlock_sock(sk);
578 }
579
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300580 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200581}
582
Ville Tervob62f3282011-02-10 22:38:50 -0300583/* Find socket with cid and source bdaddr.
584 * Returns closest match, locked.
585 */
586static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
587{
588 struct sock *s, *sk = NULL, *sk1 = NULL;
589 struct hlist_node *node;
590
591 read_lock(&l2cap_sk_list.lock);
592
593 sk_for_each(sk, node, &l2cap_sk_list.head) {
594 if (state && sk->sk_state != state)
595 continue;
596
597 if (l2cap_pi(sk)->scid == cid) {
598 /* Exact match. */
599 if (!bacmp(&bt_sk(sk)->src, src))
600 break;
601
602 /* Closest match */
603 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
604 sk1 = sk;
605 }
606 }
607 s = node ? sk : sk1;
608 if (s)
609 bh_lock_sock(s);
610 read_unlock(&l2cap_sk_list.lock);
611
612 return s;
613}
614
615static void l2cap_le_conn_ready(struct l2cap_conn *conn)
616{
Ville Tervob62f3282011-02-10 22:38:50 -0300617 struct sock *parent, *uninitialized_var(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300618 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300619
620 BT_DBG("");
621
622 /* Check if we have socket listening on cid */
623 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
624 conn->src);
625 if (!parent)
626 return;
627
628 /* Check for backlog size */
629 if (sk_acceptq_is_full(parent)) {
630 BT_DBG("backlog full %d", parent->sk_ack_backlog);
631 goto clean;
632 }
633
634 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
635 if (!sk)
636 goto clean;
637
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300638 chan = l2cap_chan_alloc(sk);
639 if (!chan) {
640 l2cap_sock_kill(sk);
641 goto clean;
642 }
643
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300644 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300645
646 hci_conn_hold(conn->hcon);
647
648 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300649
Ville Tervob62f3282011-02-10 22:38:50 -0300650 bacpy(&bt_sk(sk)->src, conn->src);
651 bacpy(&bt_sk(sk)->dst, conn->dst);
652
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300653 bt_accept_enqueue(parent, sk);
654
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300655 __l2cap_chan_add(conn, chan);
656
657 l2cap_pi(sk)->chan = chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300658
659 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
660
661 sk->sk_state = BT_CONNECTED;
662 parent->sk_data_ready(parent, 0);
663
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300664 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300665
666clean:
667 bh_unlock_sock(parent);
668}
669
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200670static void l2cap_conn_ready(struct l2cap_conn *conn)
671{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300672 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200673
674 BT_DBG("conn %p", conn);
675
Ville Tervob62f3282011-02-10 22:38:50 -0300676 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
677 l2cap_le_conn_ready(conn);
678
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300679 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200680
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300681 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300682 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300683
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200684 bh_lock_sock(sk);
685
Ville Tervoacd7d372011-02-10 22:38:49 -0300686 if (conn->hcon->type == LE_LINK) {
687 l2cap_sock_clear_timer(sk);
688 sk->sk_state = BT_CONNECTED;
689 sk->sk_state_change(sk);
690 }
691
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300692 if (sk->sk_type != SOCK_SEQPACKET &&
693 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200694 l2cap_sock_clear_timer(sk);
695 sk->sk_state = BT_CONNECTED;
696 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200697 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300698 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200699
700 bh_unlock_sock(sk);
701 }
702
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300703 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200704}
705
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200706/* Notify sockets that we cannot guaranty reliability anymore */
707static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
708{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300709 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200710
711 BT_DBG("conn %p", conn);
712
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300713 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200714
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300715 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300716 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300717
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100718 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200719 sk->sk_err = err;
720 }
721
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300722 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200723}
724
725static void l2cap_info_timeout(unsigned long arg)
726{
727 struct l2cap_conn *conn = (void *) arg;
728
Marcel Holtmann984947d2009-02-06 23:35:19 +0100729 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100730 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100731
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200732 l2cap_conn_start(conn);
733}
734
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
736{
Marcel Holtmann01394182006-07-03 10:02:46 +0200737 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738
Marcel Holtmann01394182006-07-03 10:02:46 +0200739 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 return conn;
741
Marcel Holtmann01394182006-07-03 10:02:46 +0200742 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
743 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745
746 hcon->l2cap_data = conn;
747 conn->hcon = hcon;
748
Marcel Holtmann01394182006-07-03 10:02:46 +0200749 BT_DBG("hcon %p conn %p", hcon, conn);
750
Ville Tervoacd7d372011-02-10 22:38:49 -0300751 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
752 conn->mtu = hcon->hdev->le_mtu;
753 else
754 conn->mtu = hcon->hdev->acl_mtu;
755
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 conn->src = &hcon->hdev->bdaddr;
757 conn->dst = &hcon->dst;
758
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200759 conn->feat_mask = 0;
760
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300762 rwlock_init(&conn->chan_lock);
763
764 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765
Ville Tervob62f3282011-02-10 22:38:50 -0300766 if (hcon->type != LE_LINK)
767 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000768 (unsigned long) conn);
769
Marcel Holtmann2950f212009-02-12 14:02:50 +0100770 conn->disc_reason = 0x13;
771
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 return conn;
773}
774
Marcel Holtmann01394182006-07-03 10:02:46 +0200775static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776{
Marcel Holtmann01394182006-07-03 10:02:46 +0200777 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300778 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 struct sock *sk;
780
Marcel Holtmann01394182006-07-03 10:02:46 +0200781 if (!conn)
782 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783
784 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
785
Wei Yongjun7585b972009-02-25 18:29:52 +0800786 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787
788 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300789 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300790 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300792 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 bh_unlock_sock(sk);
794 l2cap_sock_kill(sk);
795 }
796
Dave Young8e8440f2008-03-03 12:18:55 -0800797 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
798 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800799
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 hcon->l2cap_data = NULL;
801 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802}
803
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300804static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300806 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300807 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300808 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809}
810
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812
813/* Find socket with psm and source bdaddr.
814 * Returns closest match.
815 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000816static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817{
818 struct sock *sk = NULL, *sk1 = NULL;
819 struct hlist_node *node;
820
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000821 read_lock(&l2cap_sk_list.lock);
822
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 sk_for_each(sk, node, &l2cap_sk_list.head) {
824 if (state && sk->sk_state != state)
825 continue;
826
827 if (l2cap_pi(sk)->psm == psm) {
828 /* Exact match. */
829 if (!bacmp(&bt_sk(sk)->src, src))
830 break;
831
832 /* Closest match */
833 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
834 sk1 = sk;
835 }
836 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000839
840 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841}
842
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200843int l2cap_do_connect(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844{
845 bdaddr_t *src = &bt_sk(sk)->src;
846 bdaddr_t *dst = &bt_sk(sk)->dst;
847 struct l2cap_conn *conn;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300848 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 struct hci_conn *hcon;
850 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200851 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200852 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100854 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
855 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300857 hdev = hci_get_route(dst, src);
858 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 return -EHOSTUNREACH;
860
861 hci_dev_lock_bh(hdev);
862
Johan Hedberg8556edd32011-01-19 12:06:50 +0530863 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200864
Ville Tervoacd7d372011-02-10 22:38:49 -0300865 if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
866 hcon = hci_connect(hdev, LE_LINK, dst,
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100867 l2cap_pi(sk)->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300868 else
869 hcon = hci_connect(hdev, ACL_LINK, dst,
870 l2cap_pi(sk)->sec_level, auth_type);
871
Ville Tervo30e76272011-02-22 16:10:53 -0300872 if (IS_ERR(hcon)) {
873 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300875 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876
877 conn = l2cap_conn_add(hcon, 0);
878 if (!conn) {
879 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300880 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 goto done;
882 }
883
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300884 chan = l2cap_chan_alloc(sk);
885 if (!chan) {
886 hci_conn_put(hcon);
887 err = -ENOMEM;
888 goto done;
889 }
890
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 /* Update source addr of the socket */
892 bacpy(src, conn->src);
893
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300894 l2cap_chan_add(conn, chan);
895
896 l2cap_pi(sk)->chan = chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897
898 sk->sk_state = BT_CONNECT;
899 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
900
901 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300902 if (sk->sk_type != SOCK_SEQPACKET &&
903 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530905 if (l2cap_check_security(sk))
906 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200907 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300908 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 }
910
Ville Tervo30e76272011-02-22 16:10:53 -0300911 err = 0;
912
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913done:
914 hci_dev_unlock_bh(hdev);
915 hci_dev_put(hdev);
916 return err;
917}
918
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200919int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300920{
921 DECLARE_WAITQUEUE(wait, current);
922 int err = 0;
923 int timeo = HZ/5;
924
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200925 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300926 while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
927 set_current_state(TASK_INTERRUPTIBLE);
928
929 if (!timeo)
930 timeo = HZ/5;
931
932 if (signal_pending(current)) {
933 err = sock_intr_errno(timeo);
934 break;
935 }
936
937 release_sock(sk);
938 timeo = schedule_timeout(timeo);
939 lock_sock(sk);
940
941 err = sock_error(sk);
942 if (err)
943 break;
944 }
945 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200946 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300947 return err;
948}
949
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300950static void l2cap_monitor_timeout(unsigned long arg)
951{
952 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300953
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300954 BT_DBG("sk %p", sk);
955
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300956 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300957 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300958 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200959 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300960 return;
961 }
962
963 l2cap_pi(sk)->retry_count++;
964 __mod_monitor_timer();
965
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -0300966 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300967 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300968}
969
970static void l2cap_retrans_timeout(unsigned long arg)
971{
972 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300973
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300974 BT_DBG("sk %p", sk);
975
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300976 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300977 l2cap_pi(sk)->retry_count = 1;
978 __mod_monitor_timer();
979
980 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
981
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -0300982 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300983 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300984}
985
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300986static void l2cap_drop_acked_frames(struct sock *sk)
987{
988 struct sk_buff *skb;
989
Gustavo F. Padovan812e7372010-05-01 16:15:42 -0300990 while ((skb = skb_peek(TX_QUEUE(sk))) &&
991 l2cap_pi(sk)->unacked_frames) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300992 if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
993 break;
994
995 skb = skb_dequeue(TX_QUEUE(sk));
996 kfree_skb(skb);
997
998 l2cap_pi(sk)->unacked_frames--;
999 }
1000
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001001 if (!l2cap_pi(sk)->unacked_frames)
1002 del_timer(&l2cap_pi(sk)->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001003}
1004
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001005void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001006{
1007 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001008 struct hci_conn *hcon = pi->conn->hcon;
1009 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001010
1011 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1012
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001013 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
1014 flags = ACL_START_NO_FLUSH;
1015 else
1016 flags = ACL_START;
1017
1018 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001019}
1020
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001021void l2cap_streaming_send(struct sock *sk)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001022{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001023 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001024 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001025 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001026
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001027 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
1028 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001029 control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001030 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001031
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001032 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001033 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1034 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001035 }
1036
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001037 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001038
1039 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001040 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001041}
1042
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001043static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001044{
1045 struct l2cap_pinfo *pi = l2cap_pi(sk);
1046 struct sk_buff *skb, *tx_skb;
1047 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001048
1049 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001050 if (!skb)
1051 return;
1052
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001053 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001054 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001055 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001056
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001057 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1058 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001059
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001060 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001061
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001062 if (pi->remote_max_tx &&
1063 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001064 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001065 return;
1066 }
1067
1068 tx_skb = skb_clone(skb, GFP_ATOMIC);
1069 bt_cb(skb)->retries++;
1070 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001071
1072 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1073 control |= L2CAP_CTRL_FINAL;
1074 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1075 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001076
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001077 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1078 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001079
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001080 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1081
1082 if (pi->fcs == L2CAP_FCS_CRC16) {
1083 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1084 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1085 }
1086
1087 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001088}
1089
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001090int l2cap_ertm_send(struct sock *sk)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001091{
1092 struct sk_buff *skb, *tx_skb;
1093 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001094 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001095 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001096
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001097 if (sk->sk_state != BT_CONNECTED)
1098 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001099
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001100 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001101
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001102 if (pi->remote_max_tx &&
1103 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001104 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001105 break;
1106 }
1107
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001108 tx_skb = skb_clone(skb, GFP_ATOMIC);
1109
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001110 bt_cb(skb)->retries++;
1111
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001112 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001113 control &= L2CAP_CTRL_SAR;
1114
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001115 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1116 control |= L2CAP_CTRL_FINAL;
1117 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1118 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001119 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001120 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1121 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1122
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001123
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001124 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001125 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1126 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1127 }
1128
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001129 l2cap_do_send(sk, tx_skb);
1130
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001131 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001132
1133 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1134 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1135
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301136 if (bt_cb(skb)->retries == 1)
1137 pi->unacked_frames++;
1138
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001139 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001140
1141 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1142 sk->sk_send_head = NULL;
1143 else
1144 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001145
1146 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001147 }
1148
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001149 return nsent;
1150}
1151
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001152static int l2cap_retransmit_frames(struct sock *sk)
1153{
1154 struct l2cap_pinfo *pi = l2cap_pi(sk);
1155 int ret;
1156
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001157 if (!skb_queue_empty(TX_QUEUE(sk)))
1158 sk->sk_send_head = TX_QUEUE(sk)->next;
1159
1160 pi->next_tx_seq = pi->expected_ack_seq;
1161 ret = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001162 return ret;
1163}
1164
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001165static void l2cap_send_ack(struct l2cap_pinfo *pi)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001166{
1167 struct sock *sk = (struct sock *)pi;
1168 u16 control = 0;
1169
1170 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1171
1172 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1173 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001174 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001175 l2cap_send_sframe(pi, control);
1176 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001177 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001178
Gustavo F. Padovane0f66212010-06-21 18:50:49 -03001179 if (l2cap_ertm_send(sk) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001180 return;
1181
1182 control |= L2CAP_SUPER_RCV_READY;
1183 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001184}
1185
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001186static void l2cap_send_srejtail(struct sock *sk)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001187{
1188 struct srej_list *tail;
1189 u16 control;
1190
1191 control = L2CAP_SUPER_SELECT_REJECT;
1192 control |= L2CAP_CTRL_FINAL;
1193
1194 tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
1195 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1196
1197 l2cap_send_sframe(l2cap_pi(sk), control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001198}
1199
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001200static 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 -07001201{
1202 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001203 struct sk_buff **frag;
1204 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001206 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001207 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208
1209 sent += count;
1210 len -= count;
1211
1212 /* Continuation fragments (no L2CAP header) */
1213 frag = &skb_shinfo(skb)->frag_list;
1214 while (len) {
1215 count = min_t(unsigned int, conn->mtu, len);
1216
1217 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1218 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001219 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001220 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1221 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222
1223 sent += count;
1224 len -= count;
1225
1226 frag = &(*frag)->next;
1227 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228
1229 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001230}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001232struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001233{
1234 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1235 struct sk_buff *skb;
1236 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1237 struct l2cap_hdr *lh;
1238
1239 BT_DBG("sk %p len %d", sk, (int)len);
1240
1241 count = min_t(unsigned int, (conn->mtu - hlen), len);
1242 skb = bt_skb_send_alloc(sk, count + hlen,
1243 msg->msg_flags & MSG_DONTWAIT, &err);
1244 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001245 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001246
1247 /* Create L2CAP header */
1248 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1249 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1250 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1251 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1252
1253 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1254 if (unlikely(err < 0)) {
1255 kfree_skb(skb);
1256 return ERR_PTR(err);
1257 }
1258 return skb;
1259}
1260
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001261struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001262{
1263 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1264 struct sk_buff *skb;
1265 int err, count, hlen = L2CAP_HDR_SIZE;
1266 struct l2cap_hdr *lh;
1267
1268 BT_DBG("sk %p len %d", sk, (int)len);
1269
1270 count = min_t(unsigned int, (conn->mtu - hlen), len);
1271 skb = bt_skb_send_alloc(sk, count + hlen,
1272 msg->msg_flags & MSG_DONTWAIT, &err);
1273 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001274 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001275
1276 /* Create L2CAP header */
1277 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1278 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1279 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1280
1281 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1282 if (unlikely(err < 0)) {
1283 kfree_skb(skb);
1284 return ERR_PTR(err);
1285 }
1286 return skb;
1287}
1288
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001289struct 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 -03001290{
1291 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1292 struct sk_buff *skb;
1293 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1294 struct l2cap_hdr *lh;
1295
1296 BT_DBG("sk %p len %d", sk, (int)len);
1297
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001298 if (!conn)
1299 return ERR_PTR(-ENOTCONN);
1300
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001301 if (sdulen)
1302 hlen += 2;
1303
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001304 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1305 hlen += 2;
1306
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001307 count = min_t(unsigned int, (conn->mtu - hlen), len);
1308 skb = bt_skb_send_alloc(sk, count + hlen,
1309 msg->msg_flags & MSG_DONTWAIT, &err);
1310 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001311 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001312
1313 /* Create L2CAP header */
1314 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1315 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1316 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1317 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001318 if (sdulen)
1319 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001320
1321 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1322 if (unlikely(err < 0)) {
1323 kfree_skb(skb);
1324 return ERR_PTR(err);
1325 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001326
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001327 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1328 put_unaligned_le16(0, skb_put(skb, 2));
1329
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001330 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001331 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332}
1333
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001334int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001335{
1336 struct l2cap_pinfo *pi = l2cap_pi(sk);
1337 struct sk_buff *skb;
1338 struct sk_buff_head sar_queue;
1339 u16 control;
1340 size_t size = 0;
1341
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001342 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001343 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001344 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001345 if (IS_ERR(skb))
1346 return PTR_ERR(skb);
1347
1348 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001349 len -= pi->remote_mps;
1350 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001351
1352 while (len > 0) {
1353 size_t buflen;
1354
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001355 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001356 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001357 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001358 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001359 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001360 buflen = len;
1361 }
1362
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001363 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001364 if (IS_ERR(skb)) {
1365 skb_queue_purge(&sar_queue);
1366 return PTR_ERR(skb);
1367 }
1368
1369 __skb_queue_tail(&sar_queue, skb);
1370 len -= buflen;
1371 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001372 }
1373 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1374 if (sk->sk_send_head == NULL)
1375 sk->sk_send_head = sar_queue.next;
1376
1377 return size;
1378}
1379
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380static void l2cap_chan_ready(struct sock *sk)
1381{
1382 struct sock *parent = bt_sk(sk)->parent;
1383
1384 BT_DBG("sk %p, parent %p", sk, parent);
1385
1386 l2cap_pi(sk)->conf_state = 0;
1387 l2cap_sock_clear_timer(sk);
1388
1389 if (!parent) {
1390 /* Outgoing channel.
1391 * Wake up socket sleeping on connect.
1392 */
1393 sk->sk_state = BT_CONNECTED;
1394 sk->sk_state_change(sk);
1395 } else {
1396 /* Incoming channel.
1397 * Wake up socket sleeping on accept.
1398 */
1399 parent->sk_data_ready(parent, 0);
1400 }
1401}
1402
1403/* Copy frame to all raw sockets on that connection */
1404static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1405{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001407 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408
1409 BT_DBG("conn %p", conn);
1410
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001411 read_lock(&conn->chan_lock);
1412 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001413 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 if (sk->sk_type != SOCK_RAW)
1415 continue;
1416
1417 /* Don't send frame to the socket it came from */
1418 if (skb->sk == sk)
1419 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001420 nskb = skb_clone(skb, GFP_ATOMIC);
1421 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 continue;
1423
1424 if (sock_queue_rcv_skb(sk, nskb))
1425 kfree_skb(nskb);
1426 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001427 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428}
1429
1430/* ---- L2CAP signalling commands ---- */
1431static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1432 u8 code, u8 ident, u16 dlen, void *data)
1433{
1434 struct sk_buff *skb, **frag;
1435 struct l2cap_cmd_hdr *cmd;
1436 struct l2cap_hdr *lh;
1437 int len, count;
1438
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001439 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1440 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441
1442 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1443 count = min_t(unsigned int, conn->mtu, len);
1444
1445 skb = bt_skb_alloc(count, GFP_ATOMIC);
1446 if (!skb)
1447 return NULL;
1448
1449 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001450 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001451
1452 if (conn->hcon->type == LE_LINK)
1453 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1454 else
1455 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456
1457 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1458 cmd->code = code;
1459 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001460 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461
1462 if (dlen) {
1463 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1464 memcpy(skb_put(skb, count), data, count);
1465 data += count;
1466 }
1467
1468 len -= skb->len;
1469
1470 /* Continuation fragments (no L2CAP header) */
1471 frag = &skb_shinfo(skb)->frag_list;
1472 while (len) {
1473 count = min_t(unsigned int, conn->mtu, len);
1474
1475 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1476 if (!*frag)
1477 goto fail;
1478
1479 memcpy(skb_put(*frag, count), data, count);
1480
1481 len -= count;
1482 data += count;
1483
1484 frag = &(*frag)->next;
1485 }
1486
1487 return skb;
1488
1489fail:
1490 kfree_skb(skb);
1491 return NULL;
1492}
1493
1494static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1495{
1496 struct l2cap_conf_opt *opt = *ptr;
1497 int len;
1498
1499 len = L2CAP_CONF_OPT_SIZE + opt->len;
1500 *ptr += len;
1501
1502 *type = opt->type;
1503 *olen = opt->len;
1504
1505 switch (opt->len) {
1506 case 1:
1507 *val = *((u8 *) opt->val);
1508 break;
1509
1510 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001511 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 break;
1513
1514 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001515 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 break;
1517
1518 default:
1519 *val = (unsigned long) opt->val;
1520 break;
1521 }
1522
1523 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1524 return len;
1525}
1526
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1528{
1529 struct l2cap_conf_opt *opt = *ptr;
1530
1531 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1532
1533 opt->type = type;
1534 opt->len = len;
1535
1536 switch (len) {
1537 case 1:
1538 *((u8 *) opt->val) = val;
1539 break;
1540
1541 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001542 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 break;
1544
1545 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001546 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 break;
1548
1549 default:
1550 memcpy(opt->val, (void *) val, len);
1551 break;
1552 }
1553
1554 *ptr += L2CAP_CONF_OPT_SIZE + len;
1555}
1556
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001557static void l2cap_ack_timeout(unsigned long arg)
1558{
1559 struct sock *sk = (void *) arg;
1560
1561 bh_lock_sock(sk);
1562 l2cap_send_ack(l2cap_pi(sk));
1563 bh_unlock_sock(sk);
1564}
1565
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001566static inline void l2cap_ertm_init(struct sock *sk)
1567{
1568 l2cap_pi(sk)->expected_ack_seq = 0;
1569 l2cap_pi(sk)->unacked_frames = 0;
1570 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03001571 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001572 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001573
1574 setup_timer(&l2cap_pi(sk)->retrans_timer,
1575 l2cap_retrans_timeout, (unsigned long) sk);
1576 setup_timer(&l2cap_pi(sk)->monitor_timer,
1577 l2cap_monitor_timeout, (unsigned long) sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001578 setup_timer(&l2cap_pi(sk)->ack_timer,
1579 l2cap_ack_timeout, (unsigned long) sk);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001580
1581 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001582 __skb_queue_head_init(BUSY_QUEUE(sk));
1583
1584 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001585
1586 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001587}
1588
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001589static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1590{
1591 switch (mode) {
1592 case L2CAP_MODE_STREAMING:
1593 case L2CAP_MODE_ERTM:
1594 if (l2cap_mode_supported(mode, remote_feat_mask))
1595 return mode;
1596 /* fall through */
1597 default:
1598 return L2CAP_MODE_BASIC;
1599 }
1600}
1601
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001602static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001604 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 struct l2cap_pinfo *pi = l2cap_pi(sk);
1606 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001607 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 void *ptr = req->data;
1609
1610 BT_DBG("sk %p", sk);
1611
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001612 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001613 goto done;
1614
1615 switch (pi->mode) {
1616 case L2CAP_MODE_STREAMING:
1617 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001618 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001619 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001620
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001621 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001622 default:
1623 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1624 break;
1625 }
1626
1627done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001628 if (pi->imtu != L2CAP_DEFAULT_MTU)
1629 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1630
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001631 switch (pi->mode) {
1632 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001633 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1634 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1635 break;
1636
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001637 rfc.mode = L2CAP_MODE_BASIC;
1638 rfc.txwin_size = 0;
1639 rfc.max_transmit = 0;
1640 rfc.retrans_timeout = 0;
1641 rfc.monitor_timeout = 0;
1642 rfc.max_pdu_size = 0;
1643
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001644 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1645 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001646 break;
1647
1648 case L2CAP_MODE_ERTM:
1649 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001650 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001651 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001652 rfc.retrans_timeout = 0;
1653 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001654 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001655 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001656 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001657
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001658 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1659 (unsigned long) &rfc);
1660
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001661 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1662 break;
1663
1664 if (pi->fcs == L2CAP_FCS_NONE ||
1665 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1666 pi->fcs = L2CAP_FCS_NONE;
1667 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1668 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001669 break;
1670
1671 case L2CAP_MODE_STREAMING:
1672 rfc.mode = L2CAP_MODE_STREAMING;
1673 rfc.txwin_size = 0;
1674 rfc.max_transmit = 0;
1675 rfc.retrans_timeout = 0;
1676 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001677 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001678 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001679 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001680
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001681 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1682 (unsigned long) &rfc);
1683
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001684 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1685 break;
1686
1687 if (pi->fcs == L2CAP_FCS_NONE ||
1688 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1689 pi->fcs = L2CAP_FCS_NONE;
1690 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1691 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001692 break;
1693 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001695 req->dcid = cpu_to_le16(pi->dcid);
1696 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697
1698 return ptr - data;
1699}
1700
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001701static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001703 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001704 struct l2cap_conf_rsp *rsp = data;
1705 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001706 void *req = chan->conf_req;
1707 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001708 int type, hint, olen;
1709 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001710 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001711 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001712 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001714 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001715
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001716 while (len >= L2CAP_CONF_OPT_SIZE) {
1717 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001719 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001720 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001721
1722 switch (type) {
1723 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001724 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001725 break;
1726
1727 case L2CAP_CONF_FLUSH_TO:
1728 pi->flush_to = val;
1729 break;
1730
1731 case L2CAP_CONF_QOS:
1732 break;
1733
Marcel Holtmann6464f352007-10-20 13:39:51 +02001734 case L2CAP_CONF_RFC:
1735 if (olen == sizeof(rfc))
1736 memcpy(&rfc, (void *) val, olen);
1737 break;
1738
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001739 case L2CAP_CONF_FCS:
1740 if (val == L2CAP_FCS_NONE)
1741 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1742
1743 break;
1744
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001745 default:
1746 if (hint)
1747 break;
1748
1749 result = L2CAP_CONF_UNKNOWN;
1750 *((u8 *) ptr++) = type;
1751 break;
1752 }
1753 }
1754
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001755 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001756 goto done;
1757
1758 switch (pi->mode) {
1759 case L2CAP_MODE_STREAMING:
1760 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001761 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1762 pi->mode = l2cap_select_mode(rfc.mode,
1763 pi->conn->feat_mask);
1764 break;
1765 }
1766
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001767 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001768 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001769
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001770 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001771 }
1772
1773done:
1774 if (pi->mode != rfc.mode) {
1775 result = L2CAP_CONF_UNACCEPT;
1776 rfc.mode = pi->mode;
1777
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001778 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001779 return -ECONNREFUSED;
1780
1781 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1782 sizeof(rfc), (unsigned long) &rfc);
1783 }
1784
1785
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001786 if (result == L2CAP_CONF_SUCCESS) {
1787 /* Configure output options and let the other side know
1788 * which ones we don't like. */
1789
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001790 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1791 result = L2CAP_CONF_UNACCEPT;
1792 else {
1793 pi->omtu = mtu;
1794 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1795 }
1796 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001797
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001798 switch (rfc.mode) {
1799 case L2CAP_MODE_BASIC:
1800 pi->fcs = L2CAP_FCS_NONE;
1801 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1802 break;
1803
1804 case L2CAP_MODE_ERTM:
1805 pi->remote_tx_win = rfc.txwin_size;
1806 pi->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001807
1808 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1809 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001810
1811 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001812
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001813 rfc.retrans_timeout =
1814 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1815 rfc.monitor_timeout =
1816 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001817
1818 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001819
1820 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1821 sizeof(rfc), (unsigned long) &rfc);
1822
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001823 break;
1824
1825 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001826 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1827 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001828
1829 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001830
1831 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001832
1833 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1834 sizeof(rfc), (unsigned long) &rfc);
1835
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001836 break;
1837
1838 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001839 result = L2CAP_CONF_UNACCEPT;
1840
1841 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001842 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001843 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001844
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001845 if (result == L2CAP_CONF_SUCCESS)
1846 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1847 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001848 rsp->scid = cpu_to_le16(pi->dcid);
1849 rsp->result = cpu_to_le16(result);
1850 rsp->flags = cpu_to_le16(0x0000);
1851
1852 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853}
1854
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001855static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1856{
1857 struct l2cap_pinfo *pi = l2cap_pi(sk);
1858 struct l2cap_conf_req *req = data;
1859 void *ptr = req->data;
1860 int type, olen;
1861 unsigned long val;
1862 struct l2cap_conf_rfc rfc;
1863
1864 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1865
1866 while (len >= L2CAP_CONF_OPT_SIZE) {
1867 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1868
1869 switch (type) {
1870 case L2CAP_CONF_MTU:
1871 if (val < L2CAP_DEFAULT_MIN_MTU) {
1872 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001873 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001874 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001875 pi->imtu = val;
1876 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001877 break;
1878
1879 case L2CAP_CONF_FLUSH_TO:
1880 pi->flush_to = val;
1881 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1882 2, pi->flush_to);
1883 break;
1884
1885 case L2CAP_CONF_RFC:
1886 if (olen == sizeof(rfc))
1887 memcpy(&rfc, (void *)val, olen);
1888
1889 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1890 rfc.mode != pi->mode)
1891 return -ECONNREFUSED;
1892
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001893 pi->fcs = 0;
1894
1895 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1896 sizeof(rfc), (unsigned long) &rfc);
1897 break;
1898 }
1899 }
1900
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001901 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1902 return -ECONNREFUSED;
1903
1904 pi->mode = rfc.mode;
1905
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001906 if (*result == L2CAP_CONF_SUCCESS) {
1907 switch (rfc.mode) {
1908 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001909 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1910 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001911 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001912 break;
1913 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001914 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001915 }
1916 }
1917
1918 req->dcid = cpu_to_le16(pi->dcid);
1919 req->flags = cpu_to_le16(0x0000);
1920
1921 return ptr - data;
1922}
1923
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001924static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925{
1926 struct l2cap_conf_rsp *rsp = data;
1927 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001929 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001931 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001932 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001933 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934
1935 return ptr - data;
1936}
1937
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001938void __l2cap_connect_rsp_defer(struct sock *sk)
1939{
1940 struct l2cap_conn_rsp rsp;
1941 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1942 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
1943 u8 buf[128];
1944
1945 sk->sk_state = BT_CONFIG;
1946
1947 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1948 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1949 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1950 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1951 l2cap_send_cmd(conn, chan->ident,
1952 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1953
1954 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
1955 return;
1956
1957 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
1958 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1959 l2cap_build_conf_req(chan, buf), buf);
1960 chan->num_conf_req++;
1961}
1962
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001963static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1964{
1965 struct l2cap_pinfo *pi = l2cap_pi(sk);
1966 int type, olen;
1967 unsigned long val;
1968 struct l2cap_conf_rfc rfc;
1969
1970 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1971
1972 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1973 return;
1974
1975 while (len >= L2CAP_CONF_OPT_SIZE) {
1976 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1977
1978 switch (type) {
1979 case L2CAP_CONF_RFC:
1980 if (olen == sizeof(rfc))
1981 memcpy(&rfc, (void *)val, olen);
1982 goto done;
1983 }
1984 }
1985
1986done:
1987 switch (rfc.mode) {
1988 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001989 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1990 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001991 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1992 break;
1993 case L2CAP_MODE_STREAMING:
1994 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1995 }
1996}
1997
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001998static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1999{
2000 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2001
2002 if (rej->reason != 0x0000)
2003 return 0;
2004
2005 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2006 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002007 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002008
2009 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002010 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002011
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002012 l2cap_conn_start(conn);
2013 }
2014
2015 return 0;
2016}
2017
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2019{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2021 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002022 struct l2cap_chan *chan = NULL;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002023 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002024 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025
2026 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002027 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028
2029 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2030
2031 /* Check if we have socket listening on psm */
2032 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2033 if (!parent) {
2034 result = L2CAP_CR_BAD_PSM;
2035 goto sendresp;
2036 }
2037
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002038 bh_lock_sock(parent);
2039
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002040 /* Check if the ACL is secure enough (if not SDP) */
2041 if (psm != cpu_to_le16(0x0001) &&
2042 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002043 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002044 result = L2CAP_CR_SEC_BLOCK;
2045 goto response;
2046 }
2047
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048 result = L2CAP_CR_NO_MEM;
2049
2050 /* Check for backlog size */
2051 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002052 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 goto response;
2054 }
2055
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002056 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 if (!sk)
2058 goto response;
2059
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002060 chan = l2cap_chan_alloc(sk);
2061 if (!chan) {
2062 l2cap_sock_kill(sk);
2063 goto response;
2064 }
2065
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002066 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067
2068 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002069 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2070 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 sock_set_flag(sk, SOCK_ZAPPED);
2072 l2cap_sock_kill(sk);
2073 goto response;
2074 }
2075
2076 hci_conn_hold(conn->hcon);
2077
2078 l2cap_sock_init(sk, parent);
2079 bacpy(&bt_sk(sk)->src, conn->src);
2080 bacpy(&bt_sk(sk)->dst, conn->dst);
2081 l2cap_pi(sk)->psm = psm;
2082 l2cap_pi(sk)->dcid = scid;
2083
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002084 bt_accept_enqueue(parent, sk);
2085
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002086 __l2cap_chan_add(conn, chan);
2087
2088 l2cap_pi(sk)->chan = chan;
2089
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 dcid = l2cap_pi(sk)->scid;
2091
2092 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2093
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002094 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095
Marcel Holtmann984947d2009-02-06 23:35:19 +01002096 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002097 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002098 if (bt_sk(sk)->defer_setup) {
2099 sk->sk_state = BT_CONNECT2;
2100 result = L2CAP_CR_PEND;
2101 status = L2CAP_CS_AUTHOR_PEND;
2102 parent->sk_data_ready(parent, 0);
2103 } else {
2104 sk->sk_state = BT_CONFIG;
2105 result = L2CAP_CR_SUCCESS;
2106 status = L2CAP_CS_NO_INFO;
2107 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002108 } else {
2109 sk->sk_state = BT_CONNECT2;
2110 result = L2CAP_CR_PEND;
2111 status = L2CAP_CS_AUTHEN_PEND;
2112 }
2113 } else {
2114 sk->sk_state = BT_CONNECT2;
2115 result = L2CAP_CR_PEND;
2116 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 }
2118
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002119 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120
2121response:
2122 bh_unlock_sock(parent);
2123
2124sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002125 rsp.scid = cpu_to_le16(scid);
2126 rsp.dcid = cpu_to_le16(dcid);
2127 rsp.result = cpu_to_le16(result);
2128 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002130
2131 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2132 struct l2cap_info_req info;
2133 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2134
2135 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2136 conn->info_ident = l2cap_get_ident(conn);
2137
2138 mod_timer(&conn->info_timer, jiffies +
2139 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2140
2141 l2cap_send_cmd(conn, conn->info_ident,
2142 L2CAP_INFO_REQ, sizeof(info), &info);
2143 }
2144
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002145 if (chan && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002146 result == L2CAP_CR_SUCCESS) {
2147 u8 buf[128];
2148 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2149 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002150 l2cap_build_conf_req(chan, buf), buf);
2151 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002152 }
2153
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 return 0;
2155}
2156
2157static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2158{
2159 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2160 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002161 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 struct sock *sk;
2163 u8 req[128];
2164
2165 scid = __le16_to_cpu(rsp->scid);
2166 dcid = __le16_to_cpu(rsp->dcid);
2167 result = __le16_to_cpu(rsp->result);
2168 status = __le16_to_cpu(rsp->status);
2169
2170 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2171
2172 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002173 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002174 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002175 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002177 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002178 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002179 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 }
2181
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002182 sk = chan->sk;
2183
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 switch (result) {
2185 case L2CAP_CR_SUCCESS:
2186 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002187 chan->ident = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002189 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2190
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002191 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2192 break;
2193
2194 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2195
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002197 l2cap_build_conf_req(chan, req), req);
2198 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 break;
2200
2201 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002202 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 break;
2204
2205 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002206 /* don't delete l2cap channel if sk is owned by user */
2207 if (sock_owned_by_user(sk)) {
2208 sk->sk_state = BT_DISCONN;
2209 l2cap_sock_clear_timer(sk);
2210 l2cap_sock_set_timer(sk, HZ / 5);
2211 break;
2212 }
2213
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002214 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 break;
2216 }
2217
2218 bh_unlock_sock(sk);
2219 return 0;
2220}
2221
Mat Martineau8c462b62010-08-24 15:35:42 -07002222static inline void set_default_fcs(struct l2cap_pinfo *pi)
2223{
2224 /* FCS is enabled only in ERTM or streaming mode, if one or both
2225 * sides request it.
2226 */
2227 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2228 pi->fcs = L2CAP_FCS_NONE;
2229 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2230 pi->fcs = L2CAP_FCS_CRC16;
2231}
2232
Al Viro88219a02007-07-29 00:17:25 -07002233static 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 -07002234{
2235 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2236 u16 dcid, flags;
2237 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002238 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002240 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241
2242 dcid = __le16_to_cpu(req->dcid);
2243 flags = __le16_to_cpu(req->flags);
2244
2245 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2246
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002247 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002248 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249 return -ENOENT;
2250
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002251 sk = chan->sk;
2252
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002253 if (sk->sk_state != BT_CONFIG) {
2254 struct l2cap_cmd_rej rej;
2255
2256 rej.reason = cpu_to_le16(0x0002);
2257 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2258 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002259 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002260 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002261
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002262 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002263 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002264 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002265 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2266 l2cap_build_conf_rsp(sk, rsp,
2267 L2CAP_CONF_REJECT, flags), rsp);
2268 goto unlock;
2269 }
2270
2271 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002272 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2273 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274
2275 if (flags & 0x0001) {
2276 /* Incomplete config. Send empty response. */
2277 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002278 l2cap_build_conf_rsp(sk, rsp,
2279 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280 goto unlock;
2281 }
2282
2283 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002284 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002285 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002286 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002288 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002290 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002291 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002292
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002293 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002294 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002295
Marcel Holtmann876d9482007-10-20 13:35:42 +02002296 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2297 goto unlock;
2298
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002300 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002301
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002303
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002304 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002305 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002306 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002307 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2308 l2cap_ertm_init(sk);
2309
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002311 goto unlock;
2312 }
2313
2314 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002315 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002316 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002318 l2cap_build_conf_req(chan, buf), buf);
2319 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 }
2321
2322unlock:
2323 bh_unlock_sock(sk);
2324 return 0;
2325}
2326
2327static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2328{
2329 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2330 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002331 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002333 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334
2335 scid = __le16_to_cpu(rsp->scid);
2336 flags = __le16_to_cpu(rsp->flags);
2337 result = __le16_to_cpu(rsp->result);
2338
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002339 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2340 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002342 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002343 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 return 0;
2345
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002346 sk = chan->sk;
2347
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 switch (result) {
2349 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002350 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 break;
2352
2353 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002354 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002355 char req[64];
2356
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002357 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002358 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002359 goto done;
2360 }
2361
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002362 /* throw out any old stored conf requests */
2363 result = L2CAP_CONF_SUCCESS;
2364 len = l2cap_parse_conf_rsp(sk, rsp->data,
2365 len, req, &result);
2366 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002367 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002368 goto done;
2369 }
2370
2371 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2372 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002373 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002374 if (result != L2CAP_CONF_SUCCESS)
2375 goto done;
2376 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377 }
2378
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002379 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002380 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002382 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 goto done;
2384 }
2385
2386 if (flags & 0x01)
2387 goto done;
2388
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2390
2391 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002392 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002393
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002395 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002396 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002397 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002398 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2399 l2cap_ertm_init(sk);
2400
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 l2cap_chan_ready(sk);
2402 }
2403
2404done:
2405 bh_unlock_sock(sk);
2406 return 0;
2407}
2408
2409static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2410{
2411 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2412 struct l2cap_disconn_rsp rsp;
2413 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002414 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415 struct sock *sk;
2416
2417 scid = __le16_to_cpu(req->scid);
2418 dcid = __le16_to_cpu(req->dcid);
2419
2420 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2421
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002422 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002423 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 return 0;
2425
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002426 sk = chan->sk;
2427
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002428 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2429 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2431
2432 sk->sk_shutdown = SHUTDOWN_MASK;
2433
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002434 /* don't delete l2cap channel if sk is owned by user */
2435 if (sock_owned_by_user(sk)) {
2436 sk->sk_state = BT_DISCONN;
2437 l2cap_sock_clear_timer(sk);
2438 l2cap_sock_set_timer(sk, HZ / 5);
2439 bh_unlock_sock(sk);
2440 return 0;
2441 }
2442
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002443 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444 bh_unlock_sock(sk);
2445
2446 l2cap_sock_kill(sk);
2447 return 0;
2448}
2449
2450static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2451{
2452 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2453 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002454 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 struct sock *sk;
2456
2457 scid = __le16_to_cpu(rsp->scid);
2458 dcid = __le16_to_cpu(rsp->dcid);
2459
2460 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2461
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002462 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002463 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 return 0;
2465
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002466 sk = chan->sk;
2467
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002468 /* don't delete l2cap channel if sk is owned by user */
2469 if (sock_owned_by_user(sk)) {
2470 sk->sk_state = BT_DISCONN;
2471 l2cap_sock_clear_timer(sk);
2472 l2cap_sock_set_timer(sk, HZ / 5);
2473 bh_unlock_sock(sk);
2474 return 0;
2475 }
2476
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002477 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 bh_unlock_sock(sk);
2479
2480 l2cap_sock_kill(sk);
2481 return 0;
2482}
2483
2484static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2485{
2486 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487 u16 type;
2488
2489 type = __le16_to_cpu(req->type);
2490
2491 BT_DBG("type 0x%4.4x", type);
2492
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002493 if (type == L2CAP_IT_FEAT_MASK) {
2494 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002495 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002496 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2497 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2498 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002499 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002500 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2501 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002502 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002503 l2cap_send_cmd(conn, cmd->ident,
2504 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002505 } else if (type == L2CAP_IT_FIXED_CHAN) {
2506 u8 buf[12];
2507 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2508 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2509 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2510 memcpy(buf + 4, l2cap_fixed_chan, 8);
2511 l2cap_send_cmd(conn, cmd->ident,
2512 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002513 } else {
2514 struct l2cap_info_rsp rsp;
2515 rsp.type = cpu_to_le16(type);
2516 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2517 l2cap_send_cmd(conn, cmd->ident,
2518 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2519 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520
2521 return 0;
2522}
2523
2524static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2525{
2526 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2527 u16 type, result;
2528
2529 type = __le16_to_cpu(rsp->type);
2530 result = __le16_to_cpu(rsp->result);
2531
2532 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2533
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002534 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2535 if (cmd->ident != conn->info_ident ||
2536 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2537 return 0;
2538
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002539 del_timer(&conn->info_timer);
2540
Ville Tervoadb08ed2010-08-04 09:43:33 +03002541 if (result != L2CAP_IR_SUCCESS) {
2542 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2543 conn->info_ident = 0;
2544
2545 l2cap_conn_start(conn);
2546
2547 return 0;
2548 }
2549
Marcel Holtmann984947d2009-02-06 23:35:19 +01002550 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002551 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002552
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002553 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002554 struct l2cap_info_req req;
2555 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2556
2557 conn->info_ident = l2cap_get_ident(conn);
2558
2559 l2cap_send_cmd(conn, conn->info_ident,
2560 L2CAP_INFO_REQ, sizeof(req), &req);
2561 } else {
2562 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2563 conn->info_ident = 0;
2564
2565 l2cap_conn_start(conn);
2566 }
2567 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002568 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002569 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002570
2571 l2cap_conn_start(conn);
2572 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002573
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574 return 0;
2575}
2576
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002577static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002578 u16 to_multiplier)
2579{
2580 u16 max_latency;
2581
2582 if (min > max || min < 6 || max > 3200)
2583 return -EINVAL;
2584
2585 if (to_multiplier < 10 || to_multiplier > 3200)
2586 return -EINVAL;
2587
2588 if (max >= to_multiplier * 8)
2589 return -EINVAL;
2590
2591 max_latency = (to_multiplier * 8 / max) - 1;
2592 if (latency > 499 || latency > max_latency)
2593 return -EINVAL;
2594
2595 return 0;
2596}
2597
2598static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2599 struct l2cap_cmd_hdr *cmd, u8 *data)
2600{
2601 struct hci_conn *hcon = conn->hcon;
2602 struct l2cap_conn_param_update_req *req;
2603 struct l2cap_conn_param_update_rsp rsp;
2604 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002605 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002606
2607 if (!(hcon->link_mode & HCI_LM_MASTER))
2608 return -EINVAL;
2609
2610 cmd_len = __le16_to_cpu(cmd->len);
2611 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2612 return -EPROTO;
2613
2614 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002615 min = __le16_to_cpu(req->min);
2616 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002617 latency = __le16_to_cpu(req->latency);
2618 to_multiplier = __le16_to_cpu(req->to_multiplier);
2619
2620 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2621 min, max, latency, to_multiplier);
2622
2623 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002624
2625 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2626 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002627 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2628 else
2629 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2630
2631 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2632 sizeof(rsp), &rsp);
2633
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002634 if (!err)
2635 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2636
Claudio Takahaside731152011-02-11 19:28:55 -02002637 return 0;
2638}
2639
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002640static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2641 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2642{
2643 int err = 0;
2644
2645 switch (cmd->code) {
2646 case L2CAP_COMMAND_REJ:
2647 l2cap_command_rej(conn, cmd, data);
2648 break;
2649
2650 case L2CAP_CONN_REQ:
2651 err = l2cap_connect_req(conn, cmd, data);
2652 break;
2653
2654 case L2CAP_CONN_RSP:
2655 err = l2cap_connect_rsp(conn, cmd, data);
2656 break;
2657
2658 case L2CAP_CONF_REQ:
2659 err = l2cap_config_req(conn, cmd, cmd_len, data);
2660 break;
2661
2662 case L2CAP_CONF_RSP:
2663 err = l2cap_config_rsp(conn, cmd, data);
2664 break;
2665
2666 case L2CAP_DISCONN_REQ:
2667 err = l2cap_disconnect_req(conn, cmd, data);
2668 break;
2669
2670 case L2CAP_DISCONN_RSP:
2671 err = l2cap_disconnect_rsp(conn, cmd, data);
2672 break;
2673
2674 case L2CAP_ECHO_REQ:
2675 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2676 break;
2677
2678 case L2CAP_ECHO_RSP:
2679 break;
2680
2681 case L2CAP_INFO_REQ:
2682 err = l2cap_information_req(conn, cmd, data);
2683 break;
2684
2685 case L2CAP_INFO_RSP:
2686 err = l2cap_information_rsp(conn, cmd, data);
2687 break;
2688
2689 default:
2690 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2691 err = -EINVAL;
2692 break;
2693 }
2694
2695 return err;
2696}
2697
2698static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2699 struct l2cap_cmd_hdr *cmd, u8 *data)
2700{
2701 switch (cmd->code) {
2702 case L2CAP_COMMAND_REJ:
2703 return 0;
2704
2705 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002706 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002707
2708 case L2CAP_CONN_PARAM_UPDATE_RSP:
2709 return 0;
2710
2711 default:
2712 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2713 return -EINVAL;
2714 }
2715}
2716
2717static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2718 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719{
2720 u8 *data = skb->data;
2721 int len = skb->len;
2722 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002723 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724
2725 l2cap_raw_recv(conn, skb);
2726
2727 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002728 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2730 data += L2CAP_CMD_HDR_SIZE;
2731 len -= L2CAP_CMD_HDR_SIZE;
2732
Al Viro88219a02007-07-29 00:17:25 -07002733 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734
Al Viro88219a02007-07-29 00:17:25 -07002735 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 -07002736
Al Viro88219a02007-07-29 00:17:25 -07002737 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738 BT_DBG("corrupted command");
2739 break;
2740 }
2741
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002742 if (conn->hcon->type == LE_LINK)
2743 err = l2cap_le_sig_cmd(conn, &cmd, data);
2744 else
2745 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746
2747 if (err) {
2748 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002749
2750 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751
2752 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002753 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2755 }
2756
Al Viro88219a02007-07-29 00:17:25 -07002757 data += cmd_len;
2758 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 }
2760
2761 kfree_skb(skb);
2762}
2763
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002764static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2765{
2766 u16 our_fcs, rcv_fcs;
2767 int hdr_size = L2CAP_HDR_SIZE + 2;
2768
2769 if (pi->fcs == L2CAP_FCS_CRC16) {
2770 skb_trim(skb, skb->len - 2);
2771 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2772 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2773
2774 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002775 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002776 }
2777 return 0;
2778}
2779
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002780static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
2781{
2782 struct l2cap_pinfo *pi = l2cap_pi(sk);
2783 u16 control = 0;
2784
2785 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002786
2787 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2788
2789 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002790 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002791 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002792 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002793 }
2794
Gustavo F. Padovan4ea727e2010-06-03 16:34:20 -03002795 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
2796 l2cap_retransmit_frames(sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002797
2798 l2cap_ertm_send(sk);
2799
2800 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
2801 pi->frames_sent == 0) {
2802 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002803 l2cap_send_sframe(pi, control);
2804 }
2805}
2806
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002807static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002808{
2809 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002810 struct l2cap_pinfo *pi = l2cap_pi(sk);
2811 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002812
2813 bt_cb(skb)->tx_seq = tx_seq;
2814 bt_cb(skb)->sar = sar;
2815
2816 next_skb = skb_peek(SREJ_QUEUE(sk));
2817 if (!next_skb) {
2818 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002819 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002820 }
2821
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002822 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
2823 if (tx_seq_offset < 0)
2824 tx_seq_offset += 64;
2825
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002826 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002827 if (bt_cb(next_skb)->tx_seq == tx_seq)
2828 return -EINVAL;
2829
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002830 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
2831 pi->buffer_seq) % 64;
2832 if (next_tx_seq_offset < 0)
2833 next_tx_seq_offset += 64;
2834
2835 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002836 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002837 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002838 }
2839
2840 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
2841 break;
2842
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002843 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002844
2845 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002846
2847 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002848}
2849
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002850static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
2851{
2852 struct l2cap_pinfo *pi = l2cap_pi(sk);
2853 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002854 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002855
2856 switch (control & L2CAP_CTRL_SAR) {
2857 case L2CAP_SDU_UNSEGMENTED:
2858 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2859 goto drop;
2860
2861 err = sock_queue_rcv_skb(sk, skb);
2862 if (!err)
2863 return err;
2864
2865 break;
2866
2867 case L2CAP_SDU_START:
2868 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2869 goto drop;
2870
2871 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002872
2873 if (pi->sdu_len > pi->imtu)
2874 goto disconnect;
2875
2876 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002877 if (!pi->sdu)
2878 return -ENOMEM;
2879
2880 /* pull sdu_len bytes only after alloc, because of Local Busy
2881 * condition we have to be sure that this will be executed
2882 * only once, i.e., when alloc does not fail */
2883 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002884
2885 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2886
2887 pi->conn_state |= L2CAP_CONN_SAR_SDU;
2888 pi->partial_sdu_len = skb->len;
2889 break;
2890
2891 case L2CAP_SDU_CONTINUE:
2892 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2893 goto disconnect;
2894
2895 if (!pi->sdu)
2896 goto disconnect;
2897
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002898 pi->partial_sdu_len += skb->len;
2899 if (pi->partial_sdu_len > pi->sdu_len)
2900 goto drop;
2901
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002902 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2903
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002904 break;
2905
2906 case L2CAP_SDU_END:
2907 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2908 goto disconnect;
2909
2910 if (!pi->sdu)
2911 goto disconnect;
2912
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002913 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002914 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002915
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002916 if (pi->partial_sdu_len > pi->imtu)
2917 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002918
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002919 if (pi->partial_sdu_len != pi->sdu_len)
2920 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002921
2922 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002923 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002924
2925 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002926 if (!_skb) {
2927 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2928 return -ENOMEM;
2929 }
2930
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002931 err = sock_queue_rcv_skb(sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002932 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002933 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002934 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2935 return err;
2936 }
2937
2938 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2939 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002940
2941 kfree_skb(pi->sdu);
2942 break;
2943 }
2944
2945 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002946 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002947
2948drop:
2949 kfree_skb(pi->sdu);
2950 pi->sdu = NULL;
2951
2952disconnect:
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002953 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002954 kfree_skb(skb);
2955 return 0;
2956}
2957
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002958static int l2cap_try_push_rx_skb(struct sock *sk)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002959{
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002960 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002961 struct sk_buff *skb;
2962 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002963 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002964
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002965 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
2966 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
2967 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
2968 if (err < 0) {
2969 skb_queue_head(BUSY_QUEUE(sk), skb);
2970 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002971 }
2972
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002973 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002974 }
2975
2976 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
2977 goto done;
2978
2979 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2980 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
2981 l2cap_send_sframe(pi, control);
2982 l2cap_pi(sk)->retry_count = 1;
2983
2984 del_timer(&pi->retrans_timer);
2985 __mod_monitor_timer();
2986
2987 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
2988
2989done:
2990 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2991 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
2992
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002993 BT_DBG("sk %p, Exit local busy", sk);
2994
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002995 return 0;
2996}
2997
2998static void l2cap_busy_work(struct work_struct *work)
2999{
3000 DECLARE_WAITQUEUE(wait, current);
3001 struct l2cap_pinfo *pi =
3002 container_of(work, struct l2cap_pinfo, busy_work);
3003 struct sock *sk = (struct sock *)pi;
3004 int n_tries = 0, timeo = HZ/5, err;
3005 struct sk_buff *skb;
3006
3007 lock_sock(sk);
3008
3009 add_wait_queue(sk_sleep(sk), &wait);
3010 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
3011 set_current_state(TASK_INTERRUPTIBLE);
3012
3013 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3014 err = -EBUSY;
3015 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
3016 break;
3017 }
3018
3019 if (!timeo)
3020 timeo = HZ/5;
3021
3022 if (signal_pending(current)) {
3023 err = sock_intr_errno(timeo);
3024 break;
3025 }
3026
3027 release_sock(sk);
3028 timeo = schedule_timeout(timeo);
3029 lock_sock(sk);
3030
3031 err = sock_error(sk);
3032 if (err)
3033 break;
3034
3035 if (l2cap_try_push_rx_skb(sk) == 0)
3036 break;
3037 }
3038
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003039 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003040 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003041
3042 release_sock(sk);
3043}
3044
3045static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
3046{
3047 struct l2cap_pinfo *pi = l2cap_pi(sk);
3048 int sctrl, err;
3049
3050 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
3051 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3052 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003053 return l2cap_try_push_rx_skb(sk);
3054
3055
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003056 }
3057
3058 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3059 if (err >= 0) {
3060 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3061 return err;
3062 }
3063
3064 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003065 BT_DBG("sk %p, Enter local busy", sk);
3066
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003067 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
3068 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3069 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3070
3071 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3072 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
3073 l2cap_send_sframe(pi, sctrl);
3074
3075 pi->conn_state |= L2CAP_CONN_RNR_SENT;
3076
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003077 del_timer(&pi->ack_timer);
3078
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003079 queue_work(_busy_wq, &pi->busy_work);
3080
3081 return err;
3082}
3083
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003084static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003085{
3086 struct l2cap_pinfo *pi = l2cap_pi(sk);
3087 struct sk_buff *_skb;
3088 int err = -EINVAL;
3089
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003090 /*
3091 * TODO: We have to notify the userland if some data is lost with the
3092 * Streaming Mode.
3093 */
3094
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003095 switch (control & L2CAP_CTRL_SAR) {
3096 case L2CAP_SDU_UNSEGMENTED:
3097 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3098 kfree_skb(pi->sdu);
3099 break;
3100 }
3101
3102 err = sock_queue_rcv_skb(sk, skb);
3103 if (!err)
3104 return 0;
3105
3106 break;
3107
3108 case L2CAP_SDU_START:
3109 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3110 kfree_skb(pi->sdu);
3111 break;
3112 }
3113
3114 pi->sdu_len = get_unaligned_le16(skb->data);
3115 skb_pull(skb, 2);
3116
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003117 if (pi->sdu_len > pi->imtu) {
3118 err = -EMSGSIZE;
3119 break;
3120 }
3121
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003122 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3123 if (!pi->sdu) {
3124 err = -ENOMEM;
3125 break;
3126 }
3127
3128 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3129
3130 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3131 pi->partial_sdu_len = skb->len;
3132 err = 0;
3133 break;
3134
3135 case L2CAP_SDU_CONTINUE:
3136 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3137 break;
3138
3139 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3140
3141 pi->partial_sdu_len += skb->len;
3142 if (pi->partial_sdu_len > pi->sdu_len)
3143 kfree_skb(pi->sdu);
3144 else
3145 err = 0;
3146
3147 break;
3148
3149 case L2CAP_SDU_END:
3150 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3151 break;
3152
3153 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3154
3155 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
3156 pi->partial_sdu_len += skb->len;
3157
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003158 if (pi->partial_sdu_len > pi->imtu)
3159 goto drop;
3160
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003161 if (pi->partial_sdu_len == pi->sdu_len) {
3162 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
3163 err = sock_queue_rcv_skb(sk, _skb);
3164 if (err < 0)
3165 kfree_skb(_skb);
3166 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003167 err = 0;
3168
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003169drop:
3170 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003171 break;
3172 }
3173
3174 kfree_skb(skb);
3175 return err;
3176}
3177
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003178static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
3179{
3180 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003181 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003182
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003183 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003184 if (bt_cb(skb)->tx_seq != tx_seq)
3185 break;
3186
3187 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003188 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003189 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003190 l2cap_pi(sk)->buffer_seq_srej =
3191 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003192 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003193 }
3194}
3195
3196static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
3197{
3198 struct l2cap_pinfo *pi = l2cap_pi(sk);
3199 struct srej_list *l, *tmp;
3200 u16 control;
3201
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003202 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003203 if (l->tx_seq == tx_seq) {
3204 list_del(&l->list);
3205 kfree(l);
3206 return;
3207 }
3208 control = L2CAP_SUPER_SELECT_REJECT;
3209 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3210 l2cap_send_sframe(pi, control);
3211 list_del(&l->list);
3212 list_add_tail(&l->list, SREJ_LIST(sk));
3213 }
3214}
3215
3216static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3217{
3218 struct l2cap_pinfo *pi = l2cap_pi(sk);
3219 struct srej_list *new;
3220 u16 control;
3221
3222 while (tx_seq != pi->expected_tx_seq) {
3223 control = L2CAP_SUPER_SELECT_REJECT;
3224 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3225 l2cap_send_sframe(pi, control);
3226
3227 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003228 new->tx_seq = pi->expected_tx_seq;
3229 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003230 list_add_tail(&new->list, SREJ_LIST(sk));
3231 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003232 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003233}
3234
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003235static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3236{
3237 struct l2cap_pinfo *pi = l2cap_pi(sk);
3238 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003239 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003240 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003241 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003242 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003243 int err = 0;
3244
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003245 BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
3246 rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003247
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003248 if (L2CAP_CTRL_FINAL & rx_control &&
3249 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003250 del_timer(&pi->monitor_timer);
3251 if (pi->unacked_frames > 0)
3252 __mod_retrans_timer();
3253 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
3254 }
3255
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003256 pi->expected_ack_seq = req_seq;
3257 l2cap_drop_acked_frames(sk);
3258
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003259 if (tx_seq == pi->expected_tx_seq)
3260 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003261
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003262 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3263 if (tx_seq_offset < 0)
3264 tx_seq_offset += 64;
3265
3266 /* invalid tx_seq */
3267 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003268 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003269 goto drop;
3270 }
3271
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003272 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
3273 goto drop;
3274
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003275 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3276 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003277
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003278 first = list_first_entry(SREJ_LIST(sk),
3279 struct srej_list, list);
3280 if (tx_seq == first->tx_seq) {
3281 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3282 l2cap_check_srej_gap(sk, tx_seq);
3283
3284 list_del(&first->list);
3285 kfree(first);
3286
3287 if (list_empty(SREJ_LIST(sk))) {
3288 pi->buffer_seq = pi->buffer_seq_srej;
3289 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666cc2010-05-01 16:15:40 -03003290 l2cap_send_ack(pi);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003291 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003292 }
3293 } else {
3294 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003295
3296 /* duplicated tx_seq */
3297 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
3298 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003299
3300 list_for_each_entry(l, SREJ_LIST(sk), list) {
3301 if (l->tx_seq == tx_seq) {
3302 l2cap_resend_srejframe(sk, tx_seq);
3303 return 0;
3304 }
3305 }
3306 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003307 }
3308 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003309 expected_tx_seq_offset =
3310 (pi->expected_tx_seq - pi->buffer_seq) % 64;
3311 if (expected_tx_seq_offset < 0)
3312 expected_tx_seq_offset += 64;
3313
3314 /* duplicated tx_seq */
3315 if (tx_seq_offset < expected_tx_seq_offset)
3316 goto drop;
3317
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003318 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003319
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003320 BT_DBG("sk %p, Enter SREJ", sk);
3321
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003322 INIT_LIST_HEAD(SREJ_LIST(sk));
3323 pi->buffer_seq_srej = pi->buffer_seq;
3324
3325 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003326 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003327 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3328
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003329 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
3330
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003331 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003332
3333 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003334 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003335 return 0;
3336
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003337expected:
3338 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3339
3340 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003341 bt_cb(skb)->tx_seq = tx_seq;
3342 bt_cb(skb)->sar = sar;
3343 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003344 return 0;
3345 }
3346
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003347 err = l2cap_push_rx_skb(sk, skb, rx_control);
3348 if (err < 0)
3349 return 0;
3350
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003351 if (rx_control & L2CAP_CTRL_FINAL) {
3352 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3353 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003354 else
3355 l2cap_retransmit_frames(sk);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003356 }
3357
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003358 __mod_ack_timer();
3359
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003360 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
3361 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003362 l2cap_send_ack(pi);
3363
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003364 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003365
3366drop:
3367 kfree_skb(skb);
3368 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003369}
3370
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003371static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003372{
3373 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003374
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003375 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3376 rx_control);
3377
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003378 pi->expected_ack_seq = __get_reqseq(rx_control);
3379 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003380
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003381 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003382 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003383 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3384 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3385 (pi->unacked_frames > 0))
3386 __mod_retrans_timer();
3387
3388 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3389 l2cap_send_srejtail(sk);
3390 } else {
3391 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003392 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003393
3394 } else if (rx_control & L2CAP_CTRL_FINAL) {
3395 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003396
3397 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3398 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003399 else
3400 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003401
3402 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003403 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3404 (pi->unacked_frames > 0))
3405 __mod_retrans_timer();
3406
3407 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003408 if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003409 l2cap_send_ack(pi);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003410 else
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003411 l2cap_ertm_send(sk);
3412 }
3413}
3414
3415static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
3416{
3417 struct l2cap_pinfo *pi = l2cap_pi(sk);
3418 u8 tx_seq = __get_reqseq(rx_control);
3419
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003420 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3421
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003422 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3423
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03003424 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003425 l2cap_drop_acked_frames(sk);
3426
3427 if (rx_control & L2CAP_CTRL_FINAL) {
3428 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3429 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003430 else
3431 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003432 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003433 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003434
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03003435 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003436 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003437 }
3438}
3439static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
3440{
3441 struct l2cap_pinfo *pi = l2cap_pi(sk);
3442 u8 tx_seq = __get_reqseq(rx_control);
3443
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003444 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3445
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003446 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3447
3448 if (rx_control & L2CAP_CTRL_POLL) {
3449 pi->expected_ack_seq = tx_seq;
3450 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003451
3452 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003453 l2cap_retransmit_one_frame(sk, tx_seq);
3454
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003455 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003456
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003457 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3458 pi->srej_save_reqseq = tx_seq;
3459 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3460 }
3461 } else if (rx_control & L2CAP_CTRL_FINAL) {
3462 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
3463 pi->srej_save_reqseq == tx_seq)
3464 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
3465 else
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003466 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003467 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003468 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003469 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3470 pi->srej_save_reqseq = tx_seq;
3471 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3472 }
3473 }
3474}
3475
3476static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
3477{
3478 struct l2cap_pinfo *pi = l2cap_pi(sk);
3479 u8 tx_seq = __get_reqseq(rx_control);
3480
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003481 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3482
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003483 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
3484 pi->expected_ack_seq = tx_seq;
3485 l2cap_drop_acked_frames(sk);
3486
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003487 if (rx_control & L2CAP_CTRL_POLL)
3488 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
3489
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003490 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
3491 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003492 if (rx_control & L2CAP_CTRL_POLL)
3493 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003494 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003495 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003496
3497 if (rx_control & L2CAP_CTRL_POLL)
3498 l2cap_send_srejtail(sk);
3499 else
3500 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003501}
3502
3503static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3504{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003505 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3506
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003507 if (L2CAP_CTRL_FINAL & rx_control &&
3508 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003509 del_timer(&l2cap_pi(sk)->monitor_timer);
3510 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003511 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003512 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003513 }
3514
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003515 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3516 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003517 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003518 break;
3519
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003520 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003521 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003522 break;
3523
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003524 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003525 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003526 break;
3527
3528 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003529 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003530 break;
3531 }
3532
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003533 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003534 return 0;
3535}
3536
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003537static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3538{
3539 struct l2cap_pinfo *pi = l2cap_pi(sk);
3540 u16 control;
3541 u8 req_seq;
3542 int len, next_tx_seq_offset, req_seq_offset;
3543
3544 control = get_unaligned_le16(skb->data);
3545 skb_pull(skb, 2);
3546 len = skb->len;
3547
3548 /*
3549 * We can just drop the corrupted I-frame here.
3550 * Receiver will miss it and start proper recovery
3551 * procedures and ask retransmission.
3552 */
3553 if (l2cap_check_fcs(pi, skb))
3554 goto drop;
3555
3556 if (__is_sar_start(control) && __is_iframe(control))
3557 len -= 2;
3558
3559 if (pi->fcs == L2CAP_FCS_CRC16)
3560 len -= 2;
3561
3562 if (len > pi->mps) {
3563 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3564 goto drop;
3565 }
3566
3567 req_seq = __get_reqseq(control);
3568 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
3569 if (req_seq_offset < 0)
3570 req_seq_offset += 64;
3571
3572 next_tx_seq_offset =
3573 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
3574 if (next_tx_seq_offset < 0)
3575 next_tx_seq_offset += 64;
3576
3577 /* check for invalid req-seq */
3578 if (req_seq_offset > next_tx_seq_offset) {
3579 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3580 goto drop;
3581 }
3582
3583 if (__is_iframe(control)) {
3584 if (len < 0) {
3585 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3586 goto drop;
3587 }
3588
3589 l2cap_data_channel_iframe(sk, control, skb);
3590 } else {
3591 if (len != 0) {
3592 BT_ERR("%d", len);
3593 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3594 goto drop;
3595 }
3596
3597 l2cap_data_channel_sframe(sk, control, skb);
3598 }
3599
3600 return 0;
3601
3602drop:
3603 kfree_skb(skb);
3604 return 0;
3605}
3606
Linus Torvalds1da177e2005-04-16 15:20:36 -07003607static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3608{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003609 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003610 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003611 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003612 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003613 u8 tx_seq;
3614 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003616 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003617 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618 BT_DBG("unknown cid 0x%4.4x", cid);
3619 goto drop;
3620 }
3621
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003622 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003623 pi = l2cap_pi(sk);
3624
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625 BT_DBG("sk %p, len %d", sk, skb->len);
3626
3627 if (sk->sk_state != BT_CONNECTED)
3628 goto drop;
3629
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003630 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003631 case L2CAP_MODE_BASIC:
3632 /* If socket recv buffers overflows we drop data here
3633 * which is *bad* because L2CAP has to be reliable.
3634 * But we don't have any other choice. L2CAP doesn't
3635 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003637 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003638 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003640 if (!sock_queue_rcv_skb(sk, skb))
3641 goto done;
3642 break;
3643
3644 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003645 if (!sock_owned_by_user(sk)) {
3646 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003647 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003648 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003649 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003650 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003651
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003652 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003653
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003654 case L2CAP_MODE_STREAMING:
3655 control = get_unaligned_le16(skb->data);
3656 skb_pull(skb, 2);
3657 len = skb->len;
3658
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003659 if (l2cap_check_fcs(pi, skb))
3660 goto drop;
3661
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003662 if (__is_sar_start(control))
3663 len -= 2;
3664
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003665 if (pi->fcs == L2CAP_FCS_CRC16)
3666 len -= 2;
3667
Nathan Holstein51893f82010-06-09 15:46:25 -04003668 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003669 goto drop;
3670
3671 tx_seq = __get_txseq(control);
3672
3673 if (pi->expected_tx_seq == tx_seq)
3674 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3675 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03003676 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003677
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003678 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003679
3680 goto done;
3681
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003682 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003683 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003684 break;
3685 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686
3687drop:
3688 kfree_skb(skb);
3689
3690done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003691 if (sk)
3692 bh_unlock_sock(sk);
3693
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694 return 0;
3695}
3696
Al Viro8e036fc2007-07-29 00:16:36 -07003697static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698{
3699 struct sock *sk;
3700
3701 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3702 if (!sk)
3703 goto drop;
3704
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003705 bh_lock_sock(sk);
3706
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707 BT_DBG("sk %p, len %d", sk, skb->len);
3708
3709 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3710 goto drop;
3711
3712 if (l2cap_pi(sk)->imtu < skb->len)
3713 goto drop;
3714
3715 if (!sock_queue_rcv_skb(sk, skb))
3716 goto done;
3717
3718drop:
3719 kfree_skb(skb);
3720
3721done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003722 if (sk)
3723 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724 return 0;
3725}
3726
3727static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3728{
3729 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003730 u16 cid, len;
3731 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003732
3733 skb_pull(skb, L2CAP_HDR_SIZE);
3734 cid = __le16_to_cpu(lh->cid);
3735 len = __le16_to_cpu(lh->len);
3736
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003737 if (len != skb->len) {
3738 kfree_skb(skb);
3739 return;
3740 }
3741
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3743
3744 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003745 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003746 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747 l2cap_sig_channel(conn, skb);
3748 break;
3749
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003750 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003751 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003752 skb_pull(skb, 2);
3753 l2cap_conless_channel(conn, psm, skb);
3754 break;
3755
3756 default:
3757 l2cap_data_channel(conn, cid, skb);
3758 break;
3759 }
3760}
3761
3762/* ---- L2CAP interface with lower layer (HCI) ---- */
3763
3764static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3765{
3766 int exact = 0, lm1 = 0, lm2 = 0;
3767 register struct sock *sk;
3768 struct hlist_node *node;
3769
3770 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003771 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772
3773 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3774
3775 /* Find listening sockets and check their link_mode */
3776 read_lock(&l2cap_sk_list.lock);
3777 sk_for_each(sk, node, &l2cap_sk_list.head) {
3778 if (sk->sk_state != BT_LISTEN)
3779 continue;
3780
3781 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003782 lm1 |= HCI_LM_ACCEPT;
3783 if (l2cap_pi(sk)->role_switch)
3784 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003786 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3787 lm2 |= HCI_LM_ACCEPT;
3788 if (l2cap_pi(sk)->role_switch)
3789 lm2 |= HCI_LM_MASTER;
3790 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791 }
3792 read_unlock(&l2cap_sk_list.lock);
3793
3794 return exact ? lm1 : lm2;
3795}
3796
3797static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3798{
Marcel Holtmann01394182006-07-03 10:02:46 +02003799 struct l2cap_conn *conn;
3800
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3802
Ville Tervoacd7d372011-02-10 22:38:49 -03003803 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003804 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003805
3806 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807 conn = l2cap_conn_add(hcon, status);
3808 if (conn)
3809 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003810 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003811 l2cap_conn_del(hcon, bt_err(status));
3812
3813 return 0;
3814}
3815
Marcel Holtmann2950f212009-02-12 14:02:50 +01003816static int l2cap_disconn_ind(struct hci_conn *hcon)
3817{
3818 struct l2cap_conn *conn = hcon->l2cap_data;
3819
3820 BT_DBG("hcon %p", hcon);
3821
3822 if (hcon->type != ACL_LINK || !conn)
3823 return 0x13;
3824
3825 return conn->disc_reason;
3826}
3827
3828static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003829{
3830 BT_DBG("hcon %p reason %d", hcon, reason);
3831
Ville Tervoacd7d372011-02-10 22:38:49 -03003832 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003833 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003834
3835 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003836
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837 return 0;
3838}
3839
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003840static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3841{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003842 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003843 return;
3844
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003845 if (encrypt == 0x00) {
3846 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3847 l2cap_sock_clear_timer(sk);
3848 l2cap_sock_set_timer(sk, HZ * 5);
3849 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3850 __l2cap_sock_close(sk, ECONNREFUSED);
3851 } else {
3852 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3853 l2cap_sock_clear_timer(sk);
3854 }
3855}
3856
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003857static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003859 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003860 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861
Marcel Holtmann01394182006-07-03 10:02:46 +02003862 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003864
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865 BT_DBG("conn %p", conn);
3866
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003867 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003869 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003870 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003871
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872 bh_lock_sock(sk);
3873
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003874 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3875 bh_unlock_sock(sk);
3876 continue;
3877 }
3878
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003879 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003880 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003881 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003882 bh_unlock_sock(sk);
3883 continue;
3884 }
3885
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003886 if (sk->sk_state == BT_CONNECT) {
3887 if (!status) {
3888 struct l2cap_conn_req req;
3889 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3890 req.psm = l2cap_pi(sk)->psm;
3891
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003892 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003893 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003894
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003895 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003896 L2CAP_CONN_REQ, sizeof(req), &req);
3897 } else {
3898 l2cap_sock_clear_timer(sk);
3899 l2cap_sock_set_timer(sk, HZ / 10);
3900 }
3901 } else if (sk->sk_state == BT_CONNECT2) {
3902 struct l2cap_conn_rsp rsp;
3903 __u16 result;
3904
3905 if (!status) {
3906 sk->sk_state = BT_CONFIG;
3907 result = L2CAP_CR_SUCCESS;
3908 } else {
3909 sk->sk_state = BT_DISCONN;
3910 l2cap_sock_set_timer(sk, HZ / 10);
3911 result = L2CAP_CR_SEC_BLOCK;
3912 }
3913
3914 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3915 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3916 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003917 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003918 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
3919 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920 }
3921
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922 bh_unlock_sock(sk);
3923 }
3924
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003925 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003926
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927 return 0;
3928}
3929
3930static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3931{
3932 struct l2cap_conn *conn = hcon->l2cap_data;
3933
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003934 if (!conn)
3935 conn = l2cap_conn_add(hcon, 0);
3936
3937 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938 goto drop;
3939
3940 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3941
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003942 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003944 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003945 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 int len;
3947
3948 if (conn->rx_len) {
3949 BT_ERR("Unexpected start frame (len %d)", skb->len);
3950 kfree_skb(conn->rx_skb);
3951 conn->rx_skb = NULL;
3952 conn->rx_len = 0;
3953 l2cap_conn_unreliable(conn, ECOMM);
3954 }
3955
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003956 /* Start fragment always begin with Basic L2CAP header */
3957 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 BT_ERR("Frame is too short (len %d)", skb->len);
3959 l2cap_conn_unreliable(conn, ECOMM);
3960 goto drop;
3961 }
3962
3963 hdr = (struct l2cap_hdr *) skb->data;
3964 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003965 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966
3967 if (len == skb->len) {
3968 /* Complete frame received */
3969 l2cap_recv_frame(conn, skb);
3970 return 0;
3971 }
3972
3973 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3974
3975 if (skb->len > len) {
3976 BT_ERR("Frame is too long (len %d, expected len %d)",
3977 skb->len, len);
3978 l2cap_conn_unreliable(conn, ECOMM);
3979 goto drop;
3980 }
3981
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003982 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003983
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003984 if (chan && chan->sk) {
3985 struct sock *sk = chan->sk;
3986
3987 if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
3988 BT_ERR("Frame exceeding recv MTU (len %d, "
3989 "MTU %d)", len,
3990 l2cap_pi(sk)->imtu);
3991 bh_unlock_sock(sk);
3992 l2cap_conn_unreliable(conn, ECOMM);
3993 goto drop;
3994 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003995 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003996 }
3997
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003999 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4000 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004001 goto drop;
4002
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004003 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004004 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004005 conn->rx_len = len - skb->len;
4006 } else {
4007 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4008
4009 if (!conn->rx_len) {
4010 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4011 l2cap_conn_unreliable(conn, ECOMM);
4012 goto drop;
4013 }
4014
4015 if (skb->len > conn->rx_len) {
4016 BT_ERR("Fragment is too long (len %d, expected %d)",
4017 skb->len, conn->rx_len);
4018 kfree_skb(conn->rx_skb);
4019 conn->rx_skb = NULL;
4020 conn->rx_len = 0;
4021 l2cap_conn_unreliable(conn, ECOMM);
4022 goto drop;
4023 }
4024
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004025 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004026 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027 conn->rx_len -= skb->len;
4028
4029 if (!conn->rx_len) {
4030 /* Complete frame received */
4031 l2cap_recv_frame(conn, conn->rx_skb);
4032 conn->rx_skb = NULL;
4033 }
4034 }
4035
4036drop:
4037 kfree_skb(skb);
4038 return 0;
4039}
4040
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004041static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042{
4043 struct sock *sk;
4044 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045
4046 read_lock_bh(&l2cap_sk_list.lock);
4047
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004048 sk_for_each(sk, node, &l2cap_sk_list.head) {
4049 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004050
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004051 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 +01004052 batostr(&bt_sk(sk)->src),
4053 batostr(&bt_sk(sk)->dst),
4054 sk->sk_state, __le16_to_cpu(pi->psm),
4055 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004056 pi->imtu, pi->omtu, pi->sec_level,
4057 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004058 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004059
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004061
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004062 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063}
4064
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004065static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4066{
4067 return single_open(file, l2cap_debugfs_show, inode->i_private);
4068}
4069
4070static const struct file_operations l2cap_debugfs_fops = {
4071 .open = l2cap_debugfs_open,
4072 .read = seq_read,
4073 .llseek = seq_lseek,
4074 .release = single_release,
4075};
4076
4077static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079static struct hci_proto l2cap_hci_proto = {
4080 .name = "L2CAP",
4081 .id = HCI_PROTO_L2CAP,
4082 .connect_ind = l2cap_connect_ind,
4083 .connect_cfm = l2cap_connect_cfm,
4084 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004085 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004086 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087 .recv_acldata = l2cap_recv_acldata
4088};
4089
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004090int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091{
4092 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004093
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004094 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095 if (err < 0)
4096 return err;
4097
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004098 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004099 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004100 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101 goto error;
4102 }
4103
4104 err = hci_register_proto(&l2cap_hci_proto);
4105 if (err < 0) {
4106 BT_ERR("L2CAP protocol registration failed");
4107 bt_sock_unregister(BTPROTO_L2CAP);
4108 goto error;
4109 }
4110
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004111 if (bt_debugfs) {
4112 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4113 bt_debugfs, NULL, &l2cap_debugfs_fops);
4114 if (!l2cap_debugfs)
4115 BT_ERR("Failed to create L2CAP debug file");
4116 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118 return 0;
4119
4120error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004121 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004122 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123 return err;
4124}
4125
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004126void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004128 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004130 flush_workqueue(_busy_wq);
4131 destroy_workqueue(_busy_wq);
4132
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4134 BT_ERR("L2CAP protocol unregistration failed");
4135
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004136 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137}
4138
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004139module_param(disable_ertm, bool, 0644);
4140MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");