blob: 0fc6bbe85d41248bf11b018a1b575ebe3de911f9 [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. Padovan5d41ce12011-04-08 15:40:02 -0300152struct 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
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300214 BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
Marcel Holtmann01394182006-07-03 10:02:46 +0200215
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
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300239 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE &&
240 chan->conf_state & L2CAP_CONF_INPUT_DONE))
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300241 goto free;
242
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300243 skb_queue_purge(&chan->tx_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300244
245 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
246 struct srej_list *l, *tmp;
247
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300248 del_timer(&chan->retrans_timer);
249 del_timer(&chan->monitor_timer);
250 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300251
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -0300252 skb_queue_purge(&chan->srej_q);
253 skb_queue_purge(&chan->busy_q);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300254
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -0300255 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300256 list_del(&l->list);
257 kfree(l);
258 }
259 }
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300260
Gustavo F. Padovan2ead70b2011-04-01 15:13:36 -0300261free:
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300262 kfree(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200263}
264
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300265static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530266{
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300267 struct sock *sk = chan->sk;
268
Johan Hedberg8556edd32011-01-19 12:06:50 +0530269 if (sk->sk_type == SOCK_RAW) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300270 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530271 case BT_SECURITY_HIGH:
272 return HCI_AT_DEDICATED_BONDING_MITM;
273 case BT_SECURITY_MEDIUM:
274 return HCI_AT_DEDICATED_BONDING;
275 default:
276 return HCI_AT_NO_BONDING;
277 }
278 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300279 if (chan->sec_level == BT_SECURITY_LOW)
280 chan->sec_level = BT_SECURITY_SDP;
Johan Hedberg8556edd32011-01-19 12:06:50 +0530281
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300282 if (chan->sec_level == BT_SECURITY_HIGH)
Johan Hedberg8556edd32011-01-19 12:06:50 +0530283 return HCI_AT_NO_BONDING_MITM;
284 else
285 return HCI_AT_NO_BONDING;
286 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300287 switch (chan->sec_level) {
Johan Hedberg8556edd32011-01-19 12:06:50 +0530288 case BT_SECURITY_HIGH:
289 return HCI_AT_GENERAL_BONDING_MITM;
290 case BT_SECURITY_MEDIUM:
291 return HCI_AT_GENERAL_BONDING;
292 default:
293 return HCI_AT_NO_BONDING;
294 }
295 }
296}
297
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200298/* Service level security */
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300299static inline int l2cap_check_security(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200300{
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300301 struct l2cap_conn *conn = l2cap_pi(chan->sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100302 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200303
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300304 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100305
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300306 return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200307}
308
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200309u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200310{
311 u8 id;
312
313 /* Get next available identificator.
314 * 1 - 128 are used by kernel.
315 * 129 - 199 are reserved.
316 * 200 - 254 are used by utilities like l2ping, etc.
317 */
318
319 spin_lock_bh(&conn->lock);
320
321 if (++conn->tx_ident > 128)
322 conn->tx_ident = 1;
323
324 id = conn->tx_ident;
325
326 spin_unlock_bh(&conn->lock);
327
328 return id;
329}
330
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200331void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200332{
333 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200334 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200335
336 BT_DBG("code 0x%2.2x", code);
337
338 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300339 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200340
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200341 if (lmp_no_flush_capable(conn->hcon->hdev))
342 flags = ACL_START_NO_FLUSH;
343 else
344 flags = ACL_START;
345
346 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200347}
348
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300349static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300350{
351 struct sk_buff *skb;
352 struct l2cap_hdr *lh;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300353 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300354 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300355 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300356 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200357 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300358
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300359 if (sk->sk_state != BT_CONNECTED)
360 return;
361
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300362 if (pi->fcs == L2CAP_FCS_CRC16)
363 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300364
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300365 BT_DBG("chan %p, control 0x%2.2x", chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300366
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300367 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300368 control |= L2CAP_CTRL_FRAME_TYPE;
369
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300370 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300371 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300372 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300373 }
374
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300375 if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300376 control |= L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300377 chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300378 }
379
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300380 skb = bt_skb_alloc(count, GFP_ATOMIC);
381 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300382 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300383
384 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300385 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300386 lh->cid = cpu_to_le16(pi->dcid);
387 put_unaligned_le16(control, skb_put(skb, 2));
388
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300389 if (pi->fcs == L2CAP_FCS_CRC16) {
390 u16 fcs = crc16(0, (u8 *)lh, count - 2);
391 put_unaligned_le16(fcs, skb_put(skb, 2));
392 }
393
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200394 if (lmp_no_flush_capable(conn->hcon->hdev))
395 flags = ACL_START_NO_FLUSH;
396 else
397 flags = ACL_START;
398
399 hci_send_acl(pi->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300400}
401
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300402static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300403{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300404 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300405 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300406 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300407 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300408 control |= L2CAP_SUPER_RCV_READY;
409
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300410 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300411
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300412 l2cap_send_sframe(chan, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300413}
414
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300415static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300416{
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300417 return !(chan->conf_state & L2CAP_CONF_CONNECT_PEND);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300418}
419
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300420static void l2cap_do_start(struct l2cap_chan *chan)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200421{
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300422 struct sock *sk = chan->sk;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200423 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
424
425 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100426 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
427 return;
428
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300429 if (l2cap_check_security(chan) &&
430 __l2cap_no_conn_pending(chan)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200431 struct l2cap_conn_req req;
432 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
433 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200434
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300435 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300436 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200437
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300438 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
439 sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200440 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200441 } else {
442 struct l2cap_info_req req;
443 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
444
445 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
446 conn->info_ident = l2cap_get_ident(conn);
447
448 mod_timer(&conn->info_timer, jiffies +
449 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
450
451 l2cap_send_cmd(conn, conn->info_ident,
452 L2CAP_INFO_REQ, sizeof(req), &req);
453 }
454}
455
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300456static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
457{
458 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300459 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300460 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
461
462 switch (mode) {
463 case L2CAP_MODE_ERTM:
464 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
465 case L2CAP_MODE_STREAMING:
466 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
467 default:
468 return 0x00;
469 }
470}
471
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300472void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300473{
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300474 struct sock *sk;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300475 struct l2cap_disconn_req req;
476
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300477 if (!conn)
478 return;
479
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300480 sk = chan->sk;
481
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300482 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300483 del_timer(&chan->retrans_timer);
484 del_timer(&chan->monitor_timer);
485 del_timer(&chan->ack_timer);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300486 }
487
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300488 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
489 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
490 l2cap_send_cmd(conn, l2cap_get_ident(conn),
491 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300492
493 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300494 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300495}
496
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200498static void l2cap_conn_start(struct l2cap_conn *conn)
499{
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300500 struct l2cap_chan *chan, *tmp;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200501
502 BT_DBG("conn %p", conn);
503
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300504 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200505
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300506 list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300507 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300508
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200509 bh_lock_sock(sk);
510
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300511 if (sk->sk_type != SOCK_SEQPACKET &&
512 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200513 bh_unlock_sock(sk);
514 continue;
515 }
516
517 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300518 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300519
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300520 if (!l2cap_check_security(chan) ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300521 !__l2cap_no_conn_pending(chan)) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300522 bh_unlock_sock(sk);
523 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200524 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300525
526 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
527 conn->feat_mask)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300528 && chan->conf_state &
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300529 L2CAP_CONF_STATE2_DEVICE) {
Gustavo F. Padovan820ffdb2011-04-01 00:35:21 -0300530 /* __l2cap_sock_close() calls list_del(chan)
531 * so release the lock */
532 read_unlock_bh(&conn->chan_lock);
533 __l2cap_sock_close(sk, ECONNRESET);
534 read_lock_bh(&conn->chan_lock);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300535 bh_unlock_sock(sk);
536 continue;
537 }
538
539 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
540 req.psm = l2cap_pi(sk)->psm;
541
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300542 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300543 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300544
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300545 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
546 sizeof(req), &req);
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300547
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200548 } else if (sk->sk_state == BT_CONNECT2) {
549 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300550 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200551 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
552 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
553
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300554 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100555 if (bt_sk(sk)->defer_setup) {
556 struct sock *parent = bt_sk(sk)->parent;
557 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
558 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
559 parent->sk_data_ready(parent, 0);
560
561 } else {
562 sk->sk_state = BT_CONFIG;
563 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
564 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
565 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200566 } else {
567 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
568 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
569 }
570
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300571 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
572 sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300573
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300574 if (chan->conf_state & L2CAP_CONF_REQ_SENT ||
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300575 rsp.result != L2CAP_CR_SUCCESS) {
576 bh_unlock_sock(sk);
577 continue;
578 }
579
Gustavo F. Padovanb4450032011-04-12 18:15:09 -0300580 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300581 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -0300582 l2cap_build_conf_req(chan, buf), buf);
583 chan->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200584 }
585
586 bh_unlock_sock(sk);
587 }
588
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300589 read_unlock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200590}
591
Ville Tervob62f3282011-02-10 22:38:50 -0300592/* Find socket with cid and source bdaddr.
593 * Returns closest match, locked.
594 */
595static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
596{
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300597 struct sock *sk = NULL, *sk1 = NULL;
Ville Tervob62f3282011-02-10 22:38:50 -0300598 struct hlist_node *node;
599
600 read_lock(&l2cap_sk_list.lock);
601
602 sk_for_each(sk, node, &l2cap_sk_list.head) {
603 if (state && sk->sk_state != state)
604 continue;
605
606 if (l2cap_pi(sk)->scid == cid) {
607 /* Exact match. */
608 if (!bacmp(&bt_sk(sk)->src, src))
609 break;
610
611 /* Closest match */
612 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
613 sk1 = sk;
614 }
615 }
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300616
Ville Tervob62f3282011-02-10 22:38:50 -0300617 read_unlock(&l2cap_sk_list.lock);
618
Gustavo F. Padovan280f2942011-04-13 19:01:22 -0300619 return node ? sk : sk1;
Ville Tervob62f3282011-02-10 22:38:50 -0300620}
621
622static void l2cap_le_conn_ready(struct l2cap_conn *conn)
623{
Gustavo F. Padovanc916fbe2011-04-04 16:00:55 -0300624 struct sock *parent, *sk;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300625 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300626
627 BT_DBG("");
628
629 /* Check if we have socket listening on cid */
630 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
631 conn->src);
632 if (!parent)
633 return;
634
Gustavo F. Padovan62f3a2c2011-04-14 18:34:34 -0300635 bh_lock_sock(parent);
636
Ville Tervob62f3282011-02-10 22:38:50 -0300637 /* Check for backlog size */
638 if (sk_acceptq_is_full(parent)) {
639 BT_DBG("backlog full %d", parent->sk_ack_backlog);
640 goto clean;
641 }
642
643 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
644 if (!sk)
645 goto clean;
646
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300647 chan = l2cap_chan_alloc(sk);
648 if (!chan) {
649 l2cap_sock_kill(sk);
650 goto clean;
651 }
652
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300653 l2cap_pi(sk)->chan = chan;
654
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300655 write_lock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300656
657 hci_conn_hold(conn->hcon);
658
659 l2cap_sock_init(sk, parent);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300660
Ville Tervob62f3282011-02-10 22:38:50 -0300661 bacpy(&bt_sk(sk)->src, conn->src);
662 bacpy(&bt_sk(sk)->dst, conn->dst);
663
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300664 bt_accept_enqueue(parent, sk);
665
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300666 __l2cap_chan_add(conn, chan);
667
Ville Tervob62f3282011-02-10 22:38:50 -0300668 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
669
670 sk->sk_state = BT_CONNECTED;
671 parent->sk_data_ready(parent, 0);
672
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300673 write_unlock_bh(&conn->chan_lock);
Ville Tervob62f3282011-02-10 22:38:50 -0300674
675clean:
676 bh_unlock_sock(parent);
677}
678
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200679static void l2cap_conn_ready(struct l2cap_conn *conn)
680{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300681 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200682
683 BT_DBG("conn %p", conn);
684
Ville Tervob62f3282011-02-10 22:38:50 -0300685 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
686 l2cap_le_conn_ready(conn);
687
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300688 read_lock(&conn->chan_lock);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200689
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300690 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300691 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300692
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200693 bh_lock_sock(sk);
694
Ville Tervoacd7d372011-02-10 22:38:49 -0300695 if (conn->hcon->type == LE_LINK) {
696 l2cap_sock_clear_timer(sk);
697 sk->sk_state = BT_CONNECTED;
698 sk->sk_state_change(sk);
699 }
700
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300701 if (sk->sk_type != SOCK_SEQPACKET &&
702 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200703 l2cap_sock_clear_timer(sk);
704 sk->sk_state = BT_CONNECTED;
705 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200706 } else if (sk->sk_state == BT_CONNECT)
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300707 l2cap_do_start(chan);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200708
709 bh_unlock_sock(sk);
710 }
711
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300712 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200713}
714
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200715/* Notify sockets that we cannot guaranty reliability anymore */
716static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
717{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300718 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200719
720 BT_DBG("conn %p", conn);
721
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300722 read_lock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200723
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300724 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300725 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300726
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300727 if (chan->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200728 sk->sk_err = err;
729 }
730
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300731 read_unlock(&conn->chan_lock);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200732}
733
734static void l2cap_info_timeout(unsigned long arg)
735{
736 struct l2cap_conn *conn = (void *) arg;
737
Marcel Holtmann984947d2009-02-06 23:35:19 +0100738 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100739 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100740
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200741 l2cap_conn_start(conn);
742}
743
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
745{
Marcel Holtmann01394182006-07-03 10:02:46 +0200746 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
Marcel Holtmann01394182006-07-03 10:02:46 +0200748 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 return conn;
750
Marcel Holtmann01394182006-07-03 10:02:46 +0200751 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
752 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
755 hcon->l2cap_data = conn;
756 conn->hcon = hcon;
757
Marcel Holtmann01394182006-07-03 10:02:46 +0200758 BT_DBG("hcon %p conn %p", hcon, conn);
759
Ville Tervoacd7d372011-02-10 22:38:49 -0300760 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
761 conn->mtu = hcon->hdev->le_mtu;
762 else
763 conn->mtu = hcon->hdev->acl_mtu;
764
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 conn->src = &hcon->hdev->bdaddr;
766 conn->dst = &hcon->dst;
767
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200768 conn->feat_mask = 0;
769
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 spin_lock_init(&conn->lock);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300771 rwlock_init(&conn->chan_lock);
772
773 INIT_LIST_HEAD(&conn->chan_l);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774
Ville Tervob62f3282011-02-10 22:38:50 -0300775 if (hcon->type != LE_LINK)
776 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000777 (unsigned long) conn);
778
Marcel Holtmann2950f212009-02-12 14:02:50 +0100779 conn->disc_reason = 0x13;
780
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 return conn;
782}
783
Marcel Holtmann01394182006-07-03 10:02:46 +0200784static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785{
Marcel Holtmann01394182006-07-03 10:02:46 +0200786 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300787 struct l2cap_chan *chan, *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 struct sock *sk;
789
Marcel Holtmann01394182006-07-03 10:02:46 +0200790 if (!conn)
791 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
793 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
794
Wei Yongjun7585b972009-02-25 18:29:52 +0800795 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796
797 /* Kill channels */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300798 list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300799 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300801 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 bh_unlock_sock(sk);
803 l2cap_sock_kill(sk);
804 }
805
Dave Young8e8440f2008-03-03 12:18:55 -0800806 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
807 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800808
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 hcon->l2cap_data = NULL;
810 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811}
812
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300813static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814{
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300815 write_lock_bh(&conn->chan_lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300816 __l2cap_chan_add(conn, chan);
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -0300817 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818}
819
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
822/* Find socket with psm and source bdaddr.
823 * Returns closest match.
824 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000825static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826{
827 struct sock *sk = NULL, *sk1 = NULL;
828 struct hlist_node *node;
829
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000830 read_lock(&l2cap_sk_list.lock);
831
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 sk_for_each(sk, node, &l2cap_sk_list.head) {
833 if (state && sk->sk_state != state)
834 continue;
835
836 if (l2cap_pi(sk)->psm == psm) {
837 /* Exact match. */
838 if (!bacmp(&bt_sk(sk)->src, src))
839 break;
840
841 /* Closest match */
842 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
843 sk1 = sk;
844 }
845 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000848
849 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850}
851
Gustavo F. Padovan77a74c72011-04-12 18:17:14 -0300852int l2cap_chan_connect(struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853{
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -0300854 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 bdaddr_t *src = &bt_sk(sk)->src;
856 bdaddr_t *dst = &bt_sk(sk)->dst;
857 struct l2cap_conn *conn;
858 struct hci_conn *hcon;
859 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200860 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200861 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100863 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
864 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300866 hdev = hci_get_route(dst, src);
867 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 return -EHOSTUNREACH;
869
870 hci_dev_lock_bh(hdev);
871
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300872 auth_type = l2cap_get_auth_type(chan);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200873
Ville Tervoacd7d372011-02-10 22:38:49 -0300874 if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
875 hcon = hci_connect(hdev, LE_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300876 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300877 else
878 hcon = hci_connect(hdev, ACL_LINK, dst,
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300879 chan->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300880
Ville Tervo30e76272011-02-22 16:10:53 -0300881 if (IS_ERR(hcon)) {
882 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300884 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885
886 conn = l2cap_conn_add(hcon, 0);
887 if (!conn) {
888 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300889 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 goto done;
891 }
892
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 /* Update source addr of the socket */
894 bacpy(src, conn->src);
895
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300896 l2cap_chan_add(conn, chan);
897
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 sk->sk_state = BT_CONNECT;
899 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
900
901 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300902 if (sk->sk_type != SOCK_SEQPACKET &&
903 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 l2cap_sock_clear_timer(sk);
Gustavo F. Padovan43434782011-04-12 18:31:57 -0300905 if (l2cap_check_security(chan))
Johan Hedbergd00ef242011-01-19 12:06:51 +0530906 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200907 } else
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -0300908 l2cap_do_start(chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 }
910
Ville Tervo30e76272011-02-22 16:10:53 -0300911 err = 0;
912
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913done:
914 hci_dev_unlock_bh(hdev);
915 hci_dev_put(hdev);
916 return err;
917}
918
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200919int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300920{
921 DECLARE_WAITQUEUE(wait, current);
922 int err = 0;
923 int timeo = HZ/5;
924
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200925 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300926 while ((l2cap_pi(sk)->chan->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300927 set_current_state(TASK_INTERRUPTIBLE);
928
929 if (!timeo)
930 timeo = HZ/5;
931
932 if (signal_pending(current)) {
933 err = sock_intr_errno(timeo);
934 break;
935 }
936
937 release_sock(sk);
938 timeo = schedule_timeout(timeo);
939 lock_sock(sk);
940
941 err = sock_error(sk);
942 if (err)
943 break;
944 }
945 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200946 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300947 return err;
948}
949
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300950static void l2cap_monitor_timeout(unsigned long arg)
951{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300952 struct l2cap_chan *chan = (void *) arg;
953 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300954
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300955 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300956
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300957 bh_lock_sock(sk);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -0300958 if (chan->retry_count >= chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -0300959 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200960 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300961 return;
962 }
963
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300964 chan->retry_count++;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300965 __mod_monitor_timer();
966
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300967 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300968 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300969}
970
971static void l2cap_retrans_timeout(unsigned long arg)
972{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300973 struct l2cap_chan *chan = (void *) arg;
974 struct sock *sk = chan->sk;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300975
Gustavo F. Padovan49208c92011-04-04 15:59:54 -0300976 BT_DBG("chan %p", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300977
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300978 bh_lock_sock(sk);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300979 chan->retry_count = 1;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300980 __mod_monitor_timer();
981
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300982 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300983
Gustavo F. Padovan525cd182011-03-25 19:43:39 -0300984 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300985 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300986}
987
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300988static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300989{
990 struct sk_buff *skb;
991
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300992 while ((skb = skb_peek(&chan->tx_q)) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -0300993 chan->unacked_frames) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -0300994 if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300995 break;
996
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -0300997 skb = skb_dequeue(&chan->tx_q);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300998 kfree_skb(skb);
999
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001000 chan->unacked_frames--;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001001 }
1002
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001003 if (!chan->unacked_frames)
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001004 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001005}
1006
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001007void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001008{
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001009 struct sock *sk = chan->sk;
1010 struct hci_conn *hcon = l2cap_pi(sk)->conn->hcon;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001011 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001012
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001013 BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001014
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001015 if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001016 flags = ACL_START_NO_FLUSH;
1017 else
1018 flags = ACL_START;
1019
1020 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001021}
1022
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001023void l2cap_streaming_send(struct l2cap_chan *chan)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001024{
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001025 struct sock *sk = chan->sk;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001026 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001027 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001028 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001029
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001030 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001031 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001032 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001033 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001034
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001035 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001036 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1037 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001038 }
1039
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001040 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001041
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001042 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001043 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001044}
1045
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001046static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001047{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001048 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001049 struct l2cap_pinfo *pi = l2cap_pi(sk);
1050 struct sk_buff *skb, *tx_skb;
1051 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001052
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001053 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001054 if (!skb)
1055 return;
1056
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001057 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001058 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001059 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001060
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001061 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001062 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001063
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001064 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001065
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001066 if (chan->remote_max_tx &&
1067 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001068 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001069 return;
1070 }
1071
1072 tx_skb = skb_clone(skb, GFP_ATOMIC);
1073 bt_cb(skb)->retries++;
1074 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001075 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001076
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001077 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001078 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001079 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001080 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001081
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001082 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001083 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001084
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001085 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1086
1087 if (pi->fcs == L2CAP_FCS_CRC16) {
1088 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1089 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1090 }
1091
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001092 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001093}
1094
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001095int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001096{
1097 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001098 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001099 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001100 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001101 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001102
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001103 if (sk->sk_state != BT_CONNECTED)
1104 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001105
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001106 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001107
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001108 if (chan->remote_max_tx &&
1109 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001110 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001111 break;
1112 }
1113
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001114 tx_skb = skb_clone(skb, GFP_ATOMIC);
1115
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001116 bt_cb(skb)->retries++;
1117
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001118 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001119 control &= L2CAP_CTRL_SAR;
1120
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001121 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001122 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001123 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001124 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001125 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1126 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001127 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1128
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001129
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001130 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001131 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1132 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1133 }
1134
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001135 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001136
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001137 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001138
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001139 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1140 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001141
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301142 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001143 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301144
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001145 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001146
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001147 if (skb_queue_is_last(&chan->tx_q, skb))
1148 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001149 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001150 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001151
1152 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001153 }
1154
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001155 return nsent;
1156}
1157
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001158static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001159{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001160 int ret;
1161
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001162 if (!skb_queue_empty(&chan->tx_q))
1163 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001164
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001165 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001166 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001167 return ret;
1168}
1169
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001170static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001171{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001172 u16 control = 0;
1173
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001174 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001175
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001176 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001177 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001178 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1179 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001180 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001181 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001182
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001183 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001184 return;
1185
1186 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001187 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001188}
1189
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001190static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001191{
1192 struct srej_list *tail;
1193 u16 control;
1194
1195 control = L2CAP_SUPER_SELECT_REJECT;
1196 control |= L2CAP_CTRL_FINAL;
1197
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001198 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001199 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1200
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001201 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001202}
1203
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001204static 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 -07001205{
1206 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001207 struct sk_buff **frag;
1208 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001210 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001211 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212
1213 sent += count;
1214 len -= count;
1215
1216 /* Continuation fragments (no L2CAP header) */
1217 frag = &skb_shinfo(skb)->frag_list;
1218 while (len) {
1219 count = min_t(unsigned int, conn->mtu, len);
1220
1221 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1222 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001223 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001224 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1225 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226
1227 sent += count;
1228 len -= count;
1229
1230 frag = &(*frag)->next;
1231 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232
1233 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001234}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001236struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001237{
1238 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1239 struct sk_buff *skb;
1240 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1241 struct l2cap_hdr *lh;
1242
1243 BT_DBG("sk %p len %d", sk, (int)len);
1244
1245 count = min_t(unsigned int, (conn->mtu - hlen), len);
1246 skb = bt_skb_send_alloc(sk, count + hlen,
1247 msg->msg_flags & MSG_DONTWAIT, &err);
1248 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001249 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001250
1251 /* Create L2CAP header */
1252 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1253 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1254 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1255 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1256
1257 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1258 if (unlikely(err < 0)) {
1259 kfree_skb(skb);
1260 return ERR_PTR(err);
1261 }
1262 return skb;
1263}
1264
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001265struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001266{
1267 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1268 struct sk_buff *skb;
1269 int err, count, hlen = L2CAP_HDR_SIZE;
1270 struct l2cap_hdr *lh;
1271
1272 BT_DBG("sk %p len %d", sk, (int)len);
1273
1274 count = min_t(unsigned int, (conn->mtu - hlen), len);
1275 skb = bt_skb_send_alloc(sk, count + hlen,
1276 msg->msg_flags & MSG_DONTWAIT, &err);
1277 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001278 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001279
1280 /* Create L2CAP header */
1281 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1282 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1283 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1284
1285 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1286 if (unlikely(err < 0)) {
1287 kfree_skb(skb);
1288 return ERR_PTR(err);
1289 }
1290 return skb;
1291}
1292
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001293struct 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 -03001294{
1295 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1296 struct sk_buff *skb;
1297 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1298 struct l2cap_hdr *lh;
1299
1300 BT_DBG("sk %p len %d", sk, (int)len);
1301
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001302 if (!conn)
1303 return ERR_PTR(-ENOTCONN);
1304
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001305 if (sdulen)
1306 hlen += 2;
1307
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001308 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1309 hlen += 2;
1310
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001311 count = min_t(unsigned int, (conn->mtu - hlen), len);
1312 skb = bt_skb_send_alloc(sk, count + hlen,
1313 msg->msg_flags & MSG_DONTWAIT, &err);
1314 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001315 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001316
1317 /* Create L2CAP header */
1318 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1319 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1320 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1321 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001322 if (sdulen)
1323 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001324
1325 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1326 if (unlikely(err < 0)) {
1327 kfree_skb(skb);
1328 return ERR_PTR(err);
1329 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001330
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001331 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1332 put_unaligned_le16(0, skb_put(skb, 2));
1333
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001334 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001335 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336}
1337
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001338int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001339{
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001340 struct sock *sk = chan->sk;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001341 struct sk_buff *skb;
1342 struct sk_buff_head sar_queue;
1343 u16 control;
1344 size_t size = 0;
1345
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001346 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001347 control = L2CAP_SDU_START;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001348 skb = l2cap_create_iframe_pdu(sk, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001349 if (IS_ERR(skb))
1350 return PTR_ERR(skb);
1351
1352 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001353 len -= chan->remote_mps;
1354 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001355
1356 while (len > 0) {
1357 size_t buflen;
1358
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001359 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001360 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001361 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001362 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001363 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001364 buflen = len;
1365 }
1366
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001367 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001368 if (IS_ERR(skb)) {
1369 skb_queue_purge(&sar_queue);
1370 return PTR_ERR(skb);
1371 }
1372
1373 __skb_queue_tail(&sar_queue, skb);
1374 len -= buflen;
1375 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001376 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001377 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1378 if (chan->tx_send_head == NULL)
1379 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001380
1381 return size;
1382}
1383
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384static void l2cap_chan_ready(struct sock *sk)
1385{
1386 struct sock *parent = bt_sk(sk)->parent;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001387 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
1389 BT_DBG("sk %p, parent %p", sk, parent);
1390
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001391 chan->conf_state = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 l2cap_sock_clear_timer(sk);
1393
1394 if (!parent) {
1395 /* Outgoing channel.
1396 * Wake up socket sleeping on connect.
1397 */
1398 sk->sk_state = BT_CONNECTED;
1399 sk->sk_state_change(sk);
1400 } else {
1401 /* Incoming channel.
1402 * Wake up socket sleeping on accept.
1403 */
1404 parent->sk_data_ready(parent, 0);
1405 }
1406}
1407
1408/* Copy frame to all raw sockets on that connection */
1409static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1410{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001412 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413
1414 BT_DBG("conn %p", conn);
1415
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001416 read_lock(&conn->chan_lock);
1417 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001418 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 if (sk->sk_type != SOCK_RAW)
1420 continue;
1421
1422 /* Don't send frame to the socket it came from */
1423 if (skb->sk == sk)
1424 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001425 nskb = skb_clone(skb, GFP_ATOMIC);
1426 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 continue;
1428
1429 if (sock_queue_rcv_skb(sk, nskb))
1430 kfree_skb(nskb);
1431 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001432 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433}
1434
1435/* ---- L2CAP signalling commands ---- */
1436static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1437 u8 code, u8 ident, u16 dlen, void *data)
1438{
1439 struct sk_buff *skb, **frag;
1440 struct l2cap_cmd_hdr *cmd;
1441 struct l2cap_hdr *lh;
1442 int len, count;
1443
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001444 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1445 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446
1447 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1448 count = min_t(unsigned int, conn->mtu, len);
1449
1450 skb = bt_skb_alloc(count, GFP_ATOMIC);
1451 if (!skb)
1452 return NULL;
1453
1454 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001455 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001456
1457 if (conn->hcon->type == LE_LINK)
1458 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1459 else
1460 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461
1462 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1463 cmd->code = code;
1464 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001465 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
1467 if (dlen) {
1468 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1469 memcpy(skb_put(skb, count), data, count);
1470 data += count;
1471 }
1472
1473 len -= skb->len;
1474
1475 /* Continuation fragments (no L2CAP header) */
1476 frag = &skb_shinfo(skb)->frag_list;
1477 while (len) {
1478 count = min_t(unsigned int, conn->mtu, len);
1479
1480 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1481 if (!*frag)
1482 goto fail;
1483
1484 memcpy(skb_put(*frag, count), data, count);
1485
1486 len -= count;
1487 data += count;
1488
1489 frag = &(*frag)->next;
1490 }
1491
1492 return skb;
1493
1494fail:
1495 kfree_skb(skb);
1496 return NULL;
1497}
1498
1499static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1500{
1501 struct l2cap_conf_opt *opt = *ptr;
1502 int len;
1503
1504 len = L2CAP_CONF_OPT_SIZE + opt->len;
1505 *ptr += len;
1506
1507 *type = opt->type;
1508 *olen = opt->len;
1509
1510 switch (opt->len) {
1511 case 1:
1512 *val = *((u8 *) opt->val);
1513 break;
1514
1515 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001516 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 break;
1518
1519 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001520 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 break;
1522
1523 default:
1524 *val = (unsigned long) opt->val;
1525 break;
1526 }
1527
1528 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1529 return len;
1530}
1531
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1533{
1534 struct l2cap_conf_opt *opt = *ptr;
1535
1536 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1537
1538 opt->type = type;
1539 opt->len = len;
1540
1541 switch (len) {
1542 case 1:
1543 *((u8 *) opt->val) = val;
1544 break;
1545
1546 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001547 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 break;
1549
1550 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001551 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 break;
1553
1554 default:
1555 memcpy(opt->val, (void *) val, len);
1556 break;
1557 }
1558
1559 *ptr += L2CAP_CONF_OPT_SIZE + len;
1560}
1561
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001562static void l2cap_ack_timeout(unsigned long arg)
1563{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001564 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001565
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001566 bh_lock_sock(chan->sk);
1567 l2cap_send_ack(chan);
1568 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001569}
1570
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001571static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001572{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001573 struct sock *sk = chan->sk;
1574
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001575 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001576 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001577 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001578 chan->num_acked = 0;
1579 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001580
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001581 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1582 (unsigned long) chan);
1583 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1584 (unsigned long) chan);
1585 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001586
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001587 skb_queue_head_init(&chan->srej_q);
1588 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001589
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001590 INIT_LIST_HEAD(&chan->srej_l);
1591
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001592 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001593
1594 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001595}
1596
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001597static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1598{
1599 switch (mode) {
1600 case L2CAP_MODE_STREAMING:
1601 case L2CAP_MODE_ERTM:
1602 if (l2cap_mode_supported(mode, remote_feat_mask))
1603 return mode;
1604 /* fall through */
1605 default:
1606 return L2CAP_MODE_BASIC;
1607 }
1608}
1609
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001610static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001612 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001614 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 void *ptr = req->data;
1616
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001617 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001619 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001620 goto done;
1621
1622 switch (pi->mode) {
1623 case L2CAP_MODE_STREAMING:
1624 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001625 if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001626 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001627
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001628 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001629 default:
1630 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1631 break;
1632 }
1633
1634done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001635 if (pi->imtu != L2CAP_DEFAULT_MTU)
1636 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1637
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001638 switch (pi->mode) {
1639 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001640 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1641 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1642 break;
1643
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001644 rfc.mode = L2CAP_MODE_BASIC;
1645 rfc.txwin_size = 0;
1646 rfc.max_transmit = 0;
1647 rfc.retrans_timeout = 0;
1648 rfc.monitor_timeout = 0;
1649 rfc.max_pdu_size = 0;
1650
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001651 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1652 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001653 break;
1654
1655 case L2CAP_MODE_ERTM:
1656 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001657 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001658 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001659 rfc.retrans_timeout = 0;
1660 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001661 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001662 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001663 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001664
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001665 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1666 (unsigned long) &rfc);
1667
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001668 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1669 break;
1670
1671 if (pi->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001672 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001673 pi->fcs = L2CAP_FCS_NONE;
1674 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1675 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001676 break;
1677
1678 case L2CAP_MODE_STREAMING:
1679 rfc.mode = L2CAP_MODE_STREAMING;
1680 rfc.txwin_size = 0;
1681 rfc.max_transmit = 0;
1682 rfc.retrans_timeout = 0;
1683 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001684 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001685 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001686 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001687
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001688 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1689 (unsigned long) &rfc);
1690
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001691 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1692 break;
1693
1694 if (pi->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001695 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001696 pi->fcs = L2CAP_FCS_NONE;
1697 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1698 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001699 break;
1700 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001702 req->dcid = cpu_to_le16(pi->dcid);
1703 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704
1705 return ptr - data;
1706}
1707
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001708static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001710 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001711 struct l2cap_conf_rsp *rsp = data;
1712 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001713 void *req = chan->conf_req;
1714 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001715 int type, hint, olen;
1716 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001717 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001718 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001719 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001721 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001722
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001723 while (len >= L2CAP_CONF_OPT_SIZE) {
1724 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001726 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001727 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001728
1729 switch (type) {
1730 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001731 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001732 break;
1733
1734 case L2CAP_CONF_FLUSH_TO:
1735 pi->flush_to = val;
1736 break;
1737
1738 case L2CAP_CONF_QOS:
1739 break;
1740
Marcel Holtmann6464f352007-10-20 13:39:51 +02001741 case L2CAP_CONF_RFC:
1742 if (olen == sizeof(rfc))
1743 memcpy(&rfc, (void *) val, olen);
1744 break;
1745
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001746 case L2CAP_CONF_FCS:
1747 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001748 chan->conf_state |= L2CAP_CONF_NO_FCS_RECV;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001749
1750 break;
1751
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001752 default:
1753 if (hint)
1754 break;
1755
1756 result = L2CAP_CONF_UNKNOWN;
1757 *((u8 *) ptr++) = type;
1758 break;
1759 }
1760 }
1761
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001762 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001763 goto done;
1764
1765 switch (pi->mode) {
1766 case L2CAP_MODE_STREAMING:
1767 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001768 if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001769 pi->mode = l2cap_select_mode(rfc.mode,
1770 pi->conn->feat_mask);
1771 break;
1772 }
1773
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001774 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001775 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001776
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001777 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001778 }
1779
1780done:
1781 if (pi->mode != rfc.mode) {
1782 result = L2CAP_CONF_UNACCEPT;
1783 rfc.mode = pi->mode;
1784
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001785 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001786 return -ECONNREFUSED;
1787
1788 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1789 sizeof(rfc), (unsigned long) &rfc);
1790 }
1791
1792
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001793 if (result == L2CAP_CONF_SUCCESS) {
1794 /* Configure output options and let the other side know
1795 * which ones we don't like. */
1796
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001797 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1798 result = L2CAP_CONF_UNACCEPT;
1799 else {
1800 pi->omtu = mtu;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001801 chan->conf_state |= L2CAP_CONF_MTU_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001802 }
1803 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001804
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001805 switch (rfc.mode) {
1806 case L2CAP_MODE_BASIC:
1807 pi->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001808 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001809 break;
1810
1811 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001812 chan->remote_tx_win = rfc.txwin_size;
1813 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001814
1815 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1816 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001817
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001818 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001819
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001820 rfc.retrans_timeout =
1821 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1822 rfc.monitor_timeout =
1823 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001824
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001825 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001826
1827 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1828 sizeof(rfc), (unsigned long) &rfc);
1829
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001830 break;
1831
1832 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001833 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1834 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001835
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001836 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001837
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001838 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001839
1840 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1841 sizeof(rfc), (unsigned long) &rfc);
1842
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001843 break;
1844
1845 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001846 result = L2CAP_CONF_UNACCEPT;
1847
1848 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001849 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001850 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001851
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001852 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001853 chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001854 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001855 rsp->scid = cpu_to_le16(pi->dcid);
1856 rsp->result = cpu_to_le16(result);
1857 rsp->flags = cpu_to_le16(0x0000);
1858
1859 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860}
1861
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001862static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001863{
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001864 struct sock *sk = chan->sk;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001865 struct l2cap_pinfo *pi = l2cap_pi(sk);
1866 struct l2cap_conf_req *req = data;
1867 void *ptr = req->data;
1868 int type, olen;
1869 unsigned long val;
1870 struct l2cap_conf_rfc rfc;
1871
1872 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1873
1874 while (len >= L2CAP_CONF_OPT_SIZE) {
1875 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1876
1877 switch (type) {
1878 case L2CAP_CONF_MTU:
1879 if (val < L2CAP_DEFAULT_MIN_MTU) {
1880 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001881 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001882 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001883 pi->imtu = val;
1884 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001885 break;
1886
1887 case L2CAP_CONF_FLUSH_TO:
1888 pi->flush_to = val;
1889 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1890 2, pi->flush_to);
1891 break;
1892
1893 case L2CAP_CONF_RFC:
1894 if (olen == sizeof(rfc))
1895 memcpy(&rfc, (void *)val, olen);
1896
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001897 if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001898 rfc.mode != pi->mode)
1899 return -ECONNREFUSED;
1900
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001901 pi->fcs = 0;
1902
1903 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1904 sizeof(rfc), (unsigned long) &rfc);
1905 break;
1906 }
1907 }
1908
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001909 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1910 return -ECONNREFUSED;
1911
1912 pi->mode = rfc.mode;
1913
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001914 if (*result == L2CAP_CONF_SUCCESS) {
1915 switch (rfc.mode) {
1916 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001917 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1918 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001919 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001920 break;
1921 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001922 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001923 }
1924 }
1925
1926 req->dcid = cpu_to_le16(pi->dcid);
1927 req->flags = cpu_to_le16(0x0000);
1928
1929 return ptr - data;
1930}
1931
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001932static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933{
1934 struct l2cap_conf_rsp *rsp = data;
1935 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001937 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001939 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001940 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001941 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942
1943 return ptr - data;
1944}
1945
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001946void __l2cap_connect_rsp_defer(struct sock *sk)
1947{
1948 struct l2cap_conn_rsp rsp;
1949 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1950 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
1951 u8 buf[128];
1952
1953 sk->sk_state = BT_CONFIG;
1954
1955 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1956 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1957 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1958 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1959 l2cap_send_cmd(conn, chan->ident,
1960 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1961
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001962 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001963 return;
1964
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001965 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001966 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1967 l2cap_build_conf_req(chan, buf), buf);
1968 chan->num_conf_req++;
1969}
1970
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001971static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1972{
1973 struct l2cap_pinfo *pi = l2cap_pi(sk);
1974 int type, olen;
1975 unsigned long val;
1976 struct l2cap_conf_rfc rfc;
1977
1978 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1979
1980 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1981 return;
1982
1983 while (len >= L2CAP_CONF_OPT_SIZE) {
1984 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1985
1986 switch (type) {
1987 case L2CAP_CONF_RFC:
1988 if (olen == sizeof(rfc))
1989 memcpy(&rfc, (void *)val, olen);
1990 goto done;
1991 }
1992 }
1993
1994done:
1995 switch (rfc.mode) {
1996 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001997 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1998 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001999 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2000 break;
2001 case L2CAP_MODE_STREAMING:
2002 pi->mps = le16_to_cpu(rfc.max_pdu_size);
2003 }
2004}
2005
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002006static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2007{
2008 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2009
2010 if (rej->reason != 0x0000)
2011 return 0;
2012
2013 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2014 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002015 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002016
2017 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002018 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002019
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002020 l2cap_conn_start(conn);
2021 }
2022
2023 return 0;
2024}
2025
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2027{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2029 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002030 struct l2cap_chan *chan = NULL;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002031 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002032 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033
2034 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002035 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036
2037 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2038
2039 /* Check if we have socket listening on psm */
2040 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2041 if (!parent) {
2042 result = L2CAP_CR_BAD_PSM;
2043 goto sendresp;
2044 }
2045
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002046 bh_lock_sock(parent);
2047
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002048 /* Check if the ACL is secure enough (if not SDP) */
2049 if (psm != cpu_to_le16(0x0001) &&
2050 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002051 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002052 result = L2CAP_CR_SEC_BLOCK;
2053 goto response;
2054 }
2055
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056 result = L2CAP_CR_NO_MEM;
2057
2058 /* Check for backlog size */
2059 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002060 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 goto response;
2062 }
2063
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002064 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 if (!sk)
2066 goto response;
2067
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002068 chan = l2cap_chan_alloc(sk);
2069 if (!chan) {
2070 l2cap_sock_kill(sk);
2071 goto response;
2072 }
2073
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03002074 l2cap_pi(sk)->chan = chan;
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
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098 dcid = l2cap_pi(sk)->scid;
2099
2100 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2101
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002102 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103
Marcel Holtmann984947d2009-02-06 23:35:19 +01002104 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002105 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002106 if (bt_sk(sk)->defer_setup) {
2107 sk->sk_state = BT_CONNECT2;
2108 result = L2CAP_CR_PEND;
2109 status = L2CAP_CS_AUTHOR_PEND;
2110 parent->sk_data_ready(parent, 0);
2111 } else {
2112 sk->sk_state = BT_CONFIG;
2113 result = L2CAP_CR_SUCCESS;
2114 status = L2CAP_CS_NO_INFO;
2115 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002116 } else {
2117 sk->sk_state = BT_CONNECT2;
2118 result = L2CAP_CR_PEND;
2119 status = L2CAP_CS_AUTHEN_PEND;
2120 }
2121 } else {
2122 sk->sk_state = BT_CONNECT2;
2123 result = L2CAP_CR_PEND;
2124 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 }
2126
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002127 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128
2129response:
2130 bh_unlock_sock(parent);
2131
2132sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002133 rsp.scid = cpu_to_le16(scid);
2134 rsp.dcid = cpu_to_le16(dcid);
2135 rsp.result = cpu_to_le16(result);
2136 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002138
2139 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2140 struct l2cap_info_req info;
2141 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2142
2143 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2144 conn->info_ident = l2cap_get_ident(conn);
2145
2146 mod_timer(&conn->info_timer, jiffies +
2147 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2148
2149 l2cap_send_cmd(conn, conn->info_ident,
2150 L2CAP_INFO_REQ, sizeof(info), &info);
2151 }
2152
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002153 if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002154 result == L2CAP_CR_SUCCESS) {
2155 u8 buf[128];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002156 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002157 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002158 l2cap_build_conf_req(chan, buf), buf);
2159 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002160 }
2161
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 return 0;
2163}
2164
2165static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2166{
2167 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2168 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002169 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170 struct sock *sk;
2171 u8 req[128];
2172
2173 scid = __le16_to_cpu(rsp->scid);
2174 dcid = __le16_to_cpu(rsp->dcid);
2175 result = __le16_to_cpu(rsp->result);
2176 status = __le16_to_cpu(rsp->status);
2177
2178 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2179
2180 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002181 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002182 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002183 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002185 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002186 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002187 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 }
2189
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002190 sk = chan->sk;
2191
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 switch (result) {
2193 case L2CAP_CR_SUCCESS:
2194 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002195 chan->ident = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 l2cap_pi(sk)->dcid = dcid;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002197 chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002198
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002199 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002200 break;
2201
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002202 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002203
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002205 l2cap_build_conf_req(chan, req), req);
2206 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 break;
2208
2209 case L2CAP_CR_PEND:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002210 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 break;
2212
2213 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002214 /* don't delete l2cap channel if sk is owned by user */
2215 if (sock_owned_by_user(sk)) {
2216 sk->sk_state = BT_DISCONN;
2217 l2cap_sock_clear_timer(sk);
2218 l2cap_sock_set_timer(sk, HZ / 5);
2219 break;
2220 }
2221
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002222 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 break;
2224 }
2225
2226 bh_unlock_sock(sk);
2227 return 0;
2228}
2229
Mat Martineau8c462b62010-08-24 15:35:42 -07002230static inline void set_default_fcs(struct l2cap_pinfo *pi)
2231{
2232 /* FCS is enabled only in ERTM or streaming mode, if one or both
2233 * sides request it.
2234 */
2235 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2236 pi->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002237 else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
Mat Martineau8c462b62010-08-24 15:35:42 -07002238 pi->fcs = L2CAP_FCS_CRC16;
2239}
2240
Al Viro88219a02007-07-29 00:17:25 -07002241static 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 -07002242{
2243 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2244 u16 dcid, flags;
2245 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002246 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002248 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249
2250 dcid = __le16_to_cpu(req->dcid);
2251 flags = __le16_to_cpu(req->flags);
2252
2253 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2254
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002255 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002256 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 return -ENOENT;
2258
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002259 sk = chan->sk;
2260
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002261 if (sk->sk_state != BT_CONFIG) {
2262 struct l2cap_cmd_rej rej;
2263
2264 rej.reason = cpu_to_le16(0x0002);
2265 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2266 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002267 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002268 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002269
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002270 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002271 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002272 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002273 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2274 l2cap_build_conf_rsp(sk, rsp,
2275 L2CAP_CONF_REJECT, flags), rsp);
2276 goto unlock;
2277 }
2278
2279 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002280 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2281 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282
2283 if (flags & 0x0001) {
2284 /* Incomplete config. Send empty response. */
2285 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002286 l2cap_build_conf_rsp(sk, rsp,
2287 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 goto unlock;
2289 }
2290
2291 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002292 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002293 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002294 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002296 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002298 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002299 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002300
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002301 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002302 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002303
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002304 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002305 goto unlock;
2306
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002307 if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002308 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002309
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002311
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002312 chan->next_tx_seq = 0;
2313 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002314 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002315 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002316 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002317
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002319 goto unlock;
2320 }
2321
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002322 if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002323 u8 buf[64];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002324 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002326 l2cap_build_conf_req(chan, buf), buf);
2327 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 }
2329
2330unlock:
2331 bh_unlock_sock(sk);
2332 return 0;
2333}
2334
2335static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2336{
2337 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2338 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002339 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002341 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342
2343 scid = __le16_to_cpu(rsp->scid);
2344 flags = __le16_to_cpu(rsp->flags);
2345 result = __le16_to_cpu(rsp->result);
2346
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002347 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2348 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002350 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002351 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 return 0;
2353
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002354 sk = chan->sk;
2355
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 switch (result) {
2357 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002358 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 break;
2360
2361 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002362 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002363 char req[64];
2364
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002365 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002366 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002367 goto done;
2368 }
2369
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002370 /* throw out any old stored conf requests */
2371 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002372 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2373 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002374 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002375 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002376 goto done;
2377 }
2378
2379 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2380 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002381 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002382 if (result != L2CAP_CONF_SUCCESS)
2383 goto done;
2384 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385 }
2386
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002387 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002388 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002390 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 goto done;
2392 }
2393
2394 if (flags & 0x01)
2395 goto done;
2396
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002397 chan->conf_state |= L2CAP_CONF_INPUT_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002399 if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002400 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002401
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002403 chan->next_tx_seq = 0;
2404 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002405 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002406 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002407 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002408
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409 l2cap_chan_ready(sk);
2410 }
2411
2412done:
2413 bh_unlock_sock(sk);
2414 return 0;
2415}
2416
2417static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2418{
2419 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2420 struct l2cap_disconn_rsp rsp;
2421 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002422 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 struct sock *sk;
2424
2425 scid = __le16_to_cpu(req->scid);
2426 dcid = __le16_to_cpu(req->dcid);
2427
2428 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2429
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002430 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002431 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 return 0;
2433
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002434 sk = chan->sk;
2435
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002436 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2437 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2439
2440 sk->sk_shutdown = SHUTDOWN_MASK;
2441
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002442 /* don't delete l2cap channel if sk is owned by user */
2443 if (sock_owned_by_user(sk)) {
2444 sk->sk_state = BT_DISCONN;
2445 l2cap_sock_clear_timer(sk);
2446 l2cap_sock_set_timer(sk, HZ / 5);
2447 bh_unlock_sock(sk);
2448 return 0;
2449 }
2450
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002451 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 bh_unlock_sock(sk);
2453
2454 l2cap_sock_kill(sk);
2455 return 0;
2456}
2457
2458static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2459{
2460 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2461 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002462 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 struct sock *sk;
2464
2465 scid = __le16_to_cpu(rsp->scid);
2466 dcid = __le16_to_cpu(rsp->dcid);
2467
2468 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2469
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002470 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002471 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472 return 0;
2473
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002474 sk = chan->sk;
2475
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002476 /* don't delete l2cap channel if sk is owned by user */
2477 if (sock_owned_by_user(sk)) {
2478 sk->sk_state = BT_DISCONN;
2479 l2cap_sock_clear_timer(sk);
2480 l2cap_sock_set_timer(sk, HZ / 5);
2481 bh_unlock_sock(sk);
2482 return 0;
2483 }
2484
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002485 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486 bh_unlock_sock(sk);
2487
2488 l2cap_sock_kill(sk);
2489 return 0;
2490}
2491
2492static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2493{
2494 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495 u16 type;
2496
2497 type = __le16_to_cpu(req->type);
2498
2499 BT_DBG("type 0x%4.4x", type);
2500
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002501 if (type == L2CAP_IT_FEAT_MASK) {
2502 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002503 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002504 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2505 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2506 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002507 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002508 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2509 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002510 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002511 l2cap_send_cmd(conn, cmd->ident,
2512 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002513 } else if (type == L2CAP_IT_FIXED_CHAN) {
2514 u8 buf[12];
2515 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2516 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2517 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2518 memcpy(buf + 4, l2cap_fixed_chan, 8);
2519 l2cap_send_cmd(conn, cmd->ident,
2520 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002521 } else {
2522 struct l2cap_info_rsp rsp;
2523 rsp.type = cpu_to_le16(type);
2524 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2525 l2cap_send_cmd(conn, cmd->ident,
2526 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2527 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528
2529 return 0;
2530}
2531
2532static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2533{
2534 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2535 u16 type, result;
2536
2537 type = __le16_to_cpu(rsp->type);
2538 result = __le16_to_cpu(rsp->result);
2539
2540 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2541
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002542 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2543 if (cmd->ident != conn->info_ident ||
2544 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2545 return 0;
2546
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002547 del_timer(&conn->info_timer);
2548
Ville Tervoadb08ed2010-08-04 09:43:33 +03002549 if (result != L2CAP_IR_SUCCESS) {
2550 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2551 conn->info_ident = 0;
2552
2553 l2cap_conn_start(conn);
2554
2555 return 0;
2556 }
2557
Marcel Holtmann984947d2009-02-06 23:35:19 +01002558 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002559 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002560
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002561 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002562 struct l2cap_info_req req;
2563 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2564
2565 conn->info_ident = l2cap_get_ident(conn);
2566
2567 l2cap_send_cmd(conn, conn->info_ident,
2568 L2CAP_INFO_REQ, sizeof(req), &req);
2569 } else {
2570 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2571 conn->info_ident = 0;
2572
2573 l2cap_conn_start(conn);
2574 }
2575 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002576 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002577 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002578
2579 l2cap_conn_start(conn);
2580 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002581
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582 return 0;
2583}
2584
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002585static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002586 u16 to_multiplier)
2587{
2588 u16 max_latency;
2589
2590 if (min > max || min < 6 || max > 3200)
2591 return -EINVAL;
2592
2593 if (to_multiplier < 10 || to_multiplier > 3200)
2594 return -EINVAL;
2595
2596 if (max >= to_multiplier * 8)
2597 return -EINVAL;
2598
2599 max_latency = (to_multiplier * 8 / max) - 1;
2600 if (latency > 499 || latency > max_latency)
2601 return -EINVAL;
2602
2603 return 0;
2604}
2605
2606static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2607 struct l2cap_cmd_hdr *cmd, u8 *data)
2608{
2609 struct hci_conn *hcon = conn->hcon;
2610 struct l2cap_conn_param_update_req *req;
2611 struct l2cap_conn_param_update_rsp rsp;
2612 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002613 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002614
2615 if (!(hcon->link_mode & HCI_LM_MASTER))
2616 return -EINVAL;
2617
2618 cmd_len = __le16_to_cpu(cmd->len);
2619 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2620 return -EPROTO;
2621
2622 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002623 min = __le16_to_cpu(req->min);
2624 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002625 latency = __le16_to_cpu(req->latency);
2626 to_multiplier = __le16_to_cpu(req->to_multiplier);
2627
2628 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2629 min, max, latency, to_multiplier);
2630
2631 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002632
2633 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2634 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002635 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2636 else
2637 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2638
2639 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2640 sizeof(rsp), &rsp);
2641
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002642 if (!err)
2643 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2644
Claudio Takahaside731152011-02-11 19:28:55 -02002645 return 0;
2646}
2647
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002648static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2649 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2650{
2651 int err = 0;
2652
2653 switch (cmd->code) {
2654 case L2CAP_COMMAND_REJ:
2655 l2cap_command_rej(conn, cmd, data);
2656 break;
2657
2658 case L2CAP_CONN_REQ:
2659 err = l2cap_connect_req(conn, cmd, data);
2660 break;
2661
2662 case L2CAP_CONN_RSP:
2663 err = l2cap_connect_rsp(conn, cmd, data);
2664 break;
2665
2666 case L2CAP_CONF_REQ:
2667 err = l2cap_config_req(conn, cmd, cmd_len, data);
2668 break;
2669
2670 case L2CAP_CONF_RSP:
2671 err = l2cap_config_rsp(conn, cmd, data);
2672 break;
2673
2674 case L2CAP_DISCONN_REQ:
2675 err = l2cap_disconnect_req(conn, cmd, data);
2676 break;
2677
2678 case L2CAP_DISCONN_RSP:
2679 err = l2cap_disconnect_rsp(conn, cmd, data);
2680 break;
2681
2682 case L2CAP_ECHO_REQ:
2683 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2684 break;
2685
2686 case L2CAP_ECHO_RSP:
2687 break;
2688
2689 case L2CAP_INFO_REQ:
2690 err = l2cap_information_req(conn, cmd, data);
2691 break;
2692
2693 case L2CAP_INFO_RSP:
2694 err = l2cap_information_rsp(conn, cmd, data);
2695 break;
2696
2697 default:
2698 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2699 err = -EINVAL;
2700 break;
2701 }
2702
2703 return err;
2704}
2705
2706static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2707 struct l2cap_cmd_hdr *cmd, u8 *data)
2708{
2709 switch (cmd->code) {
2710 case L2CAP_COMMAND_REJ:
2711 return 0;
2712
2713 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002714 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002715
2716 case L2CAP_CONN_PARAM_UPDATE_RSP:
2717 return 0;
2718
2719 default:
2720 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2721 return -EINVAL;
2722 }
2723}
2724
2725static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2726 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727{
2728 u8 *data = skb->data;
2729 int len = skb->len;
2730 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002731 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732
2733 l2cap_raw_recv(conn, skb);
2734
2735 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002736 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2738 data += L2CAP_CMD_HDR_SIZE;
2739 len -= L2CAP_CMD_HDR_SIZE;
2740
Al Viro88219a02007-07-29 00:17:25 -07002741 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742
Al Viro88219a02007-07-29 00:17:25 -07002743 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 -07002744
Al Viro88219a02007-07-29 00:17:25 -07002745 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746 BT_DBG("corrupted command");
2747 break;
2748 }
2749
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002750 if (conn->hcon->type == LE_LINK)
2751 err = l2cap_le_sig_cmd(conn, &cmd, data);
2752 else
2753 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754
2755 if (err) {
2756 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002757
2758 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759
2760 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002761 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2763 }
2764
Al Viro88219a02007-07-29 00:17:25 -07002765 data += cmd_len;
2766 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 }
2768
2769 kfree_skb(skb);
2770}
2771
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002772static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2773{
2774 u16 our_fcs, rcv_fcs;
2775 int hdr_size = L2CAP_HDR_SIZE + 2;
2776
2777 if (pi->fcs == L2CAP_FCS_CRC16) {
2778 skb_trim(skb, skb->len - 2);
2779 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2780 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2781
2782 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002783 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002784 }
2785 return 0;
2786}
2787
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002788static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002789{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002790 u16 control = 0;
2791
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002792 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002793
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002794 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002795
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002796 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002797 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002798 l2cap_send_sframe(chan, control);
2799 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002800 }
2801
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002802 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2803 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002804
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002805 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002806
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002807 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002808 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002809 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002810 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002811 }
2812}
2813
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002814static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u8 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002815{
2816 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002817 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002818
2819 bt_cb(skb)->tx_seq = tx_seq;
2820 bt_cb(skb)->sar = sar;
2821
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002822 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002823 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002824 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002825 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002826 }
2827
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002828 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002829 if (tx_seq_offset < 0)
2830 tx_seq_offset += 64;
2831
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002832 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002833 if (bt_cb(next_skb)->tx_seq == tx_seq)
2834 return -EINVAL;
2835
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002836 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002837 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002838 if (next_tx_seq_offset < 0)
2839 next_tx_seq_offset += 64;
2840
2841 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002842 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002843 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002844 }
2845
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002846 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002847 break;
2848
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002849 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002850
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002851 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002852
2853 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002854}
2855
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002856static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002857{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002858 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002859 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002860 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002861
2862 switch (control & L2CAP_CTRL_SAR) {
2863 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002864 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002865 goto drop;
2866
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002867 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002868 if (!err)
2869 return err;
2870
2871 break;
2872
2873 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002874 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002875 goto drop;
2876
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002877 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002878
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002879 if (chan->sdu_len > pi->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002880 goto disconnect;
2881
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002882 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
2883 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002884 return -ENOMEM;
2885
2886 /* pull sdu_len bytes only after alloc, because of Local Busy
2887 * condition we have to be sure that this will be executed
2888 * only once, i.e., when alloc does not fail */
2889 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002890
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002891 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002892
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002893 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002894 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002895 break;
2896
2897 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002898 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002899 goto disconnect;
2900
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002901 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002902 goto disconnect;
2903
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002904 chan->partial_sdu_len += skb->len;
2905 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002906 goto drop;
2907
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002908 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002909
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002910 break;
2911
2912 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002913 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002914 goto disconnect;
2915
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002916 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002917 goto disconnect;
2918
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002919 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002920 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002921
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002922 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002923 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002924
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002925 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002926 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002927
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002928 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002929 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002930
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002931 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002932 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002933 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002934 return -ENOMEM;
2935 }
2936
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002937 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002938 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002939 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002940 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002941 return err;
2942 }
2943
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002944 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2945 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002946
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002947 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002948 break;
2949 }
2950
2951 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002952 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002953
2954drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002955 kfree_skb(chan->sdu);
2956 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002957
2958disconnect:
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002959 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002960 kfree_skb(skb);
2961 return 0;
2962}
2963
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002964static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002965{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002966 struct sk_buff *skb;
2967 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002968 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002969
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002970 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002971 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002972 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002973 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002974 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002975 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002976 }
2977
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002978 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002979 }
2980
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002981 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002982 goto done;
2983
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002984 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002985 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002986 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002987 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002988
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002989 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002990 __mod_monitor_timer();
2991
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002992 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002993
2994done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002995 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2996 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002997
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002998 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002999
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003000 return 0;
3001}
3002
3003static void l2cap_busy_work(struct work_struct *work)
3004{
3005 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003006 struct l2cap_chan *chan =
3007 container_of(work, struct l2cap_chan, busy_work);
3008 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003009 int n_tries = 0, timeo = HZ/5, err;
3010 struct sk_buff *skb;
3011
3012 lock_sock(sk);
3013
3014 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003015 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003016 set_current_state(TASK_INTERRUPTIBLE);
3017
3018 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3019 err = -EBUSY;
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003020 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003021 break;
3022 }
3023
3024 if (!timeo)
3025 timeo = HZ/5;
3026
3027 if (signal_pending(current)) {
3028 err = sock_intr_errno(timeo);
3029 break;
3030 }
3031
3032 release_sock(sk);
3033 timeo = schedule_timeout(timeo);
3034 lock_sock(sk);
3035
3036 err = sock_error(sk);
3037 if (err)
3038 break;
3039
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003040 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003041 break;
3042 }
3043
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003044 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003045 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003046
3047 release_sock(sk);
3048}
3049
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003050static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003051{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003052 int sctrl, err;
3053
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003054 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003055 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003056 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003057 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003058
3059
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003060 }
3061
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003062 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003063 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003064 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003065 return err;
3066 }
3067
3068 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003069 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003070
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003071 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003072 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003073 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003074
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003075 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003076 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003077 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003078
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003079 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003080
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003081 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003082
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003083 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003084
3085 return err;
3086}
3087
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003088static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003089{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003090 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003091 struct sk_buff *_skb;
3092 int err = -EINVAL;
3093
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003094 /*
3095 * TODO: We have to notify the userland if some data is lost with the
3096 * Streaming Mode.
3097 */
3098
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003099 switch (control & L2CAP_CTRL_SAR) {
3100 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003101 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003102 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003103 break;
3104 }
3105
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003106 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003107 if (!err)
3108 return 0;
3109
3110 break;
3111
3112 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003113 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003114 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003115 break;
3116 }
3117
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003118 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003119 skb_pull(skb, 2);
3120
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003121 if (chan->sdu_len > pi->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003122 err = -EMSGSIZE;
3123 break;
3124 }
3125
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003126 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3127 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003128 err = -ENOMEM;
3129 break;
3130 }
3131
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003132 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003133
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003134 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003135 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003136 err = 0;
3137 break;
3138
3139 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003140 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003141 break;
3142
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003143 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003144
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003145 chan->partial_sdu_len += skb->len;
3146 if (chan->partial_sdu_len > chan->sdu_len)
3147 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003148 else
3149 err = 0;
3150
3151 break;
3152
3153 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003154 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003155 break;
3156
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003157 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003158
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003159 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003160 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003161
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003162 if (chan->partial_sdu_len > pi->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003163 goto drop;
3164
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003165 if (chan->partial_sdu_len == chan->sdu_len) {
3166 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003167 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003168 if (err < 0)
3169 kfree_skb(_skb);
3170 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003171 err = 0;
3172
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003173drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003174 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003175 break;
3176 }
3177
3178 kfree_skb(skb);
3179 return err;
3180}
3181
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003182static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003183{
3184 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003185 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003186
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003187 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003188 if (bt_cb(skb)->tx_seq != tx_seq)
3189 break;
3190
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003191 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003192 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003193 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003194 chan->buffer_seq_srej =
3195 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003196 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003197 }
3198}
3199
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003200static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003201{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003202 struct srej_list *l, *tmp;
3203 u16 control;
3204
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003205 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003206 if (l->tx_seq == tx_seq) {
3207 list_del(&l->list);
3208 kfree(l);
3209 return;
3210 }
3211 control = L2CAP_SUPER_SELECT_REJECT;
3212 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003213 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003214 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003215 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003216 }
3217}
3218
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003219static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003220{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003221 struct srej_list *new;
3222 u16 control;
3223
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003224 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003225 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003226 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003227 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003228
3229 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003230 new->tx_seq = chan->expected_tx_seq;
3231 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003232 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003233 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003234 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003235}
3236
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003237static 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 -03003238{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003239 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003240 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003241 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003242 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003243 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003244 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003245 int err = 0;
3246
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003247 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3248 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003249
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003250 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003251 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003252 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003253 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003254 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003255 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003256 }
3257
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003258 chan->expected_ack_seq = req_seq;
3259 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003260
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003261 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003262 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003263
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003264 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003265 if (tx_seq_offset < 0)
3266 tx_seq_offset += 64;
3267
3268 /* invalid tx_seq */
3269 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003270 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003271 goto drop;
3272 }
3273
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003274 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003275 goto drop;
3276
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003277 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003278 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003279
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003280 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003281 struct srej_list, list);
3282 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003283 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003284 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003285
3286 list_del(&first->list);
3287 kfree(first);
3288
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003289 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003290 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003291 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3292 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003293 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003294 }
3295 } else {
3296 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003297
3298 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003299 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003300 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003301
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003302 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003303 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003304 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003305 return 0;
3306 }
3307 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003308 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003309 }
3310 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003311 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003312 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003313 if (expected_tx_seq_offset < 0)
3314 expected_tx_seq_offset += 64;
3315
3316 /* duplicated tx_seq */
3317 if (tx_seq_offset < expected_tx_seq_offset)
3318 goto drop;
3319
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003320 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003321
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003322 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003323
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003324 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003325 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003326
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003327 __skb_queue_head_init(&chan->srej_q);
3328 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003329 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003330
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003331 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003332
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003333 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003334
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003335 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003336 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003337 return 0;
3338
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003339expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003340 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003341
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003342 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003343 bt_cb(skb)->tx_seq = tx_seq;
3344 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003345 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003346 return 0;
3347 }
3348
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003349 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003350 if (err < 0)
3351 return 0;
3352
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003353 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003354 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3355 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003356 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003357 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003358 }
3359
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003360 __mod_ack_timer();
3361
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003362 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3363 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003364 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003365
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003366 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003367
3368drop:
3369 kfree_skb(skb);
3370 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003371}
3372
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003373static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003374{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003375 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003376 rx_control);
3377
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003378 chan->expected_ack_seq = __get_reqseq(rx_control);
3379 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003380
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003381 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003382 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3383 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3384 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003385 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003386 __mod_retrans_timer();
3387
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003388 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3389 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003390 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003391 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003392 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003393
3394 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003395 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003396
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003397 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3398 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003399 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003400 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003401
3402 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003403 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003404 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003405 __mod_retrans_timer();
3406
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003407 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3408 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3409 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003410 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003411 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003412 }
3413}
3414
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003415static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003416{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003417 u8 tx_seq = __get_reqseq(rx_control);
3418
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003419 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003420
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003421 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003422
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003423 chan->expected_ack_seq = tx_seq;
3424 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003425
3426 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003427 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3428 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003429 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003430 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003431 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003432 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003433
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003434 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3435 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003436 }
3437}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003438static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003439{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003440 u8 tx_seq = __get_reqseq(rx_control);
3441
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003442 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003443
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003444 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003445
3446 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003447 chan->expected_ack_seq = tx_seq;
3448 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003449
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003450 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3451 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003452
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003453 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003454
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003455 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003456 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003457 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003458 }
3459 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003460 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003461 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003462 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003463 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003464 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003465 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003466 l2cap_retransmit_one_frame(chan, tx_seq);
3467 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003468 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003469 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003470 }
3471 }
3472}
3473
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003474static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003475{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003476 u8 tx_seq = __get_reqseq(rx_control);
3477
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003478 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003479
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003480 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003481 chan->expected_ack_seq = tx_seq;
3482 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003483
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003484 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003485 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003486
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003487 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003488 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003489 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003490 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003491 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003492 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003493
3494 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003495 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003496 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003497 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003498}
3499
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003500static 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 -03003501{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003502 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003503
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003504 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003505 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003506 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003507 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003508 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003509 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003510 }
3511
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003512 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3513 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003514 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003515 break;
3516
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003517 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003518 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003519 break;
3520
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003521 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003522 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003523 break;
3524
3525 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003526 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003527 break;
3528 }
3529
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003530 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003531 return 0;
3532}
3533
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003534static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3535{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003536 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003537 struct l2cap_pinfo *pi = l2cap_pi(sk);
3538 u16 control;
3539 u8 req_seq;
3540 int len, next_tx_seq_offset, req_seq_offset;
3541
3542 control = get_unaligned_le16(skb->data);
3543 skb_pull(skb, 2);
3544 len = skb->len;
3545
3546 /*
3547 * We can just drop the corrupted I-frame here.
3548 * Receiver will miss it and start proper recovery
3549 * procedures and ask retransmission.
3550 */
3551 if (l2cap_check_fcs(pi, skb))
3552 goto drop;
3553
3554 if (__is_sar_start(control) && __is_iframe(control))
3555 len -= 2;
3556
3557 if (pi->fcs == L2CAP_FCS_CRC16)
3558 len -= 2;
3559
3560 if (len > pi->mps) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003561 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003562 goto drop;
3563 }
3564
3565 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003566 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003567 if (req_seq_offset < 0)
3568 req_seq_offset += 64;
3569
3570 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003571 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003572 if (next_tx_seq_offset < 0)
3573 next_tx_seq_offset += 64;
3574
3575 /* check for invalid req-seq */
3576 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003577 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003578 goto drop;
3579 }
3580
3581 if (__is_iframe(control)) {
3582 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003583 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003584 goto drop;
3585 }
3586
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003587 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003588 } else {
3589 if (len != 0) {
3590 BT_ERR("%d", len);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003591 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003592 goto drop;
3593 }
3594
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003595 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003596 }
3597
3598 return 0;
3599
3600drop:
3601 kfree_skb(skb);
3602 return 0;
3603}
3604
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3606{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003607 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003608 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003609 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003610 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003611 u8 tx_seq;
3612 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003614 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003615 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616 BT_DBG("unknown cid 0x%4.4x", cid);
3617 goto drop;
3618 }
3619
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003620 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003621 pi = l2cap_pi(sk);
3622
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003623 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624
3625 if (sk->sk_state != BT_CONNECTED)
3626 goto drop;
3627
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003628 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003629 case L2CAP_MODE_BASIC:
3630 /* If socket recv buffers overflows we drop data here
3631 * which is *bad* because L2CAP has to be reliable.
3632 * But we don't have any other choice. L2CAP doesn't
3633 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003635 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003636 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003638 if (!sock_queue_rcv_skb(sk, skb))
3639 goto done;
3640 break;
3641
3642 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003643 if (!sock_owned_by_user(sk)) {
3644 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003645 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003646 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003647 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003648 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003649
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003650 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003651
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003652 case L2CAP_MODE_STREAMING:
3653 control = get_unaligned_le16(skb->data);
3654 skb_pull(skb, 2);
3655 len = skb->len;
3656
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003657 if (l2cap_check_fcs(pi, skb))
3658 goto drop;
3659
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003660 if (__is_sar_start(control))
3661 len -= 2;
3662
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003663 if (pi->fcs == L2CAP_FCS_CRC16)
3664 len -= 2;
3665
Nathan Holstein51893f82010-06-09 15:46:25 -04003666 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003667 goto drop;
3668
3669 tx_seq = __get_txseq(control);
3670
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003671 if (chan->expected_tx_seq == tx_seq)
3672 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003673 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003674 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003675
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003676 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003677
3678 goto done;
3679
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003680 default:
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003681 BT_DBG("chan %p: bad mode 0x%2.2x", chan, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003682 break;
3683 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684
3685drop:
3686 kfree_skb(skb);
3687
3688done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003689 if (sk)
3690 bh_unlock_sock(sk);
3691
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692 return 0;
3693}
3694
Al Viro8e036fc2007-07-29 00:16:36 -07003695static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696{
3697 struct sock *sk;
3698
3699 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3700 if (!sk)
3701 goto drop;
3702
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003703 bh_lock_sock(sk);
3704
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705 BT_DBG("sk %p, len %d", sk, skb->len);
3706
3707 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3708 goto drop;
3709
3710 if (l2cap_pi(sk)->imtu < skb->len)
3711 goto drop;
3712
3713 if (!sock_queue_rcv_skb(sk, skb))
3714 goto done;
3715
3716drop:
3717 kfree_skb(skb);
3718
3719done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003720 if (sk)
3721 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722 return 0;
3723}
3724
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003725static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3726{
3727 struct sock *sk;
3728
3729 sk = l2cap_get_sock_by_scid(0, cid, conn->src);
3730 if (!sk)
3731 goto drop;
3732
3733 bh_lock_sock(sk);
3734
3735 BT_DBG("sk %p, len %d", sk, skb->len);
3736
3737 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3738 goto drop;
3739
3740 if (l2cap_pi(sk)->imtu < skb->len)
3741 goto drop;
3742
3743 if (!sock_queue_rcv_skb(sk, skb))
3744 goto done;
3745
3746drop:
3747 kfree_skb(skb);
3748
3749done:
3750 if (sk)
3751 bh_unlock_sock(sk);
3752 return 0;
3753}
3754
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3756{
3757 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003758 u16 cid, len;
3759 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760
3761 skb_pull(skb, L2CAP_HDR_SIZE);
3762 cid = __le16_to_cpu(lh->cid);
3763 len = __le16_to_cpu(lh->len);
3764
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003765 if (len != skb->len) {
3766 kfree_skb(skb);
3767 return;
3768 }
3769
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3771
3772 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003773 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003774 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775 l2cap_sig_channel(conn, skb);
3776 break;
3777
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003778 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003779 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003780 skb_pull(skb, 2);
3781 l2cap_conless_channel(conn, psm, skb);
3782 break;
3783
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003784 case L2CAP_CID_LE_DATA:
3785 l2cap_att_channel(conn, cid, skb);
3786 break;
3787
Linus Torvalds1da177e2005-04-16 15:20:36 -07003788 default:
3789 l2cap_data_channel(conn, cid, skb);
3790 break;
3791 }
3792}
3793
3794/* ---- L2CAP interface with lower layer (HCI) ---- */
3795
3796static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3797{
3798 int exact = 0, lm1 = 0, lm2 = 0;
3799 register struct sock *sk;
3800 struct hlist_node *node;
3801
3802 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003803 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804
3805 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3806
3807 /* Find listening sockets and check their link_mode */
3808 read_lock(&l2cap_sk_list.lock);
3809 sk_for_each(sk, node, &l2cap_sk_list.head) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003810 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
3811
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812 if (sk->sk_state != BT_LISTEN)
3813 continue;
3814
3815 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003816 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003817 if (chan->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003818 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003820 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3821 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003822 if (chan->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003823 lm2 |= HCI_LM_MASTER;
3824 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003825 }
3826 read_unlock(&l2cap_sk_list.lock);
3827
3828 return exact ? lm1 : lm2;
3829}
3830
3831static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3832{
Marcel Holtmann01394182006-07-03 10:02:46 +02003833 struct l2cap_conn *conn;
3834
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3836
Ville Tervoacd7d372011-02-10 22:38:49 -03003837 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003838 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839
3840 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 conn = l2cap_conn_add(hcon, status);
3842 if (conn)
3843 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003844 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845 l2cap_conn_del(hcon, bt_err(status));
3846
3847 return 0;
3848}
3849
Marcel Holtmann2950f212009-02-12 14:02:50 +01003850static int l2cap_disconn_ind(struct hci_conn *hcon)
3851{
3852 struct l2cap_conn *conn = hcon->l2cap_data;
3853
3854 BT_DBG("hcon %p", hcon);
3855
3856 if (hcon->type != ACL_LINK || !conn)
3857 return 0x13;
3858
3859 return conn->disc_reason;
3860}
3861
3862static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863{
3864 BT_DBG("hcon %p reason %d", hcon, reason);
3865
Ville Tervoacd7d372011-02-10 22:38:49 -03003866 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003867 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868
3869 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003870
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871 return 0;
3872}
3873
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003874static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003875{
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003876 struct sock *sk = chan->sk;
3877
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003878 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003879 return;
3880
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003881 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003882 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003883 l2cap_sock_clear_timer(sk);
3884 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003885 } else if (chan->sec_level == BT_SECURITY_HIGH)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003886 __l2cap_sock_close(sk, ECONNREFUSED);
3887 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003888 if (chan->sec_level == BT_SECURITY_MEDIUM)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003889 l2cap_sock_clear_timer(sk);
3890 }
3891}
3892
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003893static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003895 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003896 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897
Marcel Holtmann01394182006-07-03 10:02:46 +02003898 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003900
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901 BT_DBG("conn %p", conn);
3902
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003903 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003905 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003906 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003907
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908 bh_lock_sock(sk);
3909
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003910 if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003911 bh_unlock_sock(sk);
3912 continue;
3913 }
3914
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003915 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003916 sk->sk_state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003917 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003918 bh_unlock_sock(sk);
3919 continue;
3920 }
3921
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003922 if (sk->sk_state == BT_CONNECT) {
3923 if (!status) {
3924 struct l2cap_conn_req req;
3925 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3926 req.psm = l2cap_pi(sk)->psm;
3927
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003928 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003929 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003930
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003931 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003932 L2CAP_CONN_REQ, sizeof(req), &req);
3933 } else {
3934 l2cap_sock_clear_timer(sk);
3935 l2cap_sock_set_timer(sk, HZ / 10);
3936 }
3937 } else if (sk->sk_state == BT_CONNECT2) {
3938 struct l2cap_conn_rsp rsp;
3939 __u16 result;
3940
3941 if (!status) {
3942 sk->sk_state = BT_CONFIG;
3943 result = L2CAP_CR_SUCCESS;
3944 } else {
3945 sk->sk_state = BT_DISCONN;
3946 l2cap_sock_set_timer(sk, HZ / 10);
3947 result = L2CAP_CR_SEC_BLOCK;
3948 }
3949
3950 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3951 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3952 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003953 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003954 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
3955 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956 }
3957
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 bh_unlock_sock(sk);
3959 }
3960
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003961 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003962
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963 return 0;
3964}
3965
3966static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3967{
3968 struct l2cap_conn *conn = hcon->l2cap_data;
3969
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003970 if (!conn)
3971 conn = l2cap_conn_add(hcon, 0);
3972
3973 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974 goto drop;
3975
3976 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3977
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003978 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003979 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003980 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003981 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982 int len;
3983
3984 if (conn->rx_len) {
3985 BT_ERR("Unexpected start frame (len %d)", skb->len);
3986 kfree_skb(conn->rx_skb);
3987 conn->rx_skb = NULL;
3988 conn->rx_len = 0;
3989 l2cap_conn_unreliable(conn, ECOMM);
3990 }
3991
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003992 /* Start fragment always begin with Basic L2CAP header */
3993 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994 BT_ERR("Frame is too short (len %d)", skb->len);
3995 l2cap_conn_unreliable(conn, ECOMM);
3996 goto drop;
3997 }
3998
3999 hdr = (struct l2cap_hdr *) skb->data;
4000 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004001 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002
4003 if (len == skb->len) {
4004 /* Complete frame received */
4005 l2cap_recv_frame(conn, skb);
4006 return 0;
4007 }
4008
4009 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4010
4011 if (skb->len > len) {
4012 BT_ERR("Frame is too long (len %d, expected len %d)",
4013 skb->len, len);
4014 l2cap_conn_unreliable(conn, ECOMM);
4015 goto drop;
4016 }
4017
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004018 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004019
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004020 if (chan && chan->sk) {
4021 struct sock *sk = chan->sk;
4022
4023 if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
4024 BT_ERR("Frame exceeding recv MTU (len %d, "
4025 "MTU %d)", len,
4026 l2cap_pi(sk)->imtu);
4027 bh_unlock_sock(sk);
4028 l2cap_conn_unreliable(conn, ECOMM);
4029 goto drop;
4030 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004031 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004032 }
4033
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004035 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4036 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037 goto drop;
4038
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004039 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004040 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041 conn->rx_len = len - skb->len;
4042 } else {
4043 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4044
4045 if (!conn->rx_len) {
4046 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4047 l2cap_conn_unreliable(conn, ECOMM);
4048 goto drop;
4049 }
4050
4051 if (skb->len > conn->rx_len) {
4052 BT_ERR("Fragment is too long (len %d, expected %d)",
4053 skb->len, conn->rx_len);
4054 kfree_skb(conn->rx_skb);
4055 conn->rx_skb = NULL;
4056 conn->rx_len = 0;
4057 l2cap_conn_unreliable(conn, ECOMM);
4058 goto drop;
4059 }
4060
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004061 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004062 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063 conn->rx_len -= skb->len;
4064
4065 if (!conn->rx_len) {
4066 /* Complete frame received */
4067 l2cap_recv_frame(conn, conn->rx_skb);
4068 conn->rx_skb = NULL;
4069 }
4070 }
4071
4072drop:
4073 kfree_skb(skb);
4074 return 0;
4075}
4076
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004077static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078{
4079 struct sock *sk;
4080 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081
4082 read_lock_bh(&l2cap_sk_list.lock);
4083
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004084 sk_for_each(sk, node, &l2cap_sk_list.head) {
4085 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004087 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 +01004088 batostr(&bt_sk(sk)->src),
4089 batostr(&bt_sk(sk)->dst),
4090 sk->sk_state, __le16_to_cpu(pi->psm),
4091 pi->scid, pi->dcid,
Gustavo F. Padovan43434782011-04-12 18:31:57 -03004092 pi->imtu, pi->omtu, pi->chan->sec_level,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004093 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004094 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004097
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004098 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099}
4100
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004101static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4102{
4103 return single_open(file, l2cap_debugfs_show, inode->i_private);
4104}
4105
4106static const struct file_operations l2cap_debugfs_fops = {
4107 .open = l2cap_debugfs_open,
4108 .read = seq_read,
4109 .llseek = seq_lseek,
4110 .release = single_release,
4111};
4112
4113static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115static struct hci_proto l2cap_hci_proto = {
4116 .name = "L2CAP",
4117 .id = HCI_PROTO_L2CAP,
4118 .connect_ind = l2cap_connect_ind,
4119 .connect_cfm = l2cap_connect_cfm,
4120 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004121 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004122 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123 .recv_acldata = l2cap_recv_acldata
4124};
4125
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004126int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127{
4128 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004129
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004130 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131 if (err < 0)
4132 return err;
4133
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004134 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004135 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004136 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137 goto error;
4138 }
4139
4140 err = hci_register_proto(&l2cap_hci_proto);
4141 if (err < 0) {
4142 BT_ERR("L2CAP protocol registration failed");
4143 bt_sock_unregister(BTPROTO_L2CAP);
4144 goto error;
4145 }
4146
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004147 if (bt_debugfs) {
4148 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4149 bt_debugfs, NULL, &l2cap_debugfs_fops);
4150 if (!l2cap_debugfs)
4151 BT_ERR("Failed to create L2CAP debug file");
4152 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154 return 0;
4155
4156error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004157 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004158 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159 return err;
4160}
4161
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004162void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004163{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004164 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004166 flush_workqueue(_busy_wq);
4167 destroy_workqueue(_busy_wq);
4168
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4170 BT_ERR("L2CAP protocol unregistration failed");
4171
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004172 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173}
4174
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004175module_param(disable_ertm, bool, 0644);
4176MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");