blob: b5435cd74f9929ecec38489f6abf177004328203 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
7 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation;
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
16 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090017 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090022 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
23 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 SOFTWARE IS DISCLAIMED.
25*/
26
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020027/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30
31#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080032#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
34#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/poll.h>
38#include <linux/fcntl.h>
39#include <linux/init.h>
40#include <linux/interrupt.h>
41#include <linux/socket.h>
42#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080044#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010045#include <linux/debugfs.h>
46#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030047#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030048#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/sock.h>
50
51#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
57
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020058int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020059
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070060static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010061static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030063static struct workqueue_struct *_busy_wq;
64
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020065struct bt_sock_list l2cap_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070066 .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070067};
68
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030069static void l2cap_busy_work(struct work_struct *work);
70
Linus Torvalds1da177e2005-04-16 15:20:36 -070071static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
72 u8 code, u8 ident, u16 dlen, void *data);
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -030073static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030075static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
76
Marcel Holtmann01394182006-07-03 10:02:46 +020077/* ---- L2CAP channels ---- */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030078static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020079{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030080 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030081
82 list_for_each_entry(c, &conn->chan_l, list) {
83 struct sock *s = c->sk;
84 if (l2cap_pi(s)->dcid == cid)
85 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020086 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030087 return NULL;
88
Marcel Holtmann01394182006-07-03 10:02:46 +020089}
90
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030091static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020092{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030093 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -030094
95 list_for_each_entry(c, &conn->chan_l, list) {
96 struct sock *s = c->sk;
97 if (l2cap_pi(s)->scid == cid)
98 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020099 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300100 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200101}
102
103/* Find channel with given SCID.
104 * Returns locked socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300105static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200106{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300107 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300108
109 read_lock(&conn->chan_lock);
110 c = __l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300111 if (c)
112 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300113 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300114 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200115}
116
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300117static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200118{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300119 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300120
121 list_for_each_entry(c, &conn->chan_l, list) {
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300122 if (c->ident == ident)
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300123 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200124 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300125 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200126}
127
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300128static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200129{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300130 struct l2cap_chan *c;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300131
132 read_lock(&conn->chan_lock);
133 c = __l2cap_get_chan_by_ident(conn, ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300134 if (c)
135 bh_lock_sock(c->sk);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300136 read_unlock(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300137 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200138}
139
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300140static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
Marcel Holtmann01394182006-07-03 10:02:46 +0200141{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300142 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200143
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300144 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300145 if (!__l2cap_get_chan_by_scid(conn, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200146 return cid;
147 }
148
149 return 0;
150}
151
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300152static struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200153{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300154 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200155
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300156 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
157 if (!chan)
158 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200159
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300160 chan->sk = sk;
161
162 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200163}
164
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300165static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200166{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300167 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200168
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300169 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
170 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200171
Marcel Holtmann2950f212009-02-12 14:02:50 +0100172 conn->disc_reason = 0x13;
173
Marcel Holtmann01394182006-07-03 10:02:46 +0200174 l2cap_pi(sk)->conn = conn;
175
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300176 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Ville Tervob62f3282011-02-10 22:38:50 -0300177 if (conn->hcon->type == LE_LINK) {
178 /* LE connection */
179 l2cap_pi(sk)->omtu = L2CAP_LE_DEFAULT_MTU;
180 l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA;
181 l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA;
182 } else {
183 /* Alloc CID for connection-oriented socket */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300184 l2cap_pi(sk)->scid = l2cap_alloc_cid(conn);
Ville Tervob62f3282011-02-10 22:38:50 -0300185 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
186 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200187 } else if (sk->sk_type == SOCK_DGRAM) {
188 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300189 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
190 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200191 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
192 } else {
193 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300194 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
195 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200196 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
197 }
198
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300199 sock_hold(sk);
200
201 list_add(&chan->list, &conn->chan_l);
Marcel Holtmann01394182006-07-03 10:02:46 +0200202}
203
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900204/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200205 * Must be called on the locked socket. */
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300206void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200207{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300208 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200209 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
210 struct sock *parent = bt_sk(sk)->parent;
211
212 l2cap_sock_clear_timer(sk);
213
214 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
215
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900216 if (conn) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300217 /* Delete from channel list */
218 write_lock_bh(&conn->chan_lock);
219 list_del(&chan->list);
220 write_unlock_bh(&conn->chan_lock);
221 __sock_put(sk);
222
Marcel Holtmann01394182006-07-03 10:02:46 +0200223 l2cap_pi(sk)->conn = NULL;
224 hci_conn_put(conn->hcon);
225 }
226
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200227 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200228 sock_set_flag(sk, SOCK_ZAPPED);
229
230 if (err)
231 sk->sk_err = err;
232
233 if (parent) {
234 bt_accept_unlink(sk);
235 parent->sk_data_ready(parent, 0);
236 } else
237 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300238
239 skb_queue_purge(TX_QUEUE(sk));
240
241 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
242 struct srej_list *l, *tmp;
243
244 del_timer(&l2cap_pi(sk)->retrans_timer);
245 del_timer(&l2cap_pi(sk)->monitor_timer);
246 del_timer(&l2cap_pi(sk)->ack_timer);
247
248 skb_queue_purge(SREJ_QUEUE(sk));
249 skb_queue_purge(BUSY_QUEUE(sk));
250
251 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
252 list_del(&l->list);
253 kfree(l);
254 }
255 }
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300256
257 kfree(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200258}
259
Johan Hedberg8556edd32011-01-19 12:06:50 +0530260static inline u8 l2cap_get_auth_type(struct sock *sk)
261{
262 if (sk->sk_type == SOCK_RAW) {
263 switch (l2cap_pi(sk)->sec_level) {
264 case BT_SECURITY_HIGH:
265 return HCI_AT_DEDICATED_BONDING_MITM;
266 case BT_SECURITY_MEDIUM:
267 return HCI_AT_DEDICATED_BONDING;
268 default:
269 return HCI_AT_NO_BONDING;
270 }
271 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
272 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
273 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
274
275 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
276 return HCI_AT_NO_BONDING_MITM;
277 else
278 return HCI_AT_NO_BONDING;
279 } else {
280 switch (l2cap_pi(sk)->sec_level) {
281 case BT_SECURITY_HIGH:
282 return HCI_AT_GENERAL_BONDING_MITM;
283 case BT_SECURITY_MEDIUM:
284 return HCI_AT_GENERAL_BONDING;
285 default:
286 return HCI_AT_NO_BONDING;
287 }
288 }
289}
290
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200291/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100292static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200293{
294 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100295 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200296
Johan Hedberg8556edd32011-01-19 12:06:50 +0530297 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100298
299 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
300 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200301}
302
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200303u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200304{
305 u8 id;
306
307 /* Get next available identificator.
308 * 1 - 128 are used by kernel.
309 * 129 - 199 are reserved.
310 * 200 - 254 are used by utilities like l2ping, etc.
311 */
312
313 spin_lock_bh(&conn->lock);
314
315 if (++conn->tx_ident > 128)
316 conn->tx_ident = 1;
317
318 id = conn->tx_ident;
319
320 spin_unlock_bh(&conn->lock);
321
322 return id;
323}
324
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200325void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200326{
327 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200328 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200329
330 BT_DBG("code 0x%2.2x", code);
331
332 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300333 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200334
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200335 if (lmp_no_flush_capable(conn->hcon->hdev))
336 flags = ACL_START_NO_FLUSH;
337 else
338 flags = ACL_START;
339
340 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200341}
342
Gustavo F. 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 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
399
400 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300401 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300402 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300403 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300404 control |= L2CAP_SUPER_RCV_READY;
405
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300406 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
407
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300408 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300409}
410
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300411static inline int __l2cap_no_conn_pending(struct sock *sk)
412{
413 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
414}
415
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300416static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200417{
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300418 struct sock *sk = chan->sk;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200419 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
420
421 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100422 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
423 return;
424
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300425 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200426 struct l2cap_conn_req req;
427 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
428 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200429
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300430 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300431 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200432
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300433 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
434 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200435 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200436 } else {
437 struct l2cap_info_req req;
438 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
439
440 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
441 conn->info_ident = l2cap_get_ident(conn);
442
443 mod_timer(&conn->info_timer, jiffies +
444 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
445
446 l2cap_send_cmd(conn, conn->info_ident,
447 L2CAP_INFO_REQ, sizeof(req), &req);
448 }
449}
450
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300451static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
452{
453 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300454 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300455 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
456
457 switch (mode) {
458 case L2CAP_MODE_ERTM:
459 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
460 case L2CAP_MODE_STREAMING:
461 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
462 default:
463 return 0x00;
464 }
465}
466
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200467void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300468{
469 struct l2cap_disconn_req req;
470
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300471 if (!conn)
472 return;
473
474 skb_queue_purge(TX_QUEUE(sk));
475
476 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
477 del_timer(&l2cap_pi(sk)->retrans_timer);
478 del_timer(&l2cap_pi(sk)->monitor_timer);
479 del_timer(&l2cap_pi(sk)->ack_timer);
480 }
481
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300482 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
483 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
484 l2cap_send_cmd(conn, l2cap_get_ident(conn),
485 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300486
487 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300488 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300489}
490
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200492static void l2cap_conn_start(struct l2cap_conn *conn)
493{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300494 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200495
496 BT_DBG("conn %p", conn);
497
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300498 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200499
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300500 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300501 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300502
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200503 bh_lock_sock(sk);
504
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300505 if (sk->sk_type != SOCK_SEQPACKET &&
506 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200507 bh_unlock_sock(sk);
508 continue;
509 }
510
511 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300512 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300513
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300514 if (!l2cap_check_security(sk) ||
515 !__l2cap_no_conn_pending(sk)) {
516 bh_unlock_sock(sk);
517 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200518 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300519
520 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
521 conn->feat_mask)
522 && l2cap_pi(sk)->conf_state &
523 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300524 /* __l2cap_sock_close() calls list_del(chan)
525 * so release the lock */
526 read_unlock_bh(&conn->chan_lock);
527 __l2cap_sock_close(sk, ECONNRESET);
528 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300529 bh_unlock_sock(sk);
530 continue;
531 }
532
533 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
534 req.psm = l2cap_pi(sk)->psm;
535
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300536 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300537 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
538
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300539 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
540 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300541
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200542 } else if (sk->sk_state == BT_CONNECT2) {
543 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300544 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200545 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
546 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
547
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100548 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100549 if (bt_sk(sk)->defer_setup) {
550 struct sock *parent = bt_sk(sk)->parent;
551 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
552 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
553 parent->sk_data_ready(parent, 0);
554
555 } else {
556 sk->sk_state = BT_CONFIG;
557 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
558 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
559 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200560 } else {
561 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
562 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
563 }
564
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300565 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
566 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300567
568 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
569 rsp.result != L2CAP_CR_SUCCESS) {
570 bh_unlock_sock(sk);
571 continue;
572 }
573
574 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
575 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300576 l2cap_build_conf_req(chan, buf), buf);
577 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200578 }
579
580 bh_unlock_sock(sk);
581 }
582
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300583 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200584}
585
Ville Tervob62f3282011-02-10 22:38:50 -0300586/* Find socket with cid and source bdaddr.
587 * Returns closest match, locked.
588 */
589static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
590{
591 struct sock *s, *sk = NULL, *sk1 = NULL;
592 struct hlist_node *node;
593
594 read_lock(&l2cap_sk_list.lock);
595
596 sk_for_each(sk, node, &l2cap_sk_list.head) {
597 if (state && sk->sk_state != state)
598 continue;
599
600 if (l2cap_pi(sk)->scid == cid) {
601 /* Exact match. */
602 if (!bacmp(&bt_sk(sk)->src, src))
603 break;
604
605 /* Closest match */
606 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
607 sk1 = sk;
608 }
609 }
610 s = node ? sk : sk1;
611 if (s)
612 bh_lock_sock(s);
613 read_unlock(&l2cap_sk_list.lock);
614
615 return s;
616}
617
618static void l2cap_le_conn_ready(struct l2cap_conn *conn)
619{
Ville Tervob62f3282011-02-10 22:38:50 -0300620 struct sock *parent, *uninitialized_var(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300621 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300622
623 BT_DBG("");
624
625 /* Check if we have socket listening on cid */
626 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
627 conn->src);
628 if (!parent)
629 return;
630
631 /* Check for backlog size */
632 if (sk_acceptq_is_full(parent)) {
633 BT_DBG("backlog full %d", parent->sk_ack_backlog);
634 goto clean;
635 }
636
637 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
638 if (!sk)
639 goto clean;
640
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300641 chan = l2cap_chan_alloc(sk);
642 if (!chan) {
643 l2cap_sock_kill(sk);
644 goto clean;
645 }
646
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300647 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300648
649 hci_conn_hold(conn->hcon);
650
651 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300652
Ville Tervob62f3282011-02-10 22:38:50 -0300653 bacpy(&bt_sk(sk)->src, conn->src);
654 bacpy(&bt_sk(sk)->dst, conn->dst);
655
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300656 bt_accept_enqueue(parent, sk);
657
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300658 __l2cap_chan_add(conn, chan);
659
660 l2cap_pi(sk)->chan = chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300661
662 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
663
664 sk->sk_state = BT_CONNECTED;
665 parent->sk_data_ready(parent, 0);
666
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300667 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300668
669clean:
670 bh_unlock_sock(parent);
671}
672
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200673static void l2cap_conn_ready(struct l2cap_conn *conn)
674{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300675 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200676
677 BT_DBG("conn %p", conn);
678
Ville Tervob62f3282011-02-10 22:38:50 -0300679 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
680 l2cap_le_conn_ready(conn);
681
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300682 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200683
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300684 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300685 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300686
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200687 bh_lock_sock(sk);
688
Ville Tervoacd7d372011-02-10 22:38:49 -0300689 if (conn->hcon->type == LE_LINK) {
690 l2cap_sock_clear_timer(sk);
691 sk->sk_state = BT_CONNECTED;
692 sk->sk_state_change(sk);
693 }
694
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300695 if (sk->sk_type != SOCK_SEQPACKET &&
696 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200697 l2cap_sock_clear_timer(sk);
698 sk->sk_state = BT_CONNECTED;
699 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200700 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300701 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200702
703 bh_unlock_sock(sk);
704 }
705
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300706 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200707}
708
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200709/* Notify sockets that we cannot guaranty reliability anymore */
710static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
711{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300712 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200713
714 BT_DBG("conn %p", conn);
715
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300716 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200717
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300718 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300719 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300720
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100721 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200722 sk->sk_err = err;
723 }
724
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300725 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200726}
727
728static void l2cap_info_timeout(unsigned long arg)
729{
730 struct l2cap_conn *conn = (void *) arg;
731
Marcel Holtmann984947d2009-02-06 23:35:19 +0100732 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100733 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100734
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200735 l2cap_conn_start(conn);
736}
737
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
739{
Marcel Holtmann01394182006-07-03 10:02:46 +0200740 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741
Marcel Holtmann01394182006-07-03 10:02:46 +0200742 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 return conn;
744
Marcel Holtmann01394182006-07-03 10:02:46 +0200745 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
746 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748
749 hcon->l2cap_data = conn;
750 conn->hcon = hcon;
751
Marcel Holtmann01394182006-07-03 10:02:46 +0200752 BT_DBG("hcon %p conn %p", hcon, conn);
753
Ville Tervoacd7d372011-02-10 22:38:49 -0300754 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
755 conn->mtu = hcon->hdev->le_mtu;
756 else
757 conn->mtu = hcon->hdev->acl_mtu;
758
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 conn->src = &hcon->hdev->bdaddr;
760 conn->dst = &hcon->dst;
761
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200762 conn->feat_mask = 0;
763
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300765 rwlock_init(&conn->chan_lock);
766
767 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768
Ville Tervob62f3282011-02-10 22:38:50 -0300769 if (hcon->type != LE_LINK)
770 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000771 (unsigned long) conn);
772
Marcel Holtmann2950f212009-02-12 14:02:50 +0100773 conn->disc_reason = 0x13;
774
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 return conn;
776}
777
Marcel Holtmann01394182006-07-03 10:02:46 +0200778static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779{
Marcel Holtmann01394182006-07-03 10:02:46 +0200780 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300781 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 struct sock *sk;
783
Marcel Holtmann01394182006-07-03 10:02:46 +0200784 if (!conn)
785 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786
787 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
788
Wei Yongjun7585b972009-02-25 18:29:52 +0800789 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
791 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300792 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300793 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300795 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 bh_unlock_sock(sk);
797 l2cap_sock_kill(sk);
798 }
799
Dave Young8e8440f2008-03-03 12:18:55 -0800800 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
801 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800802
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 hcon->l2cap_data = NULL;
804 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805}
806
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300807static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300809 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300810 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300811 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812}
813
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815
816/* Find socket with psm and source bdaddr.
817 * Returns closest match.
818 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000819static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820{
821 struct sock *sk = NULL, *sk1 = NULL;
822 struct hlist_node *node;
823
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000824 read_lock(&l2cap_sk_list.lock);
825
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 sk_for_each(sk, node, &l2cap_sk_list.head) {
827 if (state && sk->sk_state != state)
828 continue;
829
830 if (l2cap_pi(sk)->psm == psm) {
831 /* Exact match. */
832 if (!bacmp(&bt_sk(sk)->src, src))
833 break;
834
835 /* Closest match */
836 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
837 sk1 = sk;
838 }
839 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000842
843 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844}
845
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200846int l2cap_do_connect(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847{
848 bdaddr_t *src = &bt_sk(sk)->src;
849 bdaddr_t *dst = &bt_sk(sk)->dst;
850 struct l2cap_conn *conn;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300851 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 struct hci_conn *hcon;
853 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200854 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200855 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100857 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
858 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300860 hdev = hci_get_route(dst, src);
861 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 return -EHOSTUNREACH;
863
864 hci_dev_lock_bh(hdev);
865
Johan Hedberg8556edd32011-01-19 12:06:50 +0530866 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200867
Ville Tervoacd7d372011-02-10 22:38:49 -0300868 if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
869 hcon = hci_connect(hdev, LE_LINK, dst,
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100870 l2cap_pi(sk)->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300871 else
872 hcon = hci_connect(hdev, ACL_LINK, dst,
873 l2cap_pi(sk)->sec_level, auth_type);
874
Ville Tervo30e76272011-02-22 16:10:53 -0300875 if (IS_ERR(hcon)) {
876 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300878 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879
880 conn = l2cap_conn_add(hcon, 0);
881 if (!conn) {
882 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300883 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 goto done;
885 }
886
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300887 chan = l2cap_chan_alloc(sk);
888 if (!chan) {
889 hci_conn_put(hcon);
890 err = -ENOMEM;
891 goto done;
892 }
893
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 /* Update source addr of the socket */
895 bacpy(src, conn->src);
896
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300897 l2cap_chan_add(conn, chan);
898
899 l2cap_pi(sk)->chan = chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900
901 sk->sk_state = BT_CONNECT;
902 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
903
904 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300905 if (sk->sk_type != SOCK_SEQPACKET &&
906 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530908 if (l2cap_check_security(sk))
909 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200910 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300911 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 }
913
Ville Tervo30e76272011-02-22 16:10:53 -0300914 err = 0;
915
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916done:
917 hci_dev_unlock_bh(hdev);
918 hci_dev_put(hdev);
919 return err;
920}
921
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200922int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300923{
924 DECLARE_WAITQUEUE(wait, current);
925 int err = 0;
926 int timeo = HZ/5;
927
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200928 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300929 while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
930 set_current_state(TASK_INTERRUPTIBLE);
931
932 if (!timeo)
933 timeo = HZ/5;
934
935 if (signal_pending(current)) {
936 err = sock_intr_errno(timeo);
937 break;
938 }
939
940 release_sock(sk);
941 timeo = schedule_timeout(timeo);
942 lock_sock(sk);
943
944 err = sock_error(sk);
945 if (err)
946 break;
947 }
948 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200949 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300950 return err;
951}
952
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300953static void l2cap_monitor_timeout(unsigned long arg)
954{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300955 struct l2cap_chan *chan = (void *) arg;
956 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300957
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300958 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300959
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300960 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300961 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300962 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200963 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300964 return;
965 }
966
967 l2cap_pi(sk)->retry_count++;
968 __mod_monitor_timer();
969
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300970 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300971 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300972}
973
974static void l2cap_retrans_timeout(unsigned long arg)
975{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300976 struct l2cap_chan *chan = (void *) arg;
977 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300978
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300979 BT_DBG("sk %p", sk);
980
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300981 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300982 l2cap_pi(sk)->retry_count = 1;
983 __mod_monitor_timer();
984
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300985 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300986
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300987 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300988 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300989}
990
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300991static void l2cap_drop_acked_frames(struct sock *sk)
992{
993 struct sk_buff *skb;
994
Gustavo F. Padovan812e7372010-05-01 16:15:42 -0300995 while ((skb = skb_peek(TX_QUEUE(sk))) &&
996 l2cap_pi(sk)->unacked_frames) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300997 if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
998 break;
999
1000 skb = skb_dequeue(TX_QUEUE(sk));
1001 kfree_skb(skb);
1002
1003 l2cap_pi(sk)->unacked_frames--;
1004 }
1005
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001006 if (!l2cap_pi(sk)->unacked_frames)
1007 del_timer(&l2cap_pi(sk)->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001008}
1009
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001010void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001011{
1012 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001013 struct hci_conn *hcon = pi->conn->hcon;
1014 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001015
1016 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1017
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001018 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
1019 flags = ACL_START_NO_FLUSH;
1020 else
1021 flags = ACL_START;
1022
1023 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001024}
1025
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001026void l2cap_streaming_send(struct sock *sk)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001027{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001028 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001029 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001030 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001031
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001032 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
1033 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001034 control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001035 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001036
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001037 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001038 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1039 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001040 }
1041
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001042 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001043
1044 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001045 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001046}
1047
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001048static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001049{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001050 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001051 struct l2cap_pinfo *pi = l2cap_pi(sk);
1052 struct sk_buff *skb, *tx_skb;
1053 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001054
1055 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001056 if (!skb)
1057 return;
1058
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001059 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001060 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001061 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001062
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001063 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1064 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001065
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001066 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001067
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001068 if (pi->remote_max_tx &&
1069 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001070 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001071 return;
1072 }
1073
1074 tx_skb = skb_clone(skb, GFP_ATOMIC);
1075 bt_cb(skb)->retries++;
1076 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001077
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001078 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001079 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001080 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001081 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001082
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001083 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1084 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001085
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001086 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1087
1088 if (pi->fcs == L2CAP_FCS_CRC16) {
1089 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1090 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1091 }
1092
1093 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001094}
1095
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001096int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001097{
1098 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001099 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001100 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001101 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001102 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001103
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001104 if (sk->sk_state != BT_CONNECTED)
1105 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001106
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001107 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001108
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001109 if (pi->remote_max_tx &&
1110 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001111 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001112 break;
1113 }
1114
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001115 tx_skb = skb_clone(skb, GFP_ATOMIC);
1116
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001117 bt_cb(skb)->retries++;
1118
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001119 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001120 control &= L2CAP_CTRL_SAR;
1121
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001122 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001123 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001124 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001125 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001126 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001127 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1128 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1129
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001130
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001131 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001132 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1133 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1134 }
1135
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001136 l2cap_do_send(sk, tx_skb);
1137
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001138 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001139
1140 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1141 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1142
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301143 if (bt_cb(skb)->retries == 1)
1144 pi->unacked_frames++;
1145
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001146 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001147
1148 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1149 sk->sk_send_head = NULL;
1150 else
1151 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001152
1153 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001154 }
1155
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001156 return nsent;
1157}
1158
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001159static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001160{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001161 struct sock *sk = chan->sk;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001162 struct l2cap_pinfo *pi = l2cap_pi(sk);
1163 int ret;
1164
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001165 if (!skb_queue_empty(TX_QUEUE(sk)))
1166 sk->sk_send_head = TX_QUEUE(sk)->next;
1167
1168 pi->next_tx_seq = pi->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001169 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001170 return ret;
1171}
1172
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001173static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001174{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001175 struct sock *sk = chan->sk;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001176 u16 control = 0;
1177
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001178 control |= l2cap_pi(sk)->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001179
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001180 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001181 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001182 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1183 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001184 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001185 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001186
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001187 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001188 return;
1189
1190 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001191 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001192}
1193
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001194static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001195{
1196 struct srej_list *tail;
1197 u16 control;
1198
1199 control = L2CAP_SUPER_SELECT_REJECT;
1200 control |= L2CAP_CTRL_FINAL;
1201
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001202 tail = list_entry(SREJ_LIST(chan->sk)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001203 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1204
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001205 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001206}
1207
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001208static 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 -07001209{
1210 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001211 struct sk_buff **frag;
1212 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001214 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001215 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216
1217 sent += count;
1218 len -= count;
1219
1220 /* Continuation fragments (no L2CAP header) */
1221 frag = &skb_shinfo(skb)->frag_list;
1222 while (len) {
1223 count = min_t(unsigned int, conn->mtu, len);
1224
1225 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1226 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001227 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001228 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1229 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
1231 sent += count;
1232 len -= count;
1233
1234 frag = &(*frag)->next;
1235 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236
1237 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001238}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001240struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001241{
1242 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1243 struct sk_buff *skb;
1244 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1245 struct l2cap_hdr *lh;
1246
1247 BT_DBG("sk %p len %d", sk, (int)len);
1248
1249 count = min_t(unsigned int, (conn->mtu - hlen), len);
1250 skb = bt_skb_send_alloc(sk, count + hlen,
1251 msg->msg_flags & MSG_DONTWAIT, &err);
1252 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001253 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001254
1255 /* Create L2CAP header */
1256 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1257 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1258 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1259 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1260
1261 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1262 if (unlikely(err < 0)) {
1263 kfree_skb(skb);
1264 return ERR_PTR(err);
1265 }
1266 return skb;
1267}
1268
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001269struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001270{
1271 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1272 struct sk_buff *skb;
1273 int err, count, hlen = L2CAP_HDR_SIZE;
1274 struct l2cap_hdr *lh;
1275
1276 BT_DBG("sk %p len %d", sk, (int)len);
1277
1278 count = min_t(unsigned int, (conn->mtu - hlen), len);
1279 skb = bt_skb_send_alloc(sk, count + hlen,
1280 msg->msg_flags & MSG_DONTWAIT, &err);
1281 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001282 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001283
1284 /* Create L2CAP header */
1285 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1286 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1287 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1288
1289 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1290 if (unlikely(err < 0)) {
1291 kfree_skb(skb);
1292 return ERR_PTR(err);
1293 }
1294 return skb;
1295}
1296
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001297struct 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 -03001298{
1299 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1300 struct sk_buff *skb;
1301 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1302 struct l2cap_hdr *lh;
1303
1304 BT_DBG("sk %p len %d", sk, (int)len);
1305
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001306 if (!conn)
1307 return ERR_PTR(-ENOTCONN);
1308
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001309 if (sdulen)
1310 hlen += 2;
1311
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001312 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1313 hlen += 2;
1314
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001315 count = min_t(unsigned int, (conn->mtu - hlen), len);
1316 skb = bt_skb_send_alloc(sk, count + hlen,
1317 msg->msg_flags & MSG_DONTWAIT, &err);
1318 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001319 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001320
1321 /* Create L2CAP header */
1322 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1323 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1324 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1325 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001326 if (sdulen)
1327 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001328
1329 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1330 if (unlikely(err < 0)) {
1331 kfree_skb(skb);
1332 return ERR_PTR(err);
1333 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001334
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001335 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1336 put_unaligned_le16(0, skb_put(skb, 2));
1337
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001338 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001339 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340}
1341
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001342int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001343{
1344 struct l2cap_pinfo *pi = l2cap_pi(sk);
1345 struct sk_buff *skb;
1346 struct sk_buff_head sar_queue;
1347 u16 control;
1348 size_t size = 0;
1349
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001350 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001351 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001352 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001353 if (IS_ERR(skb))
1354 return PTR_ERR(skb);
1355
1356 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001357 len -= pi->remote_mps;
1358 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001359
1360 while (len > 0) {
1361 size_t buflen;
1362
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001363 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001364 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001365 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001366 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001367 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001368 buflen = len;
1369 }
1370
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001371 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001372 if (IS_ERR(skb)) {
1373 skb_queue_purge(&sar_queue);
1374 return PTR_ERR(skb);
1375 }
1376
1377 __skb_queue_tail(&sar_queue, skb);
1378 len -= buflen;
1379 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001380 }
1381 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1382 if (sk->sk_send_head == NULL)
1383 sk->sk_send_head = sar_queue.next;
1384
1385 return size;
1386}
1387
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388static void l2cap_chan_ready(struct sock *sk)
1389{
1390 struct sock *parent = bt_sk(sk)->parent;
1391
1392 BT_DBG("sk %p, parent %p", sk, parent);
1393
1394 l2cap_pi(sk)->conf_state = 0;
1395 l2cap_sock_clear_timer(sk);
1396
1397 if (!parent) {
1398 /* Outgoing channel.
1399 * Wake up socket sleeping on connect.
1400 */
1401 sk->sk_state = BT_CONNECTED;
1402 sk->sk_state_change(sk);
1403 } else {
1404 /* Incoming channel.
1405 * Wake up socket sleeping on accept.
1406 */
1407 parent->sk_data_ready(parent, 0);
1408 }
1409}
1410
1411/* Copy frame to all raw sockets on that connection */
1412static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1413{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001415 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416
1417 BT_DBG("conn %p", conn);
1418
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001419 read_lock(&conn->chan_lock);
1420 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001421 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 if (sk->sk_type != SOCK_RAW)
1423 continue;
1424
1425 /* Don't send frame to the socket it came from */
1426 if (skb->sk == sk)
1427 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001428 nskb = skb_clone(skb, GFP_ATOMIC);
1429 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 continue;
1431
1432 if (sock_queue_rcv_skb(sk, nskb))
1433 kfree_skb(nskb);
1434 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001435 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436}
1437
1438/* ---- L2CAP signalling commands ---- */
1439static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1440 u8 code, u8 ident, u16 dlen, void *data)
1441{
1442 struct sk_buff *skb, **frag;
1443 struct l2cap_cmd_hdr *cmd;
1444 struct l2cap_hdr *lh;
1445 int len, count;
1446
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001447 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1448 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449
1450 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1451 count = min_t(unsigned int, conn->mtu, len);
1452
1453 skb = bt_skb_alloc(count, GFP_ATOMIC);
1454 if (!skb)
1455 return NULL;
1456
1457 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001458 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001459
1460 if (conn->hcon->type == LE_LINK)
1461 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1462 else
1463 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
1465 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1466 cmd->code = code;
1467 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001468 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469
1470 if (dlen) {
1471 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1472 memcpy(skb_put(skb, count), data, count);
1473 data += count;
1474 }
1475
1476 len -= skb->len;
1477
1478 /* Continuation fragments (no L2CAP header) */
1479 frag = &skb_shinfo(skb)->frag_list;
1480 while (len) {
1481 count = min_t(unsigned int, conn->mtu, len);
1482
1483 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1484 if (!*frag)
1485 goto fail;
1486
1487 memcpy(skb_put(*frag, count), data, count);
1488
1489 len -= count;
1490 data += count;
1491
1492 frag = &(*frag)->next;
1493 }
1494
1495 return skb;
1496
1497fail:
1498 kfree_skb(skb);
1499 return NULL;
1500}
1501
1502static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1503{
1504 struct l2cap_conf_opt *opt = *ptr;
1505 int len;
1506
1507 len = L2CAP_CONF_OPT_SIZE + opt->len;
1508 *ptr += len;
1509
1510 *type = opt->type;
1511 *olen = opt->len;
1512
1513 switch (opt->len) {
1514 case 1:
1515 *val = *((u8 *) opt->val);
1516 break;
1517
1518 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001519 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 break;
1521
1522 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001523 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 break;
1525
1526 default:
1527 *val = (unsigned long) opt->val;
1528 break;
1529 }
1530
1531 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1532 return len;
1533}
1534
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1536{
1537 struct l2cap_conf_opt *opt = *ptr;
1538
1539 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1540
1541 opt->type = type;
1542 opt->len = len;
1543
1544 switch (len) {
1545 case 1:
1546 *((u8 *) opt->val) = val;
1547 break;
1548
1549 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001550 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 break;
1552
1553 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001554 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 break;
1556
1557 default:
1558 memcpy(opt->val, (void *) val, len);
1559 break;
1560 }
1561
1562 *ptr += L2CAP_CONF_OPT_SIZE + len;
1563}
1564
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001565static void l2cap_ack_timeout(unsigned long arg)
1566{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001567 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001568
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001569 bh_lock_sock(chan->sk);
1570 l2cap_send_ack(chan);
1571 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001572}
1573
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001574static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001575{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001576 struct sock *sk = chan->sk;
1577
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001578 l2cap_pi(sk)->expected_ack_seq = 0;
1579 l2cap_pi(sk)->unacked_frames = 0;
1580 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03001581 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001582 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001583
1584 setup_timer(&l2cap_pi(sk)->retrans_timer,
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001585 l2cap_retrans_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001586 setup_timer(&l2cap_pi(sk)->monitor_timer,
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001587 l2cap_monitor_timeout, (unsigned long) chan);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001588 setup_timer(&l2cap_pi(sk)->ack_timer,
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001589 l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001590
1591 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001592 __skb_queue_head_init(BUSY_QUEUE(sk));
1593
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:
1815 pi->remote_tx_win = rfc.txwin_size;
1816 pi->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
1821 pi->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
1839 pi->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. Padovan9b108fc2010-05-20 16:21:53 -03002296 l2cap_send_disconn_req(conn, sk, 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. Padovan1c2acff2009-08-20 22:25:57 -03002314 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002315 l2cap_pi(sk)->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. Padovan9b108fc2010-05-20 16:21:53 -03002368 l2cap_send_disconn_req(conn, sk, 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. Padovan9b108fc2010-05-20 16:21:53 -03002377 l2cap_send_disconn_req(conn, sk, 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. Padovan9b108fc2010-05-20 16:21:53 -03002392 l2cap_send_disconn_req(conn, sk, 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. Padovan0565c1c2009-10-03 02:34:36 -03002405 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002406 l2cap_pi(sk)->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. Padovan525cd182011-03-25 19:43:39 -03002792 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002793 u16 control = 0;
2794
2795 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002796
2797 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2798
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002799 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002800 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002801 l2cap_send_sframe(chan, control);
2802 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002803 }
2804
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002805 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2806 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002807
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002808 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002809
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002810 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002811 pi->frames_sent == 0) {
2812 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002813 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002814 }
2815}
2816
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002817static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002818{
2819 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002820 struct l2cap_pinfo *pi = l2cap_pi(sk);
2821 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002822
2823 bt_cb(skb)->tx_seq = tx_seq;
2824 bt_cb(skb)->sar = sar;
2825
2826 next_skb = skb_peek(SREJ_QUEUE(sk));
2827 if (!next_skb) {
2828 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002829 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002830 }
2831
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002832 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
2833 if (tx_seq_offset < 0)
2834 tx_seq_offset += 64;
2835
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002836 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002837 if (bt_cb(next_skb)->tx_seq == tx_seq)
2838 return -EINVAL;
2839
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002840 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
2841 pi->buffer_seq) % 64;
2842 if (next_tx_seq_offset < 0)
2843 next_tx_seq_offset += 64;
2844
2845 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002846 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002847 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002848 }
2849
2850 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
2851 break;
2852
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002853 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002854
2855 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002856
2857 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002858}
2859
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002860static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002861{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002862 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002863 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002864 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002865
2866 switch (control & L2CAP_CTRL_SAR) {
2867 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002868 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002869 goto drop;
2870
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002871 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002872 if (!err)
2873 return err;
2874
2875 break;
2876
2877 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002878 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002879 goto drop;
2880
2881 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002882
2883 if (pi->sdu_len > pi->imtu)
2884 goto disconnect;
2885
2886 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002887 if (!pi->sdu)
2888 return -ENOMEM;
2889
2890 /* pull sdu_len bytes only after alloc, because of Local Busy
2891 * condition we have to be sure that this will be executed
2892 * only once, i.e., when alloc does not fail */
2893 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002894
2895 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2896
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002897 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002898 pi->partial_sdu_len = skb->len;
2899 break;
2900
2901 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002902 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002903 goto disconnect;
2904
2905 if (!pi->sdu)
2906 goto disconnect;
2907
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002908 pi->partial_sdu_len += skb->len;
2909 if (pi->partial_sdu_len > pi->sdu_len)
2910 goto drop;
2911
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002912 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2913
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002914 break;
2915
2916 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002917 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002918 goto disconnect;
2919
2920 if (!pi->sdu)
2921 goto disconnect;
2922
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002923 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002924 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002925
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002926 if (pi->partial_sdu_len > pi->imtu)
2927 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002928
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002929 if (pi->partial_sdu_len != pi->sdu_len)
2930 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002931
2932 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002933 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002934
2935 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002936 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002937 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002938 return -ENOMEM;
2939 }
2940
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002941 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002942 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002943 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002944 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002945 return err;
2946 }
2947
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002948 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2949 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002950
2951 kfree_skb(pi->sdu);
2952 break;
2953 }
2954
2955 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002956 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002957
2958drop:
2959 kfree_skb(pi->sdu);
2960 pi->sdu = NULL;
2961
2962disconnect:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002963 l2cap_send_disconn_req(pi->conn, chan->sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002964 kfree_skb(skb);
2965 return 0;
2966}
2967
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002968static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002969{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002970 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002971 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002972 struct sk_buff *skb;
2973 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002974 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002975
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002976 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
2977 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002978 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002979 if (err < 0) {
2980 skb_queue_head(BUSY_QUEUE(sk), skb);
2981 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002982 }
2983
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002984 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002985 }
2986
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002987 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002988 goto done;
2989
2990 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2991 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002992 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002993 l2cap_pi(sk)->retry_count = 1;
2994
2995 del_timer(&pi->retrans_timer);
2996 __mod_monitor_timer();
2997
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002998 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002999
3000done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003001 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
3002 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003003
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003004 BT_DBG("sk %p, Exit local busy", sk);
3005
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003006 return 0;
3007}
3008
3009static void l2cap_busy_work(struct work_struct *work)
3010{
3011 DECLARE_WAITQUEUE(wait, current);
3012 struct l2cap_pinfo *pi =
3013 container_of(work, struct l2cap_pinfo, busy_work);
3014 struct sock *sk = (struct sock *)pi;
3015 int n_tries = 0, timeo = HZ/5, err;
3016 struct sk_buff *skb;
3017
3018 lock_sock(sk);
3019
3020 add_wait_queue(sk_sleep(sk), &wait);
3021 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
3022 set_current_state(TASK_INTERRUPTIBLE);
3023
3024 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3025 err = -EBUSY;
3026 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
3027 break;
3028 }
3029
3030 if (!timeo)
3031 timeo = HZ/5;
3032
3033 if (signal_pending(current)) {
3034 err = sock_intr_errno(timeo);
3035 break;
3036 }
3037
3038 release_sock(sk);
3039 timeo = schedule_timeout(timeo);
3040 lock_sock(sk);
3041
3042 err = sock_error(sk);
3043 if (err)
3044 break;
3045
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003046 if (l2cap_try_push_rx_skb(l2cap_pi(sk)->chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003047 break;
3048 }
3049
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003050 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003051 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003052
3053 release_sock(sk);
3054}
3055
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003056static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003057{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003058 struct sock *sk = chan->sk;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003059 struct l2cap_pinfo *pi = l2cap_pi(sk);
3060 int sctrl, err;
3061
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003062 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003063 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3064 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003065 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003066
3067
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003068 }
3069
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003070 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003071 if (err >= 0) {
3072 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3073 return err;
3074 }
3075
3076 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003077 BT_DBG("sk %p, Enter local busy", sk);
3078
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003079 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003080 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3081 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3082
3083 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3084 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003085 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003086
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003087 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003088
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003089 del_timer(&pi->ack_timer);
3090
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003091 queue_work(_busy_wq, &pi->busy_work);
3092
3093 return err;
3094}
3095
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003096static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003097{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003098 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003099 struct sk_buff *_skb;
3100 int err = -EINVAL;
3101
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003102 /*
3103 * TODO: We have to notify the userland if some data is lost with the
3104 * Streaming Mode.
3105 */
3106
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003107 switch (control & L2CAP_CTRL_SAR) {
3108 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003109 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003110 kfree_skb(pi->sdu);
3111 break;
3112 }
3113
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003114 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003115 if (!err)
3116 return 0;
3117
3118 break;
3119
3120 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003121 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003122 kfree_skb(pi->sdu);
3123 break;
3124 }
3125
3126 pi->sdu_len = get_unaligned_le16(skb->data);
3127 skb_pull(skb, 2);
3128
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003129 if (pi->sdu_len > pi->imtu) {
3130 err = -EMSGSIZE;
3131 break;
3132 }
3133
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003134 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3135 if (!pi->sdu) {
3136 err = -ENOMEM;
3137 break;
3138 }
3139
3140 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3141
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003142 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003143 pi->partial_sdu_len = skb->len;
3144 err = 0;
3145 break;
3146
3147 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003148 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003149 break;
3150
3151 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3152
3153 pi->partial_sdu_len += skb->len;
3154 if (pi->partial_sdu_len > pi->sdu_len)
3155 kfree_skb(pi->sdu);
3156 else
3157 err = 0;
3158
3159 break;
3160
3161 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003162 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003163 break;
3164
3165 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3166
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003167 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003168 pi->partial_sdu_len += skb->len;
3169
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003170 if (pi->partial_sdu_len > pi->imtu)
3171 goto drop;
3172
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003173 if (pi->partial_sdu_len == pi->sdu_len) {
3174 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003175 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003176 if (err < 0)
3177 kfree_skb(_skb);
3178 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003179 err = 0;
3180
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003181drop:
3182 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003183 break;
3184 }
3185
3186 kfree_skb(skb);
3187 return err;
3188}
3189
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003190static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003191{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003192 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003193 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003194 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003195
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003196 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003197 if (bt_cb(skb)->tx_seq != tx_seq)
3198 break;
3199
3200 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003201 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003202 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003203 l2cap_pi(sk)->buffer_seq_srej =
3204 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003205 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003206 }
3207}
3208
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003209static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003210{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003211 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003212 struct srej_list *l, *tmp;
3213 u16 control;
3214
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003215 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003216 if (l->tx_seq == tx_seq) {
3217 list_del(&l->list);
3218 kfree(l);
3219 return;
3220 }
3221 control = L2CAP_SUPER_SELECT_REJECT;
3222 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003223 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003224 list_del(&l->list);
3225 list_add_tail(&l->list, SREJ_LIST(sk));
3226 }
3227}
3228
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003229static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003230{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003231 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003232 struct l2cap_pinfo *pi = l2cap_pi(sk);
3233 struct srej_list *new;
3234 u16 control;
3235
3236 while (tx_seq != pi->expected_tx_seq) {
3237 control = L2CAP_SUPER_SELECT_REJECT;
3238 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003239 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003240
3241 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003242 new->tx_seq = pi->expected_tx_seq;
3243 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003244 list_add_tail(&new->list, SREJ_LIST(sk));
3245 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003246 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003247}
3248
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003249static 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 -03003250{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003251 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003252 struct l2cap_pinfo *pi = l2cap_pi(sk);
3253 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003254 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003255 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003256 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003257 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003258 int err = 0;
3259
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003260 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3261 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003262
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003263 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003264 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003265 del_timer(&pi->monitor_timer);
3266 if (pi->unacked_frames > 0)
3267 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003268 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003269 }
3270
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003271 pi->expected_ack_seq = req_seq;
3272 l2cap_drop_acked_frames(sk);
3273
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003274 if (tx_seq == pi->expected_tx_seq)
3275 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003276
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003277 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3278 if (tx_seq_offset < 0)
3279 tx_seq_offset += 64;
3280
3281 /* invalid tx_seq */
3282 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003283 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003284 goto drop;
3285 }
3286
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003287 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003288 goto drop;
3289
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003290 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003291 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003292
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003293 first = list_first_entry(SREJ_LIST(sk),
3294 struct srej_list, list);
3295 if (tx_seq == first->tx_seq) {
3296 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003297 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003298
3299 list_del(&first->list);
3300 kfree(first);
3301
3302 if (list_empty(SREJ_LIST(sk))) {
3303 pi->buffer_seq = pi->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003304 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3305 l2cap_send_ack(chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003306 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003307 }
3308 } else {
3309 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003310
3311 /* duplicated tx_seq */
3312 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
3313 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003314
3315 list_for_each_entry(l, SREJ_LIST(sk), list) {
3316 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003317 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003318 return 0;
3319 }
3320 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003321 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003322 }
3323 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003324 expected_tx_seq_offset =
3325 (pi->expected_tx_seq - pi->buffer_seq) % 64;
3326 if (expected_tx_seq_offset < 0)
3327 expected_tx_seq_offset += 64;
3328
3329 /* duplicated tx_seq */
3330 if (tx_seq_offset < expected_tx_seq_offset)
3331 goto drop;
3332
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003333 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003334
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003335 BT_DBG("sk %p, Enter SREJ", sk);
3336
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003337 INIT_LIST_HEAD(SREJ_LIST(sk));
3338 pi->buffer_seq_srej = pi->buffer_seq;
3339
3340 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003341 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003342 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3343
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003344 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003345
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003346 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003347
3348 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003349 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003350 return 0;
3351
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003352expected:
3353 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3354
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003355 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003356 bt_cb(skb)->tx_seq = tx_seq;
3357 bt_cb(skb)->sar = sar;
3358 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003359 return 0;
3360 }
3361
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003362 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003363 if (err < 0)
3364 return 0;
3365
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003366 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003367 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3368 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003369 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003370 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003371 }
3372
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003373 __mod_ack_timer();
3374
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003375 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
3376 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003377 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003378
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003379 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003380
3381drop:
3382 kfree_skb(skb);
3383 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003384}
3385
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003386static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003387{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003388 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003389 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003390
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003391 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3392 rx_control);
3393
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003394 pi->expected_ack_seq = __get_reqseq(rx_control);
3395 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003396
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003397 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003398 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3399 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3400 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003401 (pi->unacked_frames > 0))
3402 __mod_retrans_timer();
3403
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003404 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3405 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003406 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003407 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003408 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003409
3410 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003411 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003412
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003413 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3414 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003415 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003416 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003417
3418 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003419 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003420 (pi->unacked_frames > 0))
3421 __mod_retrans_timer();
3422
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003423 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3424 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3425 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003426 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003427 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003428 }
3429}
3430
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003431static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003432{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003433 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003434 u8 tx_seq = __get_reqseq(rx_control);
3435
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003436 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003437
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003438 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003439
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03003440 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003441 l2cap_drop_acked_frames(chan->sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003442
3443 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003444 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3445 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003446 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003447 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003448 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003449 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003450
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003451 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3452 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003453 }
3454}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003455static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003456{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003457 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003458 u8 tx_seq = __get_reqseq(rx_control);
3459
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003460 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003461
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003462 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003463
3464 if (rx_control & L2CAP_CTRL_POLL) {
3465 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003466 l2cap_drop_acked_frames(chan->sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003467
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003468 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3469 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003470
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003471 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003472
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003473 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003474 pi->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003475 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003476 }
3477 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003478 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003479 pi->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003480 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003481 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003482 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003483 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003484 l2cap_retransmit_one_frame(chan, tx_seq);
3485 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003486 pi->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003487 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003488 }
3489 }
3490}
3491
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003492static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003493{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003494 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003495 u8 tx_seq = __get_reqseq(rx_control);
3496
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003497 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003498
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003499 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003500 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003501 l2cap_drop_acked_frames(chan->sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003502
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003503 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003504 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003505
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003506 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003507 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003508 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003509 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003510 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003511 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003512
3513 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003514 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003515 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003516 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003517}
3518
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003519static 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 -03003520{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003521 struct sock *sk = chan->sk;
3522
3523 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003524
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003525 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003526 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003527 del_timer(&l2cap_pi(sk)->monitor_timer);
3528 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003529 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003530 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003531 }
3532
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003533 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3534 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003535 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003536 break;
3537
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003538 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003539 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003540 break;
3541
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003542 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003543 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003544 break;
3545
3546 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003547 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003548 break;
3549 }
3550
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003551 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003552 return 0;
3553}
3554
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003555static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3556{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003557 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003558 struct l2cap_pinfo *pi = l2cap_pi(sk);
3559 u16 control;
3560 u8 req_seq;
3561 int len, next_tx_seq_offset, req_seq_offset;
3562
3563 control = get_unaligned_le16(skb->data);
3564 skb_pull(skb, 2);
3565 len = skb->len;
3566
3567 /*
3568 * We can just drop the corrupted I-frame here.
3569 * Receiver will miss it and start proper recovery
3570 * procedures and ask retransmission.
3571 */
3572 if (l2cap_check_fcs(pi, skb))
3573 goto drop;
3574
3575 if (__is_sar_start(control) && __is_iframe(control))
3576 len -= 2;
3577
3578 if (pi->fcs == L2CAP_FCS_CRC16)
3579 len -= 2;
3580
3581 if (len > pi->mps) {
3582 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3583 goto drop;
3584 }
3585
3586 req_seq = __get_reqseq(control);
3587 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
3588 if (req_seq_offset < 0)
3589 req_seq_offset += 64;
3590
3591 next_tx_seq_offset =
3592 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
3593 if (next_tx_seq_offset < 0)
3594 next_tx_seq_offset += 64;
3595
3596 /* check for invalid req-seq */
3597 if (req_seq_offset > next_tx_seq_offset) {
3598 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3599 goto drop;
3600 }
3601
3602 if (__is_iframe(control)) {
3603 if (len < 0) {
3604 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3605 goto drop;
3606 }
3607
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003608 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003609 } else {
3610 if (len != 0) {
3611 BT_ERR("%d", len);
3612 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3613 goto drop;
3614 }
3615
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003616 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003617 }
3618
3619 return 0;
3620
3621drop:
3622 kfree_skb(skb);
3623 return 0;
3624}
3625
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3627{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003628 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003630 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003631 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003632 u8 tx_seq;
3633 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003635 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003636 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637 BT_DBG("unknown cid 0x%4.4x", cid);
3638 goto drop;
3639 }
3640
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003641 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003642 pi = l2cap_pi(sk);
3643
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644 BT_DBG("sk %p, len %d", sk, skb->len);
3645
3646 if (sk->sk_state != BT_CONNECTED)
3647 goto drop;
3648
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003649 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003650 case L2CAP_MODE_BASIC:
3651 /* If socket recv buffers overflows we drop data here
3652 * which is *bad* because L2CAP has to be reliable.
3653 * But we don't have any other choice. L2CAP doesn't
3654 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003655
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003656 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003657 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003658
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003659 if (!sock_queue_rcv_skb(sk, skb))
3660 goto done;
3661 break;
3662
3663 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003664 if (!sock_owned_by_user(sk)) {
3665 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003666 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003667 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003668 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003669 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003670
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003671 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003672
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003673 case L2CAP_MODE_STREAMING:
3674 control = get_unaligned_le16(skb->data);
3675 skb_pull(skb, 2);
3676 len = skb->len;
3677
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003678 if (l2cap_check_fcs(pi, skb))
3679 goto drop;
3680
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003681 if (__is_sar_start(control))
3682 len -= 2;
3683
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003684 if (pi->fcs == L2CAP_FCS_CRC16)
3685 len -= 2;
3686
Nathan Holstein51893f82010-06-09 15:46:25 -04003687 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003688 goto drop;
3689
3690 tx_seq = __get_txseq(control);
3691
3692 if (pi->expected_tx_seq == tx_seq)
3693 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3694 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03003695 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003696
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003697 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003698
3699 goto done;
3700
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003701 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003702 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003703 break;
3704 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705
3706drop:
3707 kfree_skb(skb);
3708
3709done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003710 if (sk)
3711 bh_unlock_sock(sk);
3712
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713 return 0;
3714}
3715
Al Viro8e036fc2007-07-29 00:16:36 -07003716static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003717{
3718 struct sock *sk;
3719
3720 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3721 if (!sk)
3722 goto drop;
3723
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003724 bh_lock_sock(sk);
3725
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726 BT_DBG("sk %p, len %d", sk, skb->len);
3727
3728 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3729 goto drop;
3730
3731 if (l2cap_pi(sk)->imtu < skb->len)
3732 goto drop;
3733
3734 if (!sock_queue_rcv_skb(sk, skb))
3735 goto done;
3736
3737drop:
3738 kfree_skb(skb);
3739
3740done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003741 if (sk)
3742 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743 return 0;
3744}
3745
3746static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3747{
3748 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003749 u16 cid, len;
3750 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751
3752 skb_pull(skb, L2CAP_HDR_SIZE);
3753 cid = __le16_to_cpu(lh->cid);
3754 len = __le16_to_cpu(lh->len);
3755
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003756 if (len != skb->len) {
3757 kfree_skb(skb);
3758 return;
3759 }
3760
Linus Torvalds1da177e2005-04-16 15:20:36 -07003761 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3762
3763 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003764 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003765 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003766 l2cap_sig_channel(conn, skb);
3767 break;
3768
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003769 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003770 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771 skb_pull(skb, 2);
3772 l2cap_conless_channel(conn, psm, skb);
3773 break;
3774
3775 default:
3776 l2cap_data_channel(conn, cid, skb);
3777 break;
3778 }
3779}
3780
3781/* ---- L2CAP interface with lower layer (HCI) ---- */
3782
3783static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3784{
3785 int exact = 0, lm1 = 0, lm2 = 0;
3786 register struct sock *sk;
3787 struct hlist_node *node;
3788
3789 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003790 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791
3792 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3793
3794 /* Find listening sockets and check their link_mode */
3795 read_lock(&l2cap_sk_list.lock);
3796 sk_for_each(sk, node, &l2cap_sk_list.head) {
3797 if (sk->sk_state != BT_LISTEN)
3798 continue;
3799
3800 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003801 lm1 |= HCI_LM_ACCEPT;
3802 if (l2cap_pi(sk)->role_switch)
3803 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003805 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3806 lm2 |= HCI_LM_ACCEPT;
3807 if (l2cap_pi(sk)->role_switch)
3808 lm2 |= HCI_LM_MASTER;
3809 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 }
3811 read_unlock(&l2cap_sk_list.lock);
3812
3813 return exact ? lm1 : lm2;
3814}
3815
3816static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3817{
Marcel Holtmann01394182006-07-03 10:02:46 +02003818 struct l2cap_conn *conn;
3819
Linus Torvalds1da177e2005-04-16 15:20:36 -07003820 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3821
Ville Tervoacd7d372011-02-10 22:38:49 -03003822 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003823 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824
3825 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826 conn = l2cap_conn_add(hcon, status);
3827 if (conn)
3828 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003829 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830 l2cap_conn_del(hcon, bt_err(status));
3831
3832 return 0;
3833}
3834
Marcel Holtmann2950f212009-02-12 14:02:50 +01003835static int l2cap_disconn_ind(struct hci_conn *hcon)
3836{
3837 struct l2cap_conn *conn = hcon->l2cap_data;
3838
3839 BT_DBG("hcon %p", hcon);
3840
3841 if (hcon->type != ACL_LINK || !conn)
3842 return 0x13;
3843
3844 return conn->disc_reason;
3845}
3846
3847static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848{
3849 BT_DBG("hcon %p reason %d", hcon, reason);
3850
Ville Tervoacd7d372011-02-10 22:38:49 -03003851 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003852 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853
3854 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003855
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856 return 0;
3857}
3858
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003859static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3860{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003861 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003862 return;
3863
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003864 if (encrypt == 0x00) {
3865 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3866 l2cap_sock_clear_timer(sk);
3867 l2cap_sock_set_timer(sk, HZ * 5);
3868 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3869 __l2cap_sock_close(sk, ECONNREFUSED);
3870 } else {
3871 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3872 l2cap_sock_clear_timer(sk);
3873 }
3874}
3875
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003876static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003878 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003879 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880
Marcel Holtmann01394182006-07-03 10:02:46 +02003881 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003883
Linus Torvalds1da177e2005-04-16 15:20:36 -07003884 BT_DBG("conn %p", conn);
3885
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003886 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003888 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003889 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003890
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891 bh_lock_sock(sk);
3892
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003893 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3894 bh_unlock_sock(sk);
3895 continue;
3896 }
3897
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003898 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003899 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003900 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003901 bh_unlock_sock(sk);
3902 continue;
3903 }
3904
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003905 if (sk->sk_state == BT_CONNECT) {
3906 if (!status) {
3907 struct l2cap_conn_req req;
3908 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3909 req.psm = l2cap_pi(sk)->psm;
3910
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003911 chan->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003912 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003913
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003914 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003915 L2CAP_CONN_REQ, sizeof(req), &req);
3916 } else {
3917 l2cap_sock_clear_timer(sk);
3918 l2cap_sock_set_timer(sk, HZ / 10);
3919 }
3920 } else if (sk->sk_state == BT_CONNECT2) {
3921 struct l2cap_conn_rsp rsp;
3922 __u16 result;
3923
3924 if (!status) {
3925 sk->sk_state = BT_CONFIG;
3926 result = L2CAP_CR_SUCCESS;
3927 } else {
3928 sk->sk_state = BT_DISCONN;
3929 l2cap_sock_set_timer(sk, HZ / 10);
3930 result = L2CAP_CR_SEC_BLOCK;
3931 }
3932
3933 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3934 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3935 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003936 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003937 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
3938 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939 }
3940
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941 bh_unlock_sock(sk);
3942 }
3943
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003944 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003945
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 return 0;
3947}
3948
3949static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3950{
3951 struct l2cap_conn *conn = hcon->l2cap_data;
3952
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003953 if (!conn)
3954 conn = l2cap_conn_add(hcon, 0);
3955
3956 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957 goto drop;
3958
3959 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3960
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003961 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003963 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003964 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965 int len;
3966
3967 if (conn->rx_len) {
3968 BT_ERR("Unexpected start frame (len %d)", skb->len);
3969 kfree_skb(conn->rx_skb);
3970 conn->rx_skb = NULL;
3971 conn->rx_len = 0;
3972 l2cap_conn_unreliable(conn, ECOMM);
3973 }
3974
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003975 /* Start fragment always begin with Basic L2CAP header */
3976 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977 BT_ERR("Frame is too short (len %d)", skb->len);
3978 l2cap_conn_unreliable(conn, ECOMM);
3979 goto drop;
3980 }
3981
3982 hdr = (struct l2cap_hdr *) skb->data;
3983 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003984 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985
3986 if (len == skb->len) {
3987 /* Complete frame received */
3988 l2cap_recv_frame(conn, skb);
3989 return 0;
3990 }
3991
3992 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3993
3994 if (skb->len > len) {
3995 BT_ERR("Frame is too long (len %d, expected len %d)",
3996 skb->len, len);
3997 l2cap_conn_unreliable(conn, ECOMM);
3998 goto drop;
3999 }
4000
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004001 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004002
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004003 if (chan && chan->sk) {
4004 struct sock *sk = chan->sk;
4005
4006 if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
4007 BT_ERR("Frame exceeding recv MTU (len %d, "
4008 "MTU %d)", len,
4009 l2cap_pi(sk)->imtu);
4010 bh_unlock_sock(sk);
4011 l2cap_conn_unreliable(conn, ECOMM);
4012 goto drop;
4013 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004014 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004015 }
4016
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004018 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4019 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020 goto drop;
4021
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004022 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004023 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024 conn->rx_len = len - skb->len;
4025 } else {
4026 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4027
4028 if (!conn->rx_len) {
4029 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4030 l2cap_conn_unreliable(conn, ECOMM);
4031 goto drop;
4032 }
4033
4034 if (skb->len > conn->rx_len) {
4035 BT_ERR("Fragment is too long (len %d, expected %d)",
4036 skb->len, conn->rx_len);
4037 kfree_skb(conn->rx_skb);
4038 conn->rx_skb = NULL;
4039 conn->rx_len = 0;
4040 l2cap_conn_unreliable(conn, ECOMM);
4041 goto drop;
4042 }
4043
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004044 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004045 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046 conn->rx_len -= skb->len;
4047
4048 if (!conn->rx_len) {
4049 /* Complete frame received */
4050 l2cap_recv_frame(conn, conn->rx_skb);
4051 conn->rx_skb = NULL;
4052 }
4053 }
4054
4055drop:
4056 kfree_skb(skb);
4057 return 0;
4058}
4059
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004060static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061{
4062 struct sock *sk;
4063 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064
4065 read_lock_bh(&l2cap_sk_list.lock);
4066
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004067 sk_for_each(sk, node, &l2cap_sk_list.head) {
4068 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004070 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 +01004071 batostr(&bt_sk(sk)->src),
4072 batostr(&bt_sk(sk)->dst),
4073 sk->sk_state, __le16_to_cpu(pi->psm),
4074 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004075 pi->imtu, pi->omtu, pi->sec_level,
4076 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004077 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004080
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004081 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082}
4083
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004084static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4085{
4086 return single_open(file, l2cap_debugfs_show, inode->i_private);
4087}
4088
4089static const struct file_operations l2cap_debugfs_fops = {
4090 .open = l2cap_debugfs_open,
4091 .read = seq_read,
4092 .llseek = seq_lseek,
4093 .release = single_release,
4094};
4095
4096static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098static struct hci_proto l2cap_hci_proto = {
4099 .name = "L2CAP",
4100 .id = HCI_PROTO_L2CAP,
4101 .connect_ind = l2cap_connect_ind,
4102 .connect_cfm = l2cap_connect_cfm,
4103 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004104 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004105 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106 .recv_acldata = l2cap_recv_acldata
4107};
4108
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004109int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110{
4111 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004112
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004113 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114 if (err < 0)
4115 return err;
4116
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004117 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004118 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004119 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120 goto error;
4121 }
4122
4123 err = hci_register_proto(&l2cap_hci_proto);
4124 if (err < 0) {
4125 BT_ERR("L2CAP protocol registration failed");
4126 bt_sock_unregister(BTPROTO_L2CAP);
4127 goto error;
4128 }
4129
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004130 if (bt_debugfs) {
4131 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4132 bt_debugfs, NULL, &l2cap_debugfs_fops);
4133 if (!l2cap_debugfs)
4134 BT_ERR("Failed to create L2CAP debug file");
4135 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004136
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137 return 0;
4138
4139error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004140 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004141 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142 return err;
4143}
4144
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004145void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004147 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004149 flush_workqueue(_busy_wq);
4150 destroy_workqueue(_busy_wq);
4151
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4153 BT_ERR("L2CAP protocol unregistration failed");
4154
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004155 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156}
4157
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004158module_param(disable_ertm, bool, 0644);
4159MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");