blob: 06c505b1476d8720a38dc398d59b7168b11776c5 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
7 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation;
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
16 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090017 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090022 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
23 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 SOFTWARE IS DISCLAIMED.
25*/
26
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020027/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30
31#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080032#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
34#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/poll.h>
38#include <linux/fcntl.h>
39#include <linux/init.h>
40#include <linux/interrupt.h>
41#include <linux/socket.h>
42#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080044#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010045#include <linux/debugfs.h>
46#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030047#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030048#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/sock.h>
50
51#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
57
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020058int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020059
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070060static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010061static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030063static struct workqueue_struct *_busy_wq;
64
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020065struct bt_sock_list l2cap_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070066 .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070067};
68
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030069static void l2cap_busy_work(struct work_struct *work);
70
Linus Torvalds1da177e2005-04-16 15:20:36 -070071static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
72 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030073static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030075static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
76
Marcel Holtmann01394182006-07-03 10:02:46 +020077/* ---- L2CAP channels ---- */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030078static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020079{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030080 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030081
82 list_for_each_entry(c, &conn->chan_l, list) {
83 struct sock *s = c->sk;
84 if (l2cap_pi(s)->dcid == cid)
85 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020086 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030087 return NULL;
88
Marcel Holtmann01394182006-07-03 10:02:46 +020089}
90
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030091static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020092{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030093 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030094
95 list_for_each_entry(c, &conn->chan_l, list) {
96 struct sock *s = c->sk;
97 if (l2cap_pi(s)->scid == cid)
98 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020099 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300100 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200101}
102
103/* Find channel with given SCID.
104 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300105static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200106{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300107 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300108
109 read_lock(&conn->chan_lock);
110 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300111 if (c)
112 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300113 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300114 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200115}
116
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300117static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200118{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300119 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300120
121 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300122 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300123 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200124 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300125 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200126}
127
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300128static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200129{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300130 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300131
132 read_lock(&conn->chan_lock);
133 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300134 if (c)
135 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300136 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300137 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200138}
139
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300140static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200141{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300142 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200143
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300144 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300145 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200146 return cid;
147 }
148
149 return 0;
150}
151
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300152static struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200153{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300154 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200155
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300156 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
157 if (!chan)
158 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200159
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300160 chan->sk = sk;
161
162 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200163}
164
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300165static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200166{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300167 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200168
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300169 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
170 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200171
Marcel Holtmann2950f212009-02-12 14:02:50 +0100172 conn->disc_reason = 0x13;
173
Marcel Holtmann01394182006-07-03 10:02:46 +0200174 l2cap_pi(sk)->conn = conn;
175
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300176 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Ville Tervob62f3282011-02-10 22:38:50 -0300177 if (conn->hcon->type == LE_LINK) {
178 /* LE connection */
179 l2cap_pi(sk)->omtu = L2CAP_LE_DEFAULT_MTU;
180 l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA;
181 l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA;
182 } else {
183 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300184 l2cap_pi(sk)->scid = l2cap_alloc_cid(conn);
Ville Tervob62f3282011-02-10 22:38:50 -0300185 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
186 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200187 } else if (sk->sk_type == SOCK_DGRAM) {
188 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300189 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
190 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200191 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
192 } else {
193 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300194 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
195 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200196 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
197 }
198
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300199 sock_hold(sk);
200
201 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200202}
203
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900204/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200205 * Must be called on the locked socket. */
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300206void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200207{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300208 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200209 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
210 struct sock *parent = bt_sk(sk)->parent;
211
212 l2cap_sock_clear_timer(sk);
213
214 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
215
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900216 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300217 /* Delete from channel list */
218 write_lock_bh(&conn->chan_lock);
219 list_del(&chan->list);
220 write_unlock_bh(&conn->chan_lock);
221 __sock_put(sk);
222
Marcel Holtmann01394182006-07-03 10:02:46 +0200223 l2cap_pi(sk)->conn = NULL;
224 hci_conn_put(conn->hcon);
225 }
226
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200227 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200228 sock_set_flag(sk, SOCK_ZAPPED);
229
230 if (err)
231 sk->sk_err = err;
232
233 if (parent) {
234 bt_accept_unlink(sk);
235 parent->sk_data_ready(parent, 0);
236 } else
237 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300238
239 skb_queue_purge(TX_QUEUE(sk));
240
241 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
242 struct srej_list *l, *tmp;
243
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300244 del_timer(&chan->retrans_timer);
245 del_timer(&chan->monitor_timer);
246 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300247
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300248 skb_queue_purge(&chan->srej_q);
249 skb_queue_purge(&chan->busy_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300250
251 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
252 list_del(&l->list);
253 kfree(l);
254 }
255 }
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300256
257 kfree(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200258}
259
Johan Hedberg8556edd32011-01-19 12:06:50 +0530260static inline u8 l2cap_get_auth_type(struct sock *sk)
261{
262 if (sk->sk_type == SOCK_RAW) {
263 switch (l2cap_pi(sk)->sec_level) {
264 case BT_SECURITY_HIGH:
265 return HCI_AT_DEDICATED_BONDING_MITM;
266 case BT_SECURITY_MEDIUM:
267 return HCI_AT_DEDICATED_BONDING;
268 default:
269 return HCI_AT_NO_BONDING;
270 }
271 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
272 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
273 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
274
275 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
276 return HCI_AT_NO_BONDING_MITM;
277 else
278 return HCI_AT_NO_BONDING;
279 } else {
280 switch (l2cap_pi(sk)->sec_level) {
281 case BT_SECURITY_HIGH:
282 return HCI_AT_GENERAL_BONDING_MITM;
283 case BT_SECURITY_MEDIUM:
284 return HCI_AT_GENERAL_BONDING;
285 default:
286 return HCI_AT_NO_BONDING;
287 }
288 }
289}
290
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200291/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100292static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200293{
294 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100295 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200296
Johan Hedberg8556edd32011-01-19 12:06:50 +0530297 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100298
299 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
300 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200301}
302
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200303u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200304{
305 u8 id;
306
307 /* Get next available identificator.
308 * 1 - 128 are used by kernel.
309 * 129 - 199 are reserved.
310 * 200 - 254 are used by utilities like l2ping, etc.
311 */
312
313 spin_lock_bh(&conn->lock);
314
315 if (++conn->tx_ident > 128)
316 conn->tx_ident = 1;
317
318 id = conn->tx_ident;
319
320 spin_unlock_bh(&conn->lock);
321
322 return id;
323}
324
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200325void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200326{
327 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200328 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200329
330 BT_DBG("code 0x%2.2x", code);
331
332 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300333 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200334
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200335 if (lmp_no_flush_capable(conn->hcon->hdev))
336 flags = ACL_START_NO_FLUSH;
337 else
338 flags = ACL_START;
339
340 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200341}
342
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300343static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300344{
345 struct sk_buff *skb;
346 struct l2cap_hdr *lh;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300347 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300348 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300349 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300350 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200351 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300352
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300353 if (sk->sk_state != BT_CONNECTED)
354 return;
355
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300356 if (pi->fcs == L2CAP_FCS_CRC16)
357 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300358
359 BT_DBG("pi %p, control 0x%2.2x", pi, control);
360
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300361 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300362 control |= L2CAP_CTRL_FRAME_TYPE;
363
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300364 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300365 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300366 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300367 }
368
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300369 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300370 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300371 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300372 }
373
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300374 skb = bt_skb_alloc(count, GFP_ATOMIC);
375 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300376 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300377
378 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300379 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300380 lh->cid = cpu_to_le16(pi->dcid);
381 put_unaligned_le16(control, skb_put(skb, 2));
382
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300383 if (pi->fcs == L2CAP_FCS_CRC16) {
384 u16 fcs = crc16(0, (u8 *)lh, count - 2);
385 put_unaligned_le16(fcs, skb_put(skb, 2));
386 }
387
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200388 if (lmp_no_flush_capable(conn->hcon->hdev))
389 flags = ACL_START_NO_FLUSH;
390 else
391 flags = ACL_START;
392
393 hci_send_acl(pi->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300394}
395
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300396static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300397{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300398 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300399 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300400 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300401 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300402 control |= L2CAP_SUPER_RCV_READY;
403
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300404 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300405
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300406 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300407}
408
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300409static inline int __l2cap_no_conn_pending(struct sock *sk)
410{
411 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
412}
413
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300414static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200415{
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300416 struct sock *sk = chan->sk;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200417 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
418
419 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100420 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
421 return;
422
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300423 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200424 struct l2cap_conn_req req;
425 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
426 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200427
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300428 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300429 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200430
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300431 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
432 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200433 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200434 } else {
435 struct l2cap_info_req req;
436 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
437
438 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
439 conn->info_ident = l2cap_get_ident(conn);
440
441 mod_timer(&conn->info_timer, jiffies +
442 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
443
444 l2cap_send_cmd(conn, conn->info_ident,
445 L2CAP_INFO_REQ, sizeof(req), &req);
446 }
447}
448
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300449static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
450{
451 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300452 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300453 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
454
455 switch (mode) {
456 case L2CAP_MODE_ERTM:
457 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
458 case L2CAP_MODE_STREAMING:
459 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
460 default:
461 return 0x00;
462 }
463}
464
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300465void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300466{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300467 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300468 struct l2cap_disconn_req req;
469
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300470 if (!conn)
471 return;
472
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300473 sk = chan->sk;
474
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300475 skb_queue_purge(TX_QUEUE(sk));
476
477 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300478 del_timer(&chan->retrans_timer);
479 del_timer(&chan->monitor_timer);
480 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300481 }
482
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300483 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
484 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
485 l2cap_send_cmd(conn, l2cap_get_ident(conn),
486 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300487
488 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300489 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300490}
491
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200493static void l2cap_conn_start(struct l2cap_conn *conn)
494{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300495 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200496
497 BT_DBG("conn %p", conn);
498
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300499 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200500
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300501 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300502 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300503
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200504 bh_lock_sock(sk);
505
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300506 if (sk->sk_type != SOCK_SEQPACKET &&
507 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200508 bh_unlock_sock(sk);
509 continue;
510 }
511
512 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300513 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300514
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300515 if (!l2cap_check_security(sk) ||
516 !__l2cap_no_conn_pending(sk)) {
517 bh_unlock_sock(sk);
518 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200519 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300520
521 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
522 conn->feat_mask)
523 && l2cap_pi(sk)->conf_state &
524 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300525 /* __l2cap_sock_close() calls list_del(chan)
526 * so release the lock */
527 read_unlock_bh(&conn->chan_lock);
528 __l2cap_sock_close(sk, ECONNRESET);
529 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300530 bh_unlock_sock(sk);
531 continue;
532 }
533
534 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
535 req.psm = l2cap_pi(sk)->psm;
536
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300537 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300538 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
539
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300540 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
541 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300542
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200543 } else if (sk->sk_state == BT_CONNECT2) {
544 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300545 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200546 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
547 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
548
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100549 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100550 if (bt_sk(sk)->defer_setup) {
551 struct sock *parent = bt_sk(sk)->parent;
552 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
553 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
554 parent->sk_data_ready(parent, 0);
555
556 } else {
557 sk->sk_state = BT_CONFIG;
558 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
559 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
560 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200561 } else {
562 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
563 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
564 }
565
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300566 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
567 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300568
569 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
570 rsp.result != L2CAP_CR_SUCCESS) {
571 bh_unlock_sock(sk);
572 continue;
573 }
574
575 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
576 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300577 l2cap_build_conf_req(chan, buf), buf);
578 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200579 }
580
581 bh_unlock_sock(sk);
582 }
583
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300584 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200585}
586
Ville Tervob62f3282011-02-10 22:38:50 -0300587/* Find socket with cid and source bdaddr.
588 * Returns closest match, locked.
589 */
590static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
591{
592 struct sock *s, *sk = NULL, *sk1 = NULL;
593 struct hlist_node *node;
594
595 read_lock(&l2cap_sk_list.lock);
596
597 sk_for_each(sk, node, &l2cap_sk_list.head) {
598 if (state && sk->sk_state != state)
599 continue;
600
601 if (l2cap_pi(sk)->scid == cid) {
602 /* Exact match. */
603 if (!bacmp(&bt_sk(sk)->src, src))
604 break;
605
606 /* Closest match */
607 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
608 sk1 = sk;
609 }
610 }
611 s = node ? sk : sk1;
612 if (s)
613 bh_lock_sock(s);
614 read_unlock(&l2cap_sk_list.lock);
615
616 return s;
617}
618
619static void l2cap_le_conn_ready(struct l2cap_conn *conn)
620{
Ville Tervob62f3282011-02-10 22:38:50 -0300621 struct sock *parent, *uninitialized_var(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300622 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300623
624 BT_DBG("");
625
626 /* Check if we have socket listening on cid */
627 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
628 conn->src);
629 if (!parent)
630 return;
631
632 /* Check for backlog size */
633 if (sk_acceptq_is_full(parent)) {
634 BT_DBG("backlog full %d", parent->sk_ack_backlog);
635 goto clean;
636 }
637
638 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
639 if (!sk)
640 goto clean;
641
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300642 chan = l2cap_chan_alloc(sk);
643 if (!chan) {
644 l2cap_sock_kill(sk);
645 goto clean;
646 }
647
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300648 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300649
650 hci_conn_hold(conn->hcon);
651
652 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300653
Ville Tervob62f3282011-02-10 22:38:50 -0300654 bacpy(&bt_sk(sk)->src, conn->src);
655 bacpy(&bt_sk(sk)->dst, conn->dst);
656
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300657 bt_accept_enqueue(parent, sk);
658
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300659 __l2cap_chan_add(conn, chan);
660
661 l2cap_pi(sk)->chan = chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300662
663 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
664
665 sk->sk_state = BT_CONNECTED;
666 parent->sk_data_ready(parent, 0);
667
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300668 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300669
670clean:
671 bh_unlock_sock(parent);
672}
673
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200674static void l2cap_conn_ready(struct l2cap_conn *conn)
675{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300676 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200677
678 BT_DBG("conn %p", conn);
679
Ville Tervob62f3282011-02-10 22:38:50 -0300680 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
681 l2cap_le_conn_ready(conn);
682
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300683 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200684
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300685 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300686 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300687
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200688 bh_lock_sock(sk);
689
Ville Tervoacd7d372011-02-10 22:38:49 -0300690 if (conn->hcon->type == LE_LINK) {
691 l2cap_sock_clear_timer(sk);
692 sk->sk_state = BT_CONNECTED;
693 sk->sk_state_change(sk);
694 }
695
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300696 if (sk->sk_type != SOCK_SEQPACKET &&
697 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200698 l2cap_sock_clear_timer(sk);
699 sk->sk_state = BT_CONNECTED;
700 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200701 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300702 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200703
704 bh_unlock_sock(sk);
705 }
706
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300707 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200708}
709
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200710/* Notify sockets that we cannot guaranty reliability anymore */
711static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
712{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300713 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200714
715 BT_DBG("conn %p", conn);
716
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300717 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200718
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300719 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300720 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300721
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100722 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200723 sk->sk_err = err;
724 }
725
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300726 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200727}
728
729static void l2cap_info_timeout(unsigned long arg)
730{
731 struct l2cap_conn *conn = (void *) arg;
732
Marcel Holtmann984947d2009-02-06 23:35:19 +0100733 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100734 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100735
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200736 l2cap_conn_start(conn);
737}
738
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
740{
Marcel Holtmann01394182006-07-03 10:02:46 +0200741 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742
Marcel Holtmann01394182006-07-03 10:02:46 +0200743 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 return conn;
745
Marcel Holtmann01394182006-07-03 10:02:46 +0200746 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
747 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749
750 hcon->l2cap_data = conn;
751 conn->hcon = hcon;
752
Marcel Holtmann01394182006-07-03 10:02:46 +0200753 BT_DBG("hcon %p conn %p", hcon, conn);
754
Ville Tervoacd7d372011-02-10 22:38:49 -0300755 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
756 conn->mtu = hcon->hdev->le_mtu;
757 else
758 conn->mtu = hcon->hdev->acl_mtu;
759
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 conn->src = &hcon->hdev->bdaddr;
761 conn->dst = &hcon->dst;
762
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200763 conn->feat_mask = 0;
764
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300766 rwlock_init(&conn->chan_lock);
767
768 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769
Ville Tervob62f3282011-02-10 22:38:50 -0300770 if (hcon->type != LE_LINK)
771 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000772 (unsigned long) conn);
773
Marcel Holtmann2950f212009-02-12 14:02:50 +0100774 conn->disc_reason = 0x13;
775
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 return conn;
777}
778
Marcel Holtmann01394182006-07-03 10:02:46 +0200779static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780{
Marcel Holtmann01394182006-07-03 10:02:46 +0200781 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300782 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 struct sock *sk;
784
Marcel Holtmann01394182006-07-03 10:02:46 +0200785 if (!conn)
786 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787
788 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
789
Wei Yongjun7585b972009-02-25 18:29:52 +0800790 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
792 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300793 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300794 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300796 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 bh_unlock_sock(sk);
798 l2cap_sock_kill(sk);
799 }
800
Dave Young8e8440f2008-03-03 12:18:55 -0800801 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
802 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800803
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 hcon->l2cap_data = NULL;
805 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806}
807
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300808static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300810 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300811 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300812 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813}
814
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816
817/* Find socket with psm and source bdaddr.
818 * Returns closest match.
819 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000820static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821{
822 struct sock *sk = NULL, *sk1 = NULL;
823 struct hlist_node *node;
824
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000825 read_lock(&l2cap_sk_list.lock);
826
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 sk_for_each(sk, node, &l2cap_sk_list.head) {
828 if (state && sk->sk_state != state)
829 continue;
830
831 if (l2cap_pi(sk)->psm == psm) {
832 /* Exact match. */
833 if (!bacmp(&bt_sk(sk)->src, src))
834 break;
835
836 /* Closest match */
837 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
838 sk1 = sk;
839 }
840 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000843
844 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845}
846
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200847int l2cap_do_connect(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848{
849 bdaddr_t *src = &bt_sk(sk)->src;
850 bdaddr_t *dst = &bt_sk(sk)->dst;
851 struct l2cap_conn *conn;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300852 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 struct hci_conn *hcon;
854 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200855 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200856 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100858 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
859 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300861 hdev = hci_get_route(dst, src);
862 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 return -EHOSTUNREACH;
864
865 hci_dev_lock_bh(hdev);
866
Johan Hedberg8556edd32011-01-19 12:06:50 +0530867 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200868
Ville Tervoacd7d372011-02-10 22:38:49 -0300869 if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
870 hcon = hci_connect(hdev, LE_LINK, dst,
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100871 l2cap_pi(sk)->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300872 else
873 hcon = hci_connect(hdev, ACL_LINK, dst,
874 l2cap_pi(sk)->sec_level, auth_type);
875
Ville Tervo30e76272011-02-22 16:10:53 -0300876 if (IS_ERR(hcon)) {
877 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300879 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880
881 conn = l2cap_conn_add(hcon, 0);
882 if (!conn) {
883 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300884 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 goto done;
886 }
887
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300888 chan = l2cap_chan_alloc(sk);
889 if (!chan) {
890 hci_conn_put(hcon);
891 err = -ENOMEM;
892 goto done;
893 }
894
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 /* Update source addr of the socket */
896 bacpy(src, conn->src);
897
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300898 l2cap_chan_add(conn, chan);
899
900 l2cap_pi(sk)->chan = chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901
902 sk->sk_state = BT_CONNECT;
903 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
904
905 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300906 if (sk->sk_type != SOCK_SEQPACKET &&
907 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530909 if (l2cap_check_security(sk))
910 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200911 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300912 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 }
914
Ville Tervo30e76272011-02-22 16:10:53 -0300915 err = 0;
916
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917done:
918 hci_dev_unlock_bh(hdev);
919 hci_dev_put(hdev);
920 return err;
921}
922
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200923int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300924{
925 DECLARE_WAITQUEUE(wait, current);
926 int err = 0;
927 int timeo = HZ/5;
928
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200929 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300930 while ((l2cap_pi(sk)->chan->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300931 set_current_state(TASK_INTERRUPTIBLE);
932
933 if (!timeo)
934 timeo = HZ/5;
935
936 if (signal_pending(current)) {
937 err = sock_intr_errno(timeo);
938 break;
939 }
940
941 release_sock(sk);
942 timeo = schedule_timeout(timeo);
943 lock_sock(sk);
944
945 err = sock_error(sk);
946 if (err)
947 break;
948 }
949 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200950 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300951 return err;
952}
953
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300954static void l2cap_monitor_timeout(unsigned long arg)
955{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300956 struct l2cap_chan *chan = (void *) arg;
957 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300958
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300959 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300960
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300961 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -0300962 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300963 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200964 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300965 return;
966 }
967
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300968 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300969 __mod_monitor_timer();
970
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300971 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300972 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300973}
974
975static void l2cap_retrans_timeout(unsigned long arg)
976{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300977 struct l2cap_chan *chan = (void *) arg;
978 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300979
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300980 BT_DBG("sk %p", sk);
981
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300982 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300983 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300984 __mod_monitor_timer();
985
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300986 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300987
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300988 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300989 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300990}
991
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300992static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300993{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300994 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300995 struct sk_buff *skb;
996
Gustavo F. Padovan812e7372010-05-01 16:15:42 -0300997 while ((skb = skb_peek(TX_QUEUE(sk))) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300998 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300999 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001000 break;
1001
1002 skb = skb_dequeue(TX_QUEUE(sk));
1003 kfree_skb(skb);
1004
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001005 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001006 }
1007
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001008 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001009 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001010}
1011
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001012void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001013{
1014 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001015 struct hci_conn *hcon = pi->conn->hcon;
1016 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001017
1018 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1019
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001020 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
1021 flags = ACL_START_NO_FLUSH;
1022 else
1023 flags = ACL_START;
1024
1025 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001026}
1027
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001028void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001029{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001030 struct sock *sk = chan->sk;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001031 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001032 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001033 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001034
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001035 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
1036 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001037 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001038 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001039
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001040 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001041 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1042 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001043 }
1044
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001045 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001046
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001047 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001048 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001049}
1050
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001051static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001052{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001053 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001054 struct l2cap_pinfo *pi = l2cap_pi(sk);
1055 struct sk_buff *skb, *tx_skb;
1056 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001057
1058 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001059 if (!skb)
1060 return;
1061
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001062 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001063 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001064 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001065
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001066 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1067 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001068
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001069 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001070
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001071 if (chan->remote_max_tx &&
1072 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001073 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001074 return;
1075 }
1076
1077 tx_skb = skb_clone(skb, GFP_ATOMIC);
1078 bt_cb(skb)->retries++;
1079 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001080
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001081 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001082 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001083 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001084 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001085
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001086 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001087 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001088
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001089 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1090
1091 if (pi->fcs == L2CAP_FCS_CRC16) {
1092 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1093 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1094 }
1095
1096 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001097}
1098
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001099int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001100{
1101 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001102 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001103 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001104 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001105 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001106
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001107 if (sk->sk_state != BT_CONNECTED)
1108 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001109
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001110 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001111
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001112 if (chan->remote_max_tx &&
1113 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001114 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001115 break;
1116 }
1117
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001118 tx_skb = skb_clone(skb, GFP_ATOMIC);
1119
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001120 bt_cb(skb)->retries++;
1121
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001122 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001123 control &= L2CAP_CTRL_SAR;
1124
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001125 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001126 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001127 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001128 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001129 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1130 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001131 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1132
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001133
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001134 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001135 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1136 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1137 }
1138
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001139 l2cap_do_send(sk, tx_skb);
1140
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001141 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001142
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001143 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1144 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001145
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301146 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001147 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301148
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001149 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001150
1151 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1152 sk->sk_send_head = NULL;
1153 else
1154 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001155
1156 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001157 }
1158
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001159 return nsent;
1160}
1161
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001162static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001163{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001164 struct sock *sk = chan->sk;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001165 int ret;
1166
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001167 if (!skb_queue_empty(TX_QUEUE(sk)))
1168 sk->sk_send_head = TX_QUEUE(sk)->next;
1169
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001170 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001171 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001172 return ret;
1173}
1174
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001175static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001176{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001177 u16 control = 0;
1178
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001179 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001180
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001181 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001182 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001183 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1184 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001185 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001186 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001187
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001188 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001189 return;
1190
1191 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001192 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001193}
1194
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001195static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001196{
1197 struct srej_list *tail;
1198 u16 control;
1199
1200 control = L2CAP_SUPER_SELECT_REJECT;
1201 control |= L2CAP_CTRL_FINAL;
1202
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001203 tail = list_entry(SREJ_LIST(chan->sk)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001204 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1205
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001206 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001207}
1208
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001209static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210{
1211 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001212 struct sk_buff **frag;
1213 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001215 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001216 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217
1218 sent += count;
1219 len -= count;
1220
1221 /* Continuation fragments (no L2CAP header) */
1222 frag = &skb_shinfo(skb)->frag_list;
1223 while (len) {
1224 count = min_t(unsigned int, conn->mtu, len);
1225
1226 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1227 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001228 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001229 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1230 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231
1232 sent += count;
1233 len -= count;
1234
1235 frag = &(*frag)->next;
1236 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237
1238 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001239}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001241struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001242{
1243 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1244 struct sk_buff *skb;
1245 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1246 struct l2cap_hdr *lh;
1247
1248 BT_DBG("sk %p len %d", sk, (int)len);
1249
1250 count = min_t(unsigned int, (conn->mtu - hlen), len);
1251 skb = bt_skb_send_alloc(sk, count + hlen,
1252 msg->msg_flags & MSG_DONTWAIT, &err);
1253 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001254 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001255
1256 /* Create L2CAP header */
1257 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1258 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1259 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1260 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1261
1262 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1263 if (unlikely(err < 0)) {
1264 kfree_skb(skb);
1265 return ERR_PTR(err);
1266 }
1267 return skb;
1268}
1269
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001270struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001271{
1272 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1273 struct sk_buff *skb;
1274 int err, count, hlen = L2CAP_HDR_SIZE;
1275 struct l2cap_hdr *lh;
1276
1277 BT_DBG("sk %p len %d", sk, (int)len);
1278
1279 count = min_t(unsigned int, (conn->mtu - hlen), len);
1280 skb = bt_skb_send_alloc(sk, count + hlen,
1281 msg->msg_flags & MSG_DONTWAIT, &err);
1282 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001283 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001284
1285 /* Create L2CAP header */
1286 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1287 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1288 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1289
1290 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1291 if (unlikely(err < 0)) {
1292 kfree_skb(skb);
1293 return ERR_PTR(err);
1294 }
1295 return skb;
1296}
1297
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001298struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001299{
1300 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1301 struct sk_buff *skb;
1302 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1303 struct l2cap_hdr *lh;
1304
1305 BT_DBG("sk %p len %d", sk, (int)len);
1306
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001307 if (!conn)
1308 return ERR_PTR(-ENOTCONN);
1309
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001310 if (sdulen)
1311 hlen += 2;
1312
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001313 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1314 hlen += 2;
1315
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001316 count = min_t(unsigned int, (conn->mtu - hlen), len);
1317 skb = bt_skb_send_alloc(sk, count + hlen,
1318 msg->msg_flags & MSG_DONTWAIT, &err);
1319 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001320 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001321
1322 /* Create L2CAP header */
1323 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1324 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1325 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1326 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001327 if (sdulen)
1328 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001329
1330 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1331 if (unlikely(err < 0)) {
1332 kfree_skb(skb);
1333 return ERR_PTR(err);
1334 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001335
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001336 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1337 put_unaligned_le16(0, skb_put(skb, 2));
1338
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001339 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001340 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341}
1342
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001343int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001344{
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001345 struct sock *sk = chan->sk;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001346 struct sk_buff *skb;
1347 struct sk_buff_head sar_queue;
1348 u16 control;
1349 size_t size = 0;
1350
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001351 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001352 control = L2CAP_SDU_START;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001353 skb = l2cap_create_iframe_pdu(sk, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001354 if (IS_ERR(skb))
1355 return PTR_ERR(skb);
1356
1357 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001358 len -= chan->remote_mps;
1359 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001360
1361 while (len > 0) {
1362 size_t buflen;
1363
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001364 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001365 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001366 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001367 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001368 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001369 buflen = len;
1370 }
1371
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001372 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001373 if (IS_ERR(skb)) {
1374 skb_queue_purge(&sar_queue);
1375 return PTR_ERR(skb);
1376 }
1377
1378 __skb_queue_tail(&sar_queue, skb);
1379 len -= buflen;
1380 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001381 }
1382 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1383 if (sk->sk_send_head == NULL)
1384 sk->sk_send_head = sar_queue.next;
1385
1386 return size;
1387}
1388
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389static void l2cap_chan_ready(struct sock *sk)
1390{
1391 struct sock *parent = bt_sk(sk)->parent;
1392
1393 BT_DBG("sk %p, parent %p", sk, parent);
1394
1395 l2cap_pi(sk)->conf_state = 0;
1396 l2cap_sock_clear_timer(sk);
1397
1398 if (!parent) {
1399 /* Outgoing channel.
1400 * Wake up socket sleeping on connect.
1401 */
1402 sk->sk_state = BT_CONNECTED;
1403 sk->sk_state_change(sk);
1404 } else {
1405 /* Incoming channel.
1406 * Wake up socket sleeping on accept.
1407 */
1408 parent->sk_data_ready(parent, 0);
1409 }
1410}
1411
1412/* Copy frame to all raw sockets on that connection */
1413static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1414{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001416 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417
1418 BT_DBG("conn %p", conn);
1419
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001420 read_lock(&conn->chan_lock);
1421 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001422 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 if (sk->sk_type != SOCK_RAW)
1424 continue;
1425
1426 /* Don't send frame to the socket it came from */
1427 if (skb->sk == sk)
1428 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001429 nskb = skb_clone(skb, GFP_ATOMIC);
1430 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 continue;
1432
1433 if (sock_queue_rcv_skb(sk, nskb))
1434 kfree_skb(nskb);
1435 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001436 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437}
1438
1439/* ---- L2CAP signalling commands ---- */
1440static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1441 u8 code, u8 ident, u16 dlen, void *data)
1442{
1443 struct sk_buff *skb, **frag;
1444 struct l2cap_cmd_hdr *cmd;
1445 struct l2cap_hdr *lh;
1446 int len, count;
1447
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001448 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1449 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450
1451 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1452 count = min_t(unsigned int, conn->mtu, len);
1453
1454 skb = bt_skb_alloc(count, GFP_ATOMIC);
1455 if (!skb)
1456 return NULL;
1457
1458 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001459 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001460
1461 if (conn->hcon->type == LE_LINK)
1462 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1463 else
1464 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465
1466 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1467 cmd->code = code;
1468 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001469 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
1471 if (dlen) {
1472 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1473 memcpy(skb_put(skb, count), data, count);
1474 data += count;
1475 }
1476
1477 len -= skb->len;
1478
1479 /* Continuation fragments (no L2CAP header) */
1480 frag = &skb_shinfo(skb)->frag_list;
1481 while (len) {
1482 count = min_t(unsigned int, conn->mtu, len);
1483
1484 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1485 if (!*frag)
1486 goto fail;
1487
1488 memcpy(skb_put(*frag, count), data, count);
1489
1490 len -= count;
1491 data += count;
1492
1493 frag = &(*frag)->next;
1494 }
1495
1496 return skb;
1497
1498fail:
1499 kfree_skb(skb);
1500 return NULL;
1501}
1502
1503static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1504{
1505 struct l2cap_conf_opt *opt = *ptr;
1506 int len;
1507
1508 len = L2CAP_CONF_OPT_SIZE + opt->len;
1509 *ptr += len;
1510
1511 *type = opt->type;
1512 *olen = opt->len;
1513
1514 switch (opt->len) {
1515 case 1:
1516 *val = *((u8 *) opt->val);
1517 break;
1518
1519 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001520 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 break;
1522
1523 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001524 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 break;
1526
1527 default:
1528 *val = (unsigned long) opt->val;
1529 break;
1530 }
1531
1532 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1533 return len;
1534}
1535
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1537{
1538 struct l2cap_conf_opt *opt = *ptr;
1539
1540 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1541
1542 opt->type = type;
1543 opt->len = len;
1544
1545 switch (len) {
1546 case 1:
1547 *((u8 *) opt->val) = val;
1548 break;
1549
1550 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001551 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 break;
1553
1554 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001555 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 break;
1557
1558 default:
1559 memcpy(opt->val, (void *) val, len);
1560 break;
1561 }
1562
1563 *ptr += L2CAP_CONF_OPT_SIZE + len;
1564}
1565
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001566static void l2cap_ack_timeout(unsigned long arg)
1567{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001568 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001569
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001570 bh_lock_sock(chan->sk);
1571 l2cap_send_ack(chan);
1572 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001573}
1574
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001575static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001576{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001577 struct sock *sk = chan->sk;
1578
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001579 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001580 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001581 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001582 chan->num_acked = 0;
1583 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001584
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001585 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1586 (unsigned long) chan);
1587 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1588 (unsigned long) chan);
1589 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001590
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001591 skb_queue_head_init(&chan->srej_q);
1592 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001593
1594 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001595
1596 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001597}
1598
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001599static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1600{
1601 switch (mode) {
1602 case L2CAP_MODE_STREAMING:
1603 case L2CAP_MODE_ERTM:
1604 if (l2cap_mode_supported(mode, remote_feat_mask))
1605 return mode;
1606 /* fall through */
1607 default:
1608 return L2CAP_MODE_BASIC;
1609 }
1610}
1611
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001612static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001614 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 struct l2cap_pinfo *pi = l2cap_pi(sk);
1616 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001617 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618 void *ptr = req->data;
1619
1620 BT_DBG("sk %p", sk);
1621
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001622 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001623 goto done;
1624
1625 switch (pi->mode) {
1626 case L2CAP_MODE_STREAMING:
1627 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001628 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001629 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001630
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001631 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001632 default:
1633 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1634 break;
1635 }
1636
1637done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001638 if (pi->imtu != L2CAP_DEFAULT_MTU)
1639 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1640
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001641 switch (pi->mode) {
1642 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001643 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1644 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1645 break;
1646
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001647 rfc.mode = L2CAP_MODE_BASIC;
1648 rfc.txwin_size = 0;
1649 rfc.max_transmit = 0;
1650 rfc.retrans_timeout = 0;
1651 rfc.monitor_timeout = 0;
1652 rfc.max_pdu_size = 0;
1653
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001654 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1655 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001656 break;
1657
1658 case L2CAP_MODE_ERTM:
1659 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001660 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001661 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001662 rfc.retrans_timeout = 0;
1663 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001664 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001665 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001666 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001667
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001668 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1669 (unsigned long) &rfc);
1670
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001671 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1672 break;
1673
1674 if (pi->fcs == L2CAP_FCS_NONE ||
1675 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1676 pi->fcs = L2CAP_FCS_NONE;
1677 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1678 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001679 break;
1680
1681 case L2CAP_MODE_STREAMING:
1682 rfc.mode = L2CAP_MODE_STREAMING;
1683 rfc.txwin_size = 0;
1684 rfc.max_transmit = 0;
1685 rfc.retrans_timeout = 0;
1686 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001687 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001688 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001689 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001690
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001691 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1692 (unsigned long) &rfc);
1693
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001694 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1695 break;
1696
1697 if (pi->fcs == L2CAP_FCS_NONE ||
1698 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1699 pi->fcs = L2CAP_FCS_NONE;
1700 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1701 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001702 break;
1703 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001705 req->dcid = cpu_to_le16(pi->dcid);
1706 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707
1708 return ptr - data;
1709}
1710
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001711static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001713 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001714 struct l2cap_conf_rsp *rsp = data;
1715 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001716 void *req = chan->conf_req;
1717 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001718 int type, hint, olen;
1719 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001720 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001721 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001722 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001724 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001725
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001726 while (len >= L2CAP_CONF_OPT_SIZE) {
1727 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001729 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001730 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001731
1732 switch (type) {
1733 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001734 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001735 break;
1736
1737 case L2CAP_CONF_FLUSH_TO:
1738 pi->flush_to = val;
1739 break;
1740
1741 case L2CAP_CONF_QOS:
1742 break;
1743
Marcel Holtmann6464f352007-10-20 13:39:51 +02001744 case L2CAP_CONF_RFC:
1745 if (olen == sizeof(rfc))
1746 memcpy(&rfc, (void *) val, olen);
1747 break;
1748
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001749 case L2CAP_CONF_FCS:
1750 if (val == L2CAP_FCS_NONE)
1751 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1752
1753 break;
1754
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001755 default:
1756 if (hint)
1757 break;
1758
1759 result = L2CAP_CONF_UNKNOWN;
1760 *((u8 *) ptr++) = type;
1761 break;
1762 }
1763 }
1764
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001765 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001766 goto done;
1767
1768 switch (pi->mode) {
1769 case L2CAP_MODE_STREAMING:
1770 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001771 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1772 pi->mode = l2cap_select_mode(rfc.mode,
1773 pi->conn->feat_mask);
1774 break;
1775 }
1776
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001777 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001778 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001779
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001780 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001781 }
1782
1783done:
1784 if (pi->mode != rfc.mode) {
1785 result = L2CAP_CONF_UNACCEPT;
1786 rfc.mode = pi->mode;
1787
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001788 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001789 return -ECONNREFUSED;
1790
1791 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1792 sizeof(rfc), (unsigned long) &rfc);
1793 }
1794
1795
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001796 if (result == L2CAP_CONF_SUCCESS) {
1797 /* Configure output options and let the other side know
1798 * which ones we don't like. */
1799
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001800 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1801 result = L2CAP_CONF_UNACCEPT;
1802 else {
1803 pi->omtu = mtu;
1804 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1805 }
1806 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001807
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001808 switch (rfc.mode) {
1809 case L2CAP_MODE_BASIC:
1810 pi->fcs = L2CAP_FCS_NONE;
1811 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1812 break;
1813
1814 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001815 chan->remote_tx_win = rfc.txwin_size;
1816 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001817
1818 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1819 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001820
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001821 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001822
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001823 rfc.retrans_timeout =
1824 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1825 rfc.monitor_timeout =
1826 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001827
1828 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001829
1830 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1831 sizeof(rfc), (unsigned long) &rfc);
1832
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001833 break;
1834
1835 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001836 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1837 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001838
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001839 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001840
1841 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001842
1843 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1844 sizeof(rfc), (unsigned long) &rfc);
1845
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001846 break;
1847
1848 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001849 result = L2CAP_CONF_UNACCEPT;
1850
1851 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001852 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001853 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001854
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001855 if (result == L2CAP_CONF_SUCCESS)
1856 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1857 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001858 rsp->scid = cpu_to_le16(pi->dcid);
1859 rsp->result = cpu_to_le16(result);
1860 rsp->flags = cpu_to_le16(0x0000);
1861
1862 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863}
1864
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001865static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1866{
1867 struct l2cap_pinfo *pi = l2cap_pi(sk);
1868 struct l2cap_conf_req *req = data;
1869 void *ptr = req->data;
1870 int type, olen;
1871 unsigned long val;
1872 struct l2cap_conf_rfc rfc;
1873
1874 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1875
1876 while (len >= L2CAP_CONF_OPT_SIZE) {
1877 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1878
1879 switch (type) {
1880 case L2CAP_CONF_MTU:
1881 if (val < L2CAP_DEFAULT_MIN_MTU) {
1882 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001883 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001884 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001885 pi->imtu = val;
1886 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001887 break;
1888
1889 case L2CAP_CONF_FLUSH_TO:
1890 pi->flush_to = val;
1891 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1892 2, pi->flush_to);
1893 break;
1894
1895 case L2CAP_CONF_RFC:
1896 if (olen == sizeof(rfc))
1897 memcpy(&rfc, (void *)val, olen);
1898
1899 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1900 rfc.mode != pi->mode)
1901 return -ECONNREFUSED;
1902
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001903 pi->fcs = 0;
1904
1905 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1906 sizeof(rfc), (unsigned long) &rfc);
1907 break;
1908 }
1909 }
1910
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001911 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1912 return -ECONNREFUSED;
1913
1914 pi->mode = rfc.mode;
1915
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001916 if (*result == L2CAP_CONF_SUCCESS) {
1917 switch (rfc.mode) {
1918 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001919 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1920 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001921 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001922 break;
1923 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001924 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001925 }
1926 }
1927
1928 req->dcid = cpu_to_le16(pi->dcid);
1929 req->flags = cpu_to_le16(0x0000);
1930
1931 return ptr - data;
1932}
1933
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001934static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935{
1936 struct l2cap_conf_rsp *rsp = data;
1937 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001939 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001941 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001942 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001943 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944
1945 return ptr - data;
1946}
1947
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001948void __l2cap_connect_rsp_defer(struct sock *sk)
1949{
1950 struct l2cap_conn_rsp rsp;
1951 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1952 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
1953 u8 buf[128];
1954
1955 sk->sk_state = BT_CONFIG;
1956
1957 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1958 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1959 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1960 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1961 l2cap_send_cmd(conn, chan->ident,
1962 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1963
1964 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
1965 return;
1966
1967 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
1968 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1969 l2cap_build_conf_req(chan, buf), buf);
1970 chan->num_conf_req++;
1971}
1972
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001973static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1974{
1975 struct l2cap_pinfo *pi = l2cap_pi(sk);
1976 int type, olen;
1977 unsigned long val;
1978 struct l2cap_conf_rfc rfc;
1979
1980 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1981
1982 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1983 return;
1984
1985 while (len >= L2CAP_CONF_OPT_SIZE) {
1986 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1987
1988 switch (type) {
1989 case L2CAP_CONF_RFC:
1990 if (olen == sizeof(rfc))
1991 memcpy(&rfc, (void *)val, olen);
1992 goto done;
1993 }
1994 }
1995
1996done:
1997 switch (rfc.mode) {
1998 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001999 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
2000 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002001 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2002 break;
2003 case L2CAP_MODE_STREAMING:
2004 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2005 }
2006}
2007
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002008static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2009{
2010 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2011
2012 if (rej->reason != 0x0000)
2013 return 0;
2014
2015 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2016 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002017 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002018
2019 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002020 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002021
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002022 l2cap_conn_start(conn);
2023 }
2024
2025 return 0;
2026}
2027
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2029{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2031 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002032 struct l2cap_chan *chan = NULL;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002033 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002034 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035
2036 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002037 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038
2039 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2040
2041 /* Check if we have socket listening on psm */
2042 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2043 if (!parent) {
2044 result = L2CAP_CR_BAD_PSM;
2045 goto sendresp;
2046 }
2047
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002048 bh_lock_sock(parent);
2049
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002050 /* Check if the ACL is secure enough (if not SDP) */
2051 if (psm != cpu_to_le16(0x0001) &&
2052 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002053 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002054 result = L2CAP_CR_SEC_BLOCK;
2055 goto response;
2056 }
2057
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058 result = L2CAP_CR_NO_MEM;
2059
2060 /* Check for backlog size */
2061 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002062 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 goto response;
2064 }
2065
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002066 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 if (!sk)
2068 goto response;
2069
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002070 chan = l2cap_chan_alloc(sk);
2071 if (!chan) {
2072 l2cap_sock_kill(sk);
2073 goto response;
2074 }
2075
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002076 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077
2078 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002079 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2080 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 sock_set_flag(sk, SOCK_ZAPPED);
2082 l2cap_sock_kill(sk);
2083 goto response;
2084 }
2085
2086 hci_conn_hold(conn->hcon);
2087
2088 l2cap_sock_init(sk, parent);
2089 bacpy(&bt_sk(sk)->src, conn->src);
2090 bacpy(&bt_sk(sk)->dst, conn->dst);
2091 l2cap_pi(sk)->psm = psm;
2092 l2cap_pi(sk)->dcid = scid;
2093
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002094 bt_accept_enqueue(parent, sk);
2095
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002096 __l2cap_chan_add(conn, chan);
2097
2098 l2cap_pi(sk)->chan = chan;
2099
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 dcid = l2cap_pi(sk)->scid;
2101
2102 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2103
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002104 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105
Marcel Holtmann984947d2009-02-06 23:35:19 +01002106 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002107 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002108 if (bt_sk(sk)->defer_setup) {
2109 sk->sk_state = BT_CONNECT2;
2110 result = L2CAP_CR_PEND;
2111 status = L2CAP_CS_AUTHOR_PEND;
2112 parent->sk_data_ready(parent, 0);
2113 } else {
2114 sk->sk_state = BT_CONFIG;
2115 result = L2CAP_CR_SUCCESS;
2116 status = L2CAP_CS_NO_INFO;
2117 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002118 } else {
2119 sk->sk_state = BT_CONNECT2;
2120 result = L2CAP_CR_PEND;
2121 status = L2CAP_CS_AUTHEN_PEND;
2122 }
2123 } else {
2124 sk->sk_state = BT_CONNECT2;
2125 result = L2CAP_CR_PEND;
2126 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 }
2128
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002129 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130
2131response:
2132 bh_unlock_sock(parent);
2133
2134sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002135 rsp.scid = cpu_to_le16(scid);
2136 rsp.dcid = cpu_to_le16(dcid);
2137 rsp.result = cpu_to_le16(result);
2138 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002140
2141 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2142 struct l2cap_info_req info;
2143 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2144
2145 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2146 conn->info_ident = l2cap_get_ident(conn);
2147
2148 mod_timer(&conn->info_timer, jiffies +
2149 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2150
2151 l2cap_send_cmd(conn, conn->info_ident,
2152 L2CAP_INFO_REQ, sizeof(info), &info);
2153 }
2154
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002155 if (chan && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002156 result == L2CAP_CR_SUCCESS) {
2157 u8 buf[128];
2158 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2159 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002160 l2cap_build_conf_req(chan, buf), buf);
2161 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002162 }
2163
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 return 0;
2165}
2166
2167static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2168{
2169 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2170 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002171 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 struct sock *sk;
2173 u8 req[128];
2174
2175 scid = __le16_to_cpu(rsp->scid);
2176 dcid = __le16_to_cpu(rsp->dcid);
2177 result = __le16_to_cpu(rsp->result);
2178 status = __le16_to_cpu(rsp->status);
2179
2180 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2181
2182 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002183 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002184 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002185 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002187 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002188 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002189 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 }
2191
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002192 sk = chan->sk;
2193
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 switch (result) {
2195 case L2CAP_CR_SUCCESS:
2196 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002197 chan->ident = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002199 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2200
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002201 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2202 break;
2203
2204 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2205
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002207 l2cap_build_conf_req(chan, req), req);
2208 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 break;
2210
2211 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002212 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 break;
2214
2215 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002216 /* don't delete l2cap channel if sk is owned by user */
2217 if (sock_owned_by_user(sk)) {
2218 sk->sk_state = BT_DISCONN;
2219 l2cap_sock_clear_timer(sk);
2220 l2cap_sock_set_timer(sk, HZ / 5);
2221 break;
2222 }
2223
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002224 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 break;
2226 }
2227
2228 bh_unlock_sock(sk);
2229 return 0;
2230}
2231
Mat Martineau8c462b62010-08-24 15:35:42 -07002232static inline void set_default_fcs(struct l2cap_pinfo *pi)
2233{
2234 /* FCS is enabled only in ERTM or streaming mode, if one or both
2235 * sides request it.
2236 */
2237 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2238 pi->fcs = L2CAP_FCS_NONE;
2239 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2240 pi->fcs = L2CAP_FCS_CRC16;
2241}
2242
Al Viro88219a02007-07-29 00:17:25 -07002243static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244{
2245 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2246 u16 dcid, flags;
2247 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002248 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002250 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251
2252 dcid = __le16_to_cpu(req->dcid);
2253 flags = __le16_to_cpu(req->flags);
2254
2255 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2256
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002257 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002258 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259 return -ENOENT;
2260
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002261 sk = chan->sk;
2262
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002263 if (sk->sk_state != BT_CONFIG) {
2264 struct l2cap_cmd_rej rej;
2265
2266 rej.reason = cpu_to_le16(0x0002);
2267 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2268 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002269 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002270 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002271
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002272 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002273 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002274 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002275 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2276 l2cap_build_conf_rsp(sk, rsp,
2277 L2CAP_CONF_REJECT, flags), rsp);
2278 goto unlock;
2279 }
2280
2281 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002282 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2283 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284
2285 if (flags & 0x0001) {
2286 /* Incomplete config. Send empty response. */
2287 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002288 l2cap_build_conf_rsp(sk, rsp,
2289 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290 goto unlock;
2291 }
2292
2293 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002294 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002295 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002296 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002298 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002300 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002301 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002302
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002303 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002304 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002305
Marcel Holtmann876d9482007-10-20 13:35:42 +02002306 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2307 goto unlock;
2308
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002310 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002311
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002313
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002314 chan->next_tx_seq = 0;
2315 chan->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002316 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002317 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002318 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002319
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002321 goto unlock;
2322 }
2323
2324 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002325 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002326 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002328 l2cap_build_conf_req(chan, buf), buf);
2329 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330 }
2331
2332unlock:
2333 bh_unlock_sock(sk);
2334 return 0;
2335}
2336
2337static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2338{
2339 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2340 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002341 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002343 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344
2345 scid = __le16_to_cpu(rsp->scid);
2346 flags = __le16_to_cpu(rsp->flags);
2347 result = __le16_to_cpu(rsp->result);
2348
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002349 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2350 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002352 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002353 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 return 0;
2355
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002356 sk = chan->sk;
2357
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 switch (result) {
2359 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002360 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 break;
2362
2363 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002364 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002365 char req[64];
2366
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002367 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002368 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002369 goto done;
2370 }
2371
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002372 /* throw out any old stored conf requests */
2373 result = L2CAP_CONF_SUCCESS;
2374 len = l2cap_parse_conf_rsp(sk, rsp->data,
2375 len, req, &result);
2376 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002377 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002378 goto done;
2379 }
2380
2381 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2382 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002383 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002384 if (result != L2CAP_CONF_SUCCESS)
2385 goto done;
2386 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 }
2388
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002389 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002390 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002392 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393 goto done;
2394 }
2395
2396 if (flags & 0x01)
2397 goto done;
2398
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2400
2401 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002402 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002403
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002405 chan->next_tx_seq = 0;
2406 chan->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002407 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002408 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002409 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002410
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 l2cap_chan_ready(sk);
2412 }
2413
2414done:
2415 bh_unlock_sock(sk);
2416 return 0;
2417}
2418
2419static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2420{
2421 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2422 struct l2cap_disconn_rsp rsp;
2423 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002424 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425 struct sock *sk;
2426
2427 scid = __le16_to_cpu(req->scid);
2428 dcid = __le16_to_cpu(req->dcid);
2429
2430 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2431
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002432 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002433 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434 return 0;
2435
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002436 sk = chan->sk;
2437
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002438 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2439 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2441
2442 sk->sk_shutdown = SHUTDOWN_MASK;
2443
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002444 /* don't delete l2cap channel if sk is owned by user */
2445 if (sock_owned_by_user(sk)) {
2446 sk->sk_state = BT_DISCONN;
2447 l2cap_sock_clear_timer(sk);
2448 l2cap_sock_set_timer(sk, HZ / 5);
2449 bh_unlock_sock(sk);
2450 return 0;
2451 }
2452
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002453 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 bh_unlock_sock(sk);
2455
2456 l2cap_sock_kill(sk);
2457 return 0;
2458}
2459
2460static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2461{
2462 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2463 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002464 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465 struct sock *sk;
2466
2467 scid = __le16_to_cpu(rsp->scid);
2468 dcid = __le16_to_cpu(rsp->dcid);
2469
2470 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2471
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002472 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002473 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 return 0;
2475
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002476 sk = chan->sk;
2477
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002478 /* don't delete l2cap channel if sk is owned by user */
2479 if (sock_owned_by_user(sk)) {
2480 sk->sk_state = BT_DISCONN;
2481 l2cap_sock_clear_timer(sk);
2482 l2cap_sock_set_timer(sk, HZ / 5);
2483 bh_unlock_sock(sk);
2484 return 0;
2485 }
2486
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002487 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 bh_unlock_sock(sk);
2489
2490 l2cap_sock_kill(sk);
2491 return 0;
2492}
2493
2494static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2495{
2496 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 u16 type;
2498
2499 type = __le16_to_cpu(req->type);
2500
2501 BT_DBG("type 0x%4.4x", type);
2502
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002503 if (type == L2CAP_IT_FEAT_MASK) {
2504 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002505 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002506 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2507 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2508 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002509 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002510 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2511 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002512 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002513 l2cap_send_cmd(conn, cmd->ident,
2514 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002515 } else if (type == L2CAP_IT_FIXED_CHAN) {
2516 u8 buf[12];
2517 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2518 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2519 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2520 memcpy(buf + 4, l2cap_fixed_chan, 8);
2521 l2cap_send_cmd(conn, cmd->ident,
2522 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002523 } else {
2524 struct l2cap_info_rsp rsp;
2525 rsp.type = cpu_to_le16(type);
2526 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2527 l2cap_send_cmd(conn, cmd->ident,
2528 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2529 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530
2531 return 0;
2532}
2533
2534static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2535{
2536 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2537 u16 type, result;
2538
2539 type = __le16_to_cpu(rsp->type);
2540 result = __le16_to_cpu(rsp->result);
2541
2542 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2543
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002544 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2545 if (cmd->ident != conn->info_ident ||
2546 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2547 return 0;
2548
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002549 del_timer(&conn->info_timer);
2550
Ville Tervoadb08ed2010-08-04 09:43:33 +03002551 if (result != L2CAP_IR_SUCCESS) {
2552 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2553 conn->info_ident = 0;
2554
2555 l2cap_conn_start(conn);
2556
2557 return 0;
2558 }
2559
Marcel Holtmann984947d2009-02-06 23:35:19 +01002560 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002561 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002562
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002563 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002564 struct l2cap_info_req req;
2565 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2566
2567 conn->info_ident = l2cap_get_ident(conn);
2568
2569 l2cap_send_cmd(conn, conn->info_ident,
2570 L2CAP_INFO_REQ, sizeof(req), &req);
2571 } else {
2572 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2573 conn->info_ident = 0;
2574
2575 l2cap_conn_start(conn);
2576 }
2577 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002578 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002579 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002580
2581 l2cap_conn_start(conn);
2582 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002583
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584 return 0;
2585}
2586
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002587static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002588 u16 to_multiplier)
2589{
2590 u16 max_latency;
2591
2592 if (min > max || min < 6 || max > 3200)
2593 return -EINVAL;
2594
2595 if (to_multiplier < 10 || to_multiplier > 3200)
2596 return -EINVAL;
2597
2598 if (max >= to_multiplier * 8)
2599 return -EINVAL;
2600
2601 max_latency = (to_multiplier * 8 / max) - 1;
2602 if (latency > 499 || latency > max_latency)
2603 return -EINVAL;
2604
2605 return 0;
2606}
2607
2608static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2609 struct l2cap_cmd_hdr *cmd, u8 *data)
2610{
2611 struct hci_conn *hcon = conn->hcon;
2612 struct l2cap_conn_param_update_req *req;
2613 struct l2cap_conn_param_update_rsp rsp;
2614 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002615 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002616
2617 if (!(hcon->link_mode & HCI_LM_MASTER))
2618 return -EINVAL;
2619
2620 cmd_len = __le16_to_cpu(cmd->len);
2621 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2622 return -EPROTO;
2623
2624 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002625 min = __le16_to_cpu(req->min);
2626 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002627 latency = __le16_to_cpu(req->latency);
2628 to_multiplier = __le16_to_cpu(req->to_multiplier);
2629
2630 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2631 min, max, latency, to_multiplier);
2632
2633 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002634
2635 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2636 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002637 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2638 else
2639 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2640
2641 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2642 sizeof(rsp), &rsp);
2643
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002644 if (!err)
2645 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2646
Claudio Takahaside731152011-02-11 19:28:55 -02002647 return 0;
2648}
2649
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002650static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2651 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2652{
2653 int err = 0;
2654
2655 switch (cmd->code) {
2656 case L2CAP_COMMAND_REJ:
2657 l2cap_command_rej(conn, cmd, data);
2658 break;
2659
2660 case L2CAP_CONN_REQ:
2661 err = l2cap_connect_req(conn, cmd, data);
2662 break;
2663
2664 case L2CAP_CONN_RSP:
2665 err = l2cap_connect_rsp(conn, cmd, data);
2666 break;
2667
2668 case L2CAP_CONF_REQ:
2669 err = l2cap_config_req(conn, cmd, cmd_len, data);
2670 break;
2671
2672 case L2CAP_CONF_RSP:
2673 err = l2cap_config_rsp(conn, cmd, data);
2674 break;
2675
2676 case L2CAP_DISCONN_REQ:
2677 err = l2cap_disconnect_req(conn, cmd, data);
2678 break;
2679
2680 case L2CAP_DISCONN_RSP:
2681 err = l2cap_disconnect_rsp(conn, cmd, data);
2682 break;
2683
2684 case L2CAP_ECHO_REQ:
2685 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2686 break;
2687
2688 case L2CAP_ECHO_RSP:
2689 break;
2690
2691 case L2CAP_INFO_REQ:
2692 err = l2cap_information_req(conn, cmd, data);
2693 break;
2694
2695 case L2CAP_INFO_RSP:
2696 err = l2cap_information_rsp(conn, cmd, data);
2697 break;
2698
2699 default:
2700 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2701 err = -EINVAL;
2702 break;
2703 }
2704
2705 return err;
2706}
2707
2708static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2709 struct l2cap_cmd_hdr *cmd, u8 *data)
2710{
2711 switch (cmd->code) {
2712 case L2CAP_COMMAND_REJ:
2713 return 0;
2714
2715 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002716 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002717
2718 case L2CAP_CONN_PARAM_UPDATE_RSP:
2719 return 0;
2720
2721 default:
2722 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2723 return -EINVAL;
2724 }
2725}
2726
2727static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2728 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729{
2730 u8 *data = skb->data;
2731 int len = skb->len;
2732 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002733 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734
2735 l2cap_raw_recv(conn, skb);
2736
2737 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002738 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2740 data += L2CAP_CMD_HDR_SIZE;
2741 len -= L2CAP_CMD_HDR_SIZE;
2742
Al Viro88219a02007-07-29 00:17:25 -07002743 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744
Al Viro88219a02007-07-29 00:17:25 -07002745 BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746
Al Viro88219a02007-07-29 00:17:25 -07002747 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 BT_DBG("corrupted command");
2749 break;
2750 }
2751
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002752 if (conn->hcon->type == LE_LINK)
2753 err = l2cap_le_sig_cmd(conn, &cmd, data);
2754 else
2755 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756
2757 if (err) {
2758 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002759
2760 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761
2762 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002763 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2765 }
2766
Al Viro88219a02007-07-29 00:17:25 -07002767 data += cmd_len;
2768 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 }
2770
2771 kfree_skb(skb);
2772}
2773
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002774static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2775{
2776 u16 our_fcs, rcv_fcs;
2777 int hdr_size = L2CAP_HDR_SIZE + 2;
2778
2779 if (pi->fcs == L2CAP_FCS_CRC16) {
2780 skb_trim(skb, skb->len - 2);
2781 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2782 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2783
2784 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002785 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002786 }
2787 return 0;
2788}
2789
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002790static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002791{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002792 u16 control = 0;
2793
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002794 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002795
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002796 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002797
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002798 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002799 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002800 l2cap_send_sframe(chan, control);
2801 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002802 }
2803
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002804 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2805 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002806
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002807 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002808
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002809 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002810 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002811 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002812 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002813 }
2814}
2815
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002816static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u8 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002817{
2818 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002819 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002820
2821 bt_cb(skb)->tx_seq = tx_seq;
2822 bt_cb(skb)->sar = sar;
2823
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002824 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002825 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002826 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002827 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002828 }
2829
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002830 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002831 if (tx_seq_offset < 0)
2832 tx_seq_offset += 64;
2833
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002834 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002835 if (bt_cb(next_skb)->tx_seq == tx_seq)
2836 return -EINVAL;
2837
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002838 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002839 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002840 if (next_tx_seq_offset < 0)
2841 next_tx_seq_offset += 64;
2842
2843 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002844 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002845 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002846 }
2847
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002848 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002849 break;
2850
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002851 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002852
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002853 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002854
2855 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002856}
2857
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002858static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002859{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002860 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002861 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002862 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002863
2864 switch (control & L2CAP_CTRL_SAR) {
2865 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002866 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002867 goto drop;
2868
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002869 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002870 if (!err)
2871 return err;
2872
2873 break;
2874
2875 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002876 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002877 goto drop;
2878
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002879 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002880
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002881 if (chan->sdu_len > pi->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002882 goto disconnect;
2883
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002884 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
2885 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002886 return -ENOMEM;
2887
2888 /* pull sdu_len bytes only after alloc, because of Local Busy
2889 * condition we have to be sure that this will be executed
2890 * only once, i.e., when alloc does not fail */
2891 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002892
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002893 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002894
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002895 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002896 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002897 break;
2898
2899 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002900 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002901 goto disconnect;
2902
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002903 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002904 goto disconnect;
2905
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002906 chan->partial_sdu_len += skb->len;
2907 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002908 goto drop;
2909
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002910 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002911
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002912 break;
2913
2914 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002915 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002916 goto disconnect;
2917
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002918 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002919 goto disconnect;
2920
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002921 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002922 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002923
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002924 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002925 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002926
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002927 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002928 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002929
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002930 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002931 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002932
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002933 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002934 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002935 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002936 return -ENOMEM;
2937 }
2938
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002939 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002940 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002941 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002942 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002943 return err;
2944 }
2945
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002946 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2947 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002948
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002949 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002950 break;
2951 }
2952
2953 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002954 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002955
2956drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002957 kfree_skb(chan->sdu);
2958 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002959
2960disconnect:
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002961 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002962 kfree_skb(skb);
2963 return 0;
2964}
2965
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002966static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002967{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002968 struct sock *sk = chan->sk;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002969 struct sk_buff *skb;
2970 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002971 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002972
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002973 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002974 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002975 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002976 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002977 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002978 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002979 }
2980
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002981 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002982 }
2983
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002984 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002985 goto done;
2986
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002987 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002988 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002989 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002990 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002991
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002992 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002993 __mod_monitor_timer();
2994
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002995 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002996
2997done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002998 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2999 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003000
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003001 BT_DBG("sk %p, Exit local busy", sk);
3002
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003003 return 0;
3004}
3005
3006static void l2cap_busy_work(struct work_struct *work)
3007{
3008 DECLARE_WAITQUEUE(wait, current);
3009 struct l2cap_pinfo *pi =
3010 container_of(work, struct l2cap_pinfo, busy_work);
3011 struct sock *sk = (struct sock *)pi;
3012 int n_tries = 0, timeo = HZ/5, err;
3013 struct sk_buff *skb;
3014
3015 lock_sock(sk);
3016
3017 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003018 while ((skb = skb_peek(&pi->chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003019 set_current_state(TASK_INTERRUPTIBLE);
3020
3021 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3022 err = -EBUSY;
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003023 l2cap_send_disconn_req(pi->conn, pi->chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003024 break;
3025 }
3026
3027 if (!timeo)
3028 timeo = HZ/5;
3029
3030 if (signal_pending(current)) {
3031 err = sock_intr_errno(timeo);
3032 break;
3033 }
3034
3035 release_sock(sk);
3036 timeo = schedule_timeout(timeo);
3037 lock_sock(sk);
3038
3039 err = sock_error(sk);
3040 if (err)
3041 break;
3042
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003043 if (l2cap_try_push_rx_skb(l2cap_pi(sk)->chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003044 break;
3045 }
3046
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003047 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003048 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003049
3050 release_sock(sk);
3051}
3052
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003053static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003054{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003055 struct sock *sk = chan->sk;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003056 struct l2cap_pinfo *pi = l2cap_pi(sk);
3057 int sctrl, err;
3058
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003059 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003060 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003061 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003062 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003063
3064
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003065 }
3066
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003067 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003068 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003069 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003070 return err;
3071 }
3072
3073 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003074 BT_DBG("sk %p, Enter local busy", sk);
3075
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003076 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003077 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003078 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003079
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003080 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003081 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003082 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003083
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003084 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003085
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003086 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003087
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003088 queue_work(_busy_wq, &pi->busy_work);
3089
3090 return err;
3091}
3092
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003093static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003094{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003095 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003096 struct sk_buff *_skb;
3097 int err = -EINVAL;
3098
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003099 /*
3100 * TODO: We have to notify the userland if some data is lost with the
3101 * Streaming Mode.
3102 */
3103
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003104 switch (control & L2CAP_CTRL_SAR) {
3105 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003106 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003107 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003108 break;
3109 }
3110
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003111 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003112 if (!err)
3113 return 0;
3114
3115 break;
3116
3117 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003118 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003119 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003120 break;
3121 }
3122
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003123 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003124 skb_pull(skb, 2);
3125
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003126 if (chan->sdu_len > pi->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003127 err = -EMSGSIZE;
3128 break;
3129 }
3130
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003131 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3132 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003133 err = -ENOMEM;
3134 break;
3135 }
3136
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003137 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003138
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003139 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003140 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003141 err = 0;
3142 break;
3143
3144 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003145 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003146 break;
3147
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003148 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003149
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003150 chan->partial_sdu_len += skb->len;
3151 if (chan->partial_sdu_len > chan->sdu_len)
3152 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003153 else
3154 err = 0;
3155
3156 break;
3157
3158 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003159 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003160 break;
3161
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003162 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003163
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003164 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003165 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003166
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003167 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003168 goto drop;
3169
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003170 if (chan->partial_sdu_len == chan->sdu_len) {
3171 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003172 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003173 if (err < 0)
3174 kfree_skb(_skb);
3175 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003176 err = 0;
3177
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003178drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003179 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003180 break;
3181 }
3182
3183 kfree_skb(skb);
3184 return err;
3185}
3186
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003187static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003188{
3189 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003190 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003191
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003192 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003193 if (bt_cb(skb)->tx_seq != tx_seq)
3194 break;
3195
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003196 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003197 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003198 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003199 chan->buffer_seq_srej =
3200 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003201 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003202 }
3203}
3204
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003205static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003206{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003207 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003208 struct srej_list *l, *tmp;
3209 u16 control;
3210
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003211 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003212 if (l->tx_seq == tx_seq) {
3213 list_del(&l->list);
3214 kfree(l);
3215 return;
3216 }
3217 control = L2CAP_SUPER_SELECT_REJECT;
3218 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003219 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003220 list_del(&l->list);
3221 list_add_tail(&l->list, SREJ_LIST(sk));
3222 }
3223}
3224
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003225static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003226{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003227 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003228 struct srej_list *new;
3229 u16 control;
3230
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003231 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003232 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003233 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003234 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003235
3236 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003237 new->tx_seq = chan->expected_tx_seq;
3238 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003239 list_add_tail(&new->list, SREJ_LIST(sk));
3240 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003241 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003242}
3243
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003244static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003245{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003246 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003247 struct l2cap_pinfo *pi = l2cap_pi(sk);
3248 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003249 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003250 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003251 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003252 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003253 int err = 0;
3254
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003255 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3256 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003257
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003258 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003259 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003260 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003261 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003262 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003263 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003264 }
3265
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003266 chan->expected_ack_seq = req_seq;
3267 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003268
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003269 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003270 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003271
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003272 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003273 if (tx_seq_offset < 0)
3274 tx_seq_offset += 64;
3275
3276 /* invalid tx_seq */
3277 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003278 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003279 goto drop;
3280 }
3281
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003282 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003283 goto drop;
3284
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003285 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003286 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003287
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003288 first = list_first_entry(SREJ_LIST(sk),
3289 struct srej_list, list);
3290 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003291 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003292 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003293
3294 list_del(&first->list);
3295 kfree(first);
3296
3297 if (list_empty(SREJ_LIST(sk))) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003298 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003299 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3300 l2cap_send_ack(chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003301 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003302 }
3303 } else {
3304 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003305
3306 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003307 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003308 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003309
3310 list_for_each_entry(l, SREJ_LIST(sk), list) {
3311 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003312 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003313 return 0;
3314 }
3315 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003316 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003317 }
3318 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003319 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003320 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003321 if (expected_tx_seq_offset < 0)
3322 expected_tx_seq_offset += 64;
3323
3324 /* duplicated tx_seq */
3325 if (tx_seq_offset < expected_tx_seq_offset)
3326 goto drop;
3327
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003328 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003329
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003330 BT_DBG("sk %p, Enter SREJ", sk);
3331
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003332 INIT_LIST_HEAD(SREJ_LIST(sk));
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003333 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003334
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003335 __skb_queue_head_init(&chan->srej_q);
3336 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003337 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003338
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003339 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003340
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003341 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003342
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003343 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003344 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003345 return 0;
3346
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003347expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003348 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003349
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003350 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003351 bt_cb(skb)->tx_seq = tx_seq;
3352 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003353 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003354 return 0;
3355 }
3356
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003357 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003358 if (err < 0)
3359 return 0;
3360
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003361 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003362 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3363 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003364 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003365 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003366 }
3367
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003368 __mod_ack_timer();
3369
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003370 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3371 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003372 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003373
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003374 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003375
3376drop:
3377 kfree_skb(skb);
3378 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003379}
3380
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003381static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003382{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003383 struct sock *sk = chan->sk;
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003384
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003385 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3386 rx_control);
3387
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003388 chan->expected_ack_seq = __get_reqseq(rx_control);
3389 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003390
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003391 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003392 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3393 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3394 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003395 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003396 __mod_retrans_timer();
3397
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003398 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3399 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003400 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003401 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003402 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003403
3404 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003405 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003406
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003407 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3408 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003409 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003410 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003411
3412 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003413 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003414 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003415 __mod_retrans_timer();
3416
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003417 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3418 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3419 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003420 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003421 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003422 }
3423}
3424
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003425static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003426{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003427 u8 tx_seq = __get_reqseq(rx_control);
3428
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003429 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003430
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003431 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003432
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003433 chan->expected_ack_seq = tx_seq;
3434 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003435
3436 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003437 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3438 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003439 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003440 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003441 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003442 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003443
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003444 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3445 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003446 }
3447}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003448static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003449{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003450 u8 tx_seq = __get_reqseq(rx_control);
3451
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003452 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003453
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003454 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003455
3456 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003457 chan->expected_ack_seq = tx_seq;
3458 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003459
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003460 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3461 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003462
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003463 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003464
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003465 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003466 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003467 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003468 }
3469 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003470 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003471 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003472 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003473 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003474 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003475 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003476 l2cap_retransmit_one_frame(chan, tx_seq);
3477 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003478 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003479 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003480 }
3481 }
3482}
3483
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003484static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003485{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003486 u8 tx_seq = __get_reqseq(rx_control);
3487
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003488 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003489
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003490 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003491 chan->expected_ack_seq = tx_seq;
3492 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003493
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003494 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003495 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003496
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003497 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003498 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003499 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003500 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003501 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003502 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003503
3504 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003505 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003506 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003507 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003508}
3509
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003510static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003511{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003512 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003513
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003514 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003515 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003516 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003517 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003518 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003519 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003520 }
3521
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003522 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3523 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003524 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003525 break;
3526
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003527 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003528 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003529 break;
3530
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003531 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003532 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003533 break;
3534
3535 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003536 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003537 break;
3538 }
3539
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003540 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003541 return 0;
3542}
3543
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003544static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3545{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003546 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003547 struct l2cap_pinfo *pi = l2cap_pi(sk);
3548 u16 control;
3549 u8 req_seq;
3550 int len, next_tx_seq_offset, req_seq_offset;
3551
3552 control = get_unaligned_le16(skb->data);
3553 skb_pull(skb, 2);
3554 len = skb->len;
3555
3556 /*
3557 * We can just drop the corrupted I-frame here.
3558 * Receiver will miss it and start proper recovery
3559 * procedures and ask retransmission.
3560 */
3561 if (l2cap_check_fcs(pi, skb))
3562 goto drop;
3563
3564 if (__is_sar_start(control) && __is_iframe(control))
3565 len -= 2;
3566
3567 if (pi->fcs == L2CAP_FCS_CRC16)
3568 len -= 2;
3569
3570 if (len > pi->mps) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003571 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003572 goto drop;
3573 }
3574
3575 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003576 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003577 if (req_seq_offset < 0)
3578 req_seq_offset += 64;
3579
3580 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003581 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003582 if (next_tx_seq_offset < 0)
3583 next_tx_seq_offset += 64;
3584
3585 /* check for invalid req-seq */
3586 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003587 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003588 goto drop;
3589 }
3590
3591 if (__is_iframe(control)) {
3592 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003593 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003594 goto drop;
3595 }
3596
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003597 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003598 } else {
3599 if (len != 0) {
3600 BT_ERR("%d", len);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003601 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003602 goto drop;
3603 }
3604
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003605 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003606 }
3607
3608 return 0;
3609
3610drop:
3611 kfree_skb(skb);
3612 return 0;
3613}
3614
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3616{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003617 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003619 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003620 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003621 u8 tx_seq;
3622 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003624 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003625 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626 BT_DBG("unknown cid 0x%4.4x", cid);
3627 goto drop;
3628 }
3629
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003630 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003631 pi = l2cap_pi(sk);
3632
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633 BT_DBG("sk %p, len %d", sk, skb->len);
3634
3635 if (sk->sk_state != BT_CONNECTED)
3636 goto drop;
3637
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003638 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003639 case L2CAP_MODE_BASIC:
3640 /* If socket recv buffers overflows we drop data here
3641 * which is *bad* because L2CAP has to be reliable.
3642 * But we don't have any other choice. L2CAP doesn't
3643 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003645 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003646 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003648 if (!sock_queue_rcv_skb(sk, skb))
3649 goto done;
3650 break;
3651
3652 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003653 if (!sock_owned_by_user(sk)) {
3654 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003655 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003656 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003657 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003658 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003659
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003660 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003661
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003662 case L2CAP_MODE_STREAMING:
3663 control = get_unaligned_le16(skb->data);
3664 skb_pull(skb, 2);
3665 len = skb->len;
3666
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003667 if (l2cap_check_fcs(pi, skb))
3668 goto drop;
3669
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003670 if (__is_sar_start(control))
3671 len -= 2;
3672
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003673 if (pi->fcs == L2CAP_FCS_CRC16)
3674 len -= 2;
3675
Nathan Holstein51893f82010-06-09 15:46:25 -04003676 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003677 goto drop;
3678
3679 tx_seq = __get_txseq(control);
3680
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003681 if (chan->expected_tx_seq == tx_seq)
3682 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003683 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003684 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003685
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003686 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003687
3688 goto done;
3689
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003690 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003691 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003692 break;
3693 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694
3695drop:
3696 kfree_skb(skb);
3697
3698done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003699 if (sk)
3700 bh_unlock_sock(sk);
3701
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702 return 0;
3703}
3704
Al Viro8e036fc2007-07-29 00:16:36 -07003705static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706{
3707 struct sock *sk;
3708
3709 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3710 if (!sk)
3711 goto drop;
3712
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003713 bh_lock_sock(sk);
3714
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715 BT_DBG("sk %p, len %d", sk, skb->len);
3716
3717 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3718 goto drop;
3719
3720 if (l2cap_pi(sk)->imtu < skb->len)
3721 goto drop;
3722
3723 if (!sock_queue_rcv_skb(sk, skb))
3724 goto done;
3725
3726drop:
3727 kfree_skb(skb);
3728
3729done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003730 if (sk)
3731 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003732 return 0;
3733}
3734
3735static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3736{
3737 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003738 u16 cid, len;
3739 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740
3741 skb_pull(skb, L2CAP_HDR_SIZE);
3742 cid = __le16_to_cpu(lh->cid);
3743 len = __le16_to_cpu(lh->len);
3744
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003745 if (len != skb->len) {
3746 kfree_skb(skb);
3747 return;
3748 }
3749
Linus Torvalds1da177e2005-04-16 15:20:36 -07003750 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3751
3752 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003753 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003754 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755 l2cap_sig_channel(conn, skb);
3756 break;
3757
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003758 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003759 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760 skb_pull(skb, 2);
3761 l2cap_conless_channel(conn, psm, skb);
3762 break;
3763
3764 default:
3765 l2cap_data_channel(conn, cid, skb);
3766 break;
3767 }
3768}
3769
3770/* ---- L2CAP interface with lower layer (HCI) ---- */
3771
3772static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3773{
3774 int exact = 0, lm1 = 0, lm2 = 0;
3775 register struct sock *sk;
3776 struct hlist_node *node;
3777
3778 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003779 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003780
3781 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3782
3783 /* Find listening sockets and check their link_mode */
3784 read_lock(&l2cap_sk_list.lock);
3785 sk_for_each(sk, node, &l2cap_sk_list.head) {
3786 if (sk->sk_state != BT_LISTEN)
3787 continue;
3788
3789 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003790 lm1 |= HCI_LM_ACCEPT;
3791 if (l2cap_pi(sk)->role_switch)
3792 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003793 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003794 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3795 lm2 |= HCI_LM_ACCEPT;
3796 if (l2cap_pi(sk)->role_switch)
3797 lm2 |= HCI_LM_MASTER;
3798 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003799 }
3800 read_unlock(&l2cap_sk_list.lock);
3801
3802 return exact ? lm1 : lm2;
3803}
3804
3805static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3806{
Marcel Holtmann01394182006-07-03 10:02:46 +02003807 struct l2cap_conn *conn;
3808
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3810
Ville Tervoacd7d372011-02-10 22:38:49 -03003811 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003812 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813
3814 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815 conn = l2cap_conn_add(hcon, status);
3816 if (conn)
3817 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003818 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819 l2cap_conn_del(hcon, bt_err(status));
3820
3821 return 0;
3822}
3823
Marcel Holtmann2950f212009-02-12 14:02:50 +01003824static int l2cap_disconn_ind(struct hci_conn *hcon)
3825{
3826 struct l2cap_conn *conn = hcon->l2cap_data;
3827
3828 BT_DBG("hcon %p", hcon);
3829
3830 if (hcon->type != ACL_LINK || !conn)
3831 return 0x13;
3832
3833 return conn->disc_reason;
3834}
3835
3836static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837{
3838 BT_DBG("hcon %p reason %d", hcon, reason);
3839
Ville Tervoacd7d372011-02-10 22:38:49 -03003840 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003841 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842
3843 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003844
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845 return 0;
3846}
3847
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003848static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3849{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003850 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003851 return;
3852
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003853 if (encrypt == 0x00) {
3854 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3855 l2cap_sock_clear_timer(sk);
3856 l2cap_sock_set_timer(sk, HZ * 5);
3857 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3858 __l2cap_sock_close(sk, ECONNREFUSED);
3859 } else {
3860 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3861 l2cap_sock_clear_timer(sk);
3862 }
3863}
3864
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003865static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003866{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003867 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003868 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869
Marcel Holtmann01394182006-07-03 10:02:46 +02003870 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003872
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873 BT_DBG("conn %p", conn);
3874
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003875 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003877 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003878 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003879
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880 bh_lock_sock(sk);
3881
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003882 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3883 bh_unlock_sock(sk);
3884 continue;
3885 }
3886
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003887 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003888 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003889 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003890 bh_unlock_sock(sk);
3891 continue;
3892 }
3893
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003894 if (sk->sk_state == BT_CONNECT) {
3895 if (!status) {
3896 struct l2cap_conn_req req;
3897 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3898 req.psm = l2cap_pi(sk)->psm;
3899
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003900 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003901 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003902
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003903 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003904 L2CAP_CONN_REQ, sizeof(req), &req);
3905 } else {
3906 l2cap_sock_clear_timer(sk);
3907 l2cap_sock_set_timer(sk, HZ / 10);
3908 }
3909 } else if (sk->sk_state == BT_CONNECT2) {
3910 struct l2cap_conn_rsp rsp;
3911 __u16 result;
3912
3913 if (!status) {
3914 sk->sk_state = BT_CONFIG;
3915 result = L2CAP_CR_SUCCESS;
3916 } else {
3917 sk->sk_state = BT_DISCONN;
3918 l2cap_sock_set_timer(sk, HZ / 10);
3919 result = L2CAP_CR_SEC_BLOCK;
3920 }
3921
3922 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3923 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3924 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003925 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003926 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
3927 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928 }
3929
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930 bh_unlock_sock(sk);
3931 }
3932
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003933 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003934
Linus Torvalds1da177e2005-04-16 15:20:36 -07003935 return 0;
3936}
3937
3938static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3939{
3940 struct l2cap_conn *conn = hcon->l2cap_data;
3941
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003942 if (!conn)
3943 conn = l2cap_conn_add(hcon, 0);
3944
3945 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 goto drop;
3947
3948 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3949
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003950 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003952 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003953 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954 int len;
3955
3956 if (conn->rx_len) {
3957 BT_ERR("Unexpected start frame (len %d)", skb->len);
3958 kfree_skb(conn->rx_skb);
3959 conn->rx_skb = NULL;
3960 conn->rx_len = 0;
3961 l2cap_conn_unreliable(conn, ECOMM);
3962 }
3963
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003964 /* Start fragment always begin with Basic L2CAP header */
3965 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966 BT_ERR("Frame is too short (len %d)", skb->len);
3967 l2cap_conn_unreliable(conn, ECOMM);
3968 goto drop;
3969 }
3970
3971 hdr = (struct l2cap_hdr *) skb->data;
3972 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003973 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974
3975 if (len == skb->len) {
3976 /* Complete frame received */
3977 l2cap_recv_frame(conn, skb);
3978 return 0;
3979 }
3980
3981 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3982
3983 if (skb->len > len) {
3984 BT_ERR("Frame is too long (len %d, expected len %d)",
3985 skb->len, len);
3986 l2cap_conn_unreliable(conn, ECOMM);
3987 goto drop;
3988 }
3989
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003990 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003991
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003992 if (chan && chan->sk) {
3993 struct sock *sk = chan->sk;
3994
3995 if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
3996 BT_ERR("Frame exceeding recv MTU (len %d, "
3997 "MTU %d)", len,
3998 l2cap_pi(sk)->imtu);
3999 bh_unlock_sock(sk);
4000 l2cap_conn_unreliable(conn, ECOMM);
4001 goto drop;
4002 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004003 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004004 }
4005
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004007 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4008 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009 goto drop;
4010
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004011 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004012 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013 conn->rx_len = len - skb->len;
4014 } else {
4015 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4016
4017 if (!conn->rx_len) {
4018 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4019 l2cap_conn_unreliable(conn, ECOMM);
4020 goto drop;
4021 }
4022
4023 if (skb->len > conn->rx_len) {
4024 BT_ERR("Fragment is too long (len %d, expected %d)",
4025 skb->len, conn->rx_len);
4026 kfree_skb(conn->rx_skb);
4027 conn->rx_skb = NULL;
4028 conn->rx_len = 0;
4029 l2cap_conn_unreliable(conn, ECOMM);
4030 goto drop;
4031 }
4032
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004033 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004034 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035 conn->rx_len -= skb->len;
4036
4037 if (!conn->rx_len) {
4038 /* Complete frame received */
4039 l2cap_recv_frame(conn, conn->rx_skb);
4040 conn->rx_skb = NULL;
4041 }
4042 }
4043
4044drop:
4045 kfree_skb(skb);
4046 return 0;
4047}
4048
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004049static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004050{
4051 struct sock *sk;
4052 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053
4054 read_lock_bh(&l2cap_sk_list.lock);
4055
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004056 sk_for_each(sk, node, &l2cap_sk_list.head) {
4057 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004059 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 +01004060 batostr(&bt_sk(sk)->src),
4061 batostr(&bt_sk(sk)->dst),
4062 sk->sk_state, __le16_to_cpu(pi->psm),
4063 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004064 pi->imtu, pi->omtu, pi->sec_level,
4065 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004066 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004069
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004070 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071}
4072
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004073static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4074{
4075 return single_open(file, l2cap_debugfs_show, inode->i_private);
4076}
4077
4078static const struct file_operations l2cap_debugfs_fops = {
4079 .open = l2cap_debugfs_open,
4080 .read = seq_read,
4081 .llseek = seq_lseek,
4082 .release = single_release,
4083};
4084
4085static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087static struct hci_proto l2cap_hci_proto = {
4088 .name = "L2CAP",
4089 .id = HCI_PROTO_L2CAP,
4090 .connect_ind = l2cap_connect_ind,
4091 .connect_cfm = l2cap_connect_cfm,
4092 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004093 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004094 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095 .recv_acldata = l2cap_recv_acldata
4096};
4097
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004098int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099{
4100 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004101
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004102 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103 if (err < 0)
4104 return err;
4105
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004106 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004107 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004108 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004109 goto error;
4110 }
4111
4112 err = hci_register_proto(&l2cap_hci_proto);
4113 if (err < 0) {
4114 BT_ERR("L2CAP protocol registration failed");
4115 bt_sock_unregister(BTPROTO_L2CAP);
4116 goto error;
4117 }
4118
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004119 if (bt_debugfs) {
4120 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4121 bt_debugfs, NULL, &l2cap_debugfs_fops);
4122 if (!l2cap_debugfs)
4123 BT_ERR("Failed to create L2CAP debug file");
4124 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126 return 0;
4127
4128error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004129 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004130 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131 return err;
4132}
4133
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004134void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004136 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004138 flush_workqueue(_busy_wq);
4139 destroy_workqueue(_busy_wq);
4140
Linus Torvalds1da177e2005-04-16 15:20:36 -07004141 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4142 BT_ERR("L2CAP protocol unregistration failed");
4143
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004144 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004145}
4146
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004147module_param(disable_ertm, bool, 0644);
4148MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");