blob: 7b06375d05a7eb399839f4d1fd738bc2fb010901 [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 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300179 chan->omtu = L2CAP_LE_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300180 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);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300185 chan->omtu = L2CAP_DEFAULT_MTU;
Ville Tervob62f3282011-02-10 22:38:50 -0300186 }
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;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300191 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200192 } 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;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300196 chan->omtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann01394182006-07-03 10:02:46 +0200197 }
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
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300245 if (chan->mode == L2CAP_MODE_ERTM) {
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300246 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. Padovan47d1ec62011-04-13 15:57:03 -0300362 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300363 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. Padovan47d1ec62011-04-13 15:57:03 -0300389 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300390 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. Padovan0c1bc5c2011-04-13 17:20:49 -0300482 if (chan->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
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300526 if (!l2cap_mode_supported(chan->mode,
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300527 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. Padovanccbb84a2010-08-30 18:44:44 -03001025 struct sk_buff *skb;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001026 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001027
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001028 while ((skb = skb_dequeue(&chan->tx_q))) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001029 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001030 control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001031 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001032
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001033 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001034 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1035 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001036 }
1037
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001038 l2cap_do_send(chan, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001039
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001040 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001041 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001042}
1043
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001044static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001045{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001046 struct sock *sk = chan->sk;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001047 struct l2cap_pinfo *pi = l2cap_pi(sk);
1048 struct sk_buff *skb, *tx_skb;
1049 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001050
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001051 skb = skb_peek(&chan->tx_q);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001052 if (!skb)
1053 return;
1054
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001055 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001056 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001057 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001058
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001059 if (skb_queue_is_last(&chan->tx_q, skb))
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001060 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001061
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001062 } while ((skb = skb_queue_next(&chan->tx_q, skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001063
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001064 if (chan->remote_max_tx &&
1065 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001066 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001067 return;
1068 }
1069
1070 tx_skb = skb_clone(skb, GFP_ATOMIC);
1071 bt_cb(skb)->retries++;
1072 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Ruiyi Zhanga429b512011-04-18 11:04:30 +08001073 control &= L2CAP_CTRL_SAR;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001074
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001075 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001076 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001077 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001078 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001079
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001080 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001081 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001082
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001083 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1084
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001085 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001086 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1087 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1088 }
1089
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001090 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001091}
1092
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001093int l2cap_ertm_send(struct l2cap_chan *chan)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001094{
1095 struct sk_buff *skb, *tx_skb;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001096 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001097 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001098 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001099 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001100
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001101 if (sk->sk_state != BT_CONNECTED)
1102 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001103
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001104 while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001105
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001106 if (chan->remote_max_tx &&
1107 bt_cb(skb)->retries == chan->remote_max_tx) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001108 l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001109 break;
1110 }
1111
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001112 tx_skb = skb_clone(skb, GFP_ATOMIC);
1113
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001114 bt_cb(skb)->retries++;
1115
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001116 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001117 control &= L2CAP_CTRL_SAR;
1118
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001119 if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001120 control |= L2CAP_CTRL_FINAL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001121 chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001122 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001123 control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1124 | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001125 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1126
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001127
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001128 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001129 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1130 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1131 }
1132
Gustavo F. Padovan43434782011-04-12 18:31:57 -03001133 l2cap_do_send(chan, tx_skb);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001134
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001135 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001136
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001137 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1138 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001139
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301140 if (bt_cb(skb)->retries == 1)
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001141 chan->unacked_frames++;
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301142
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001143 chan->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001144
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001145 if (skb_queue_is_last(&chan->tx_q, skb))
1146 chan->tx_send_head = NULL;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001147 else
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001148 chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001149
1150 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001151 }
1152
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001153 return nsent;
1154}
1155
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001156static int l2cap_retransmit_frames(struct l2cap_chan *chan)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001157{
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001158 int ret;
1159
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001160 if (!skb_queue_empty(&chan->tx_q))
1161 chan->tx_send_head = chan->tx_q.next;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001162
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001163 chan->next_tx_seq = chan->expected_ack_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001164 ret = l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001165 return ret;
1166}
1167
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001168static void l2cap_send_ack(struct l2cap_chan *chan)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001169{
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001170 u16 control = 0;
1171
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001172 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001173
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001174 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001175 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001176 chan->conn_state |= L2CAP_CONN_RNR_SENT;
1177 l2cap_send_sframe(chan, control);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001178 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001179 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001180
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001181 if (l2cap_ertm_send(chan) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001182 return;
1183
1184 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001185 l2cap_send_sframe(chan, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001186}
1187
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001188static void l2cap_send_srejtail(struct l2cap_chan *chan)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001189{
1190 struct srej_list *tail;
1191 u16 control;
1192
1193 control = L2CAP_SUPER_SELECT_REJECT;
1194 control |= L2CAP_CTRL_FINAL;
1195
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001196 tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001197 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1198
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001199 l2cap_send_sframe(chan, control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001200}
1201
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001202static 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 -07001203{
1204 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001205 struct sk_buff **frag;
1206 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001208 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001209 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
1211 sent += count;
1212 len -= count;
1213
1214 /* Continuation fragments (no L2CAP header) */
1215 frag = &skb_shinfo(skb)->frag_list;
1216 while (len) {
1217 count = min_t(unsigned int, conn->mtu, len);
1218
1219 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1220 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001221 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001222 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1223 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224
1225 sent += count;
1226 len -= count;
1227
1228 frag = &(*frag)->next;
1229 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
1231 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001232}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001234struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001235{
1236 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1237 struct sk_buff *skb;
1238 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1239 struct l2cap_hdr *lh;
1240
1241 BT_DBG("sk %p len %d", sk, (int)len);
1242
1243 count = min_t(unsigned int, (conn->mtu - hlen), len);
1244 skb = bt_skb_send_alloc(sk, count + hlen,
1245 msg->msg_flags & MSG_DONTWAIT, &err);
1246 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001247 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001248
1249 /* Create L2CAP header */
1250 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1251 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1252 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1253 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1254
1255 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1256 if (unlikely(err < 0)) {
1257 kfree_skb(skb);
1258 return ERR_PTR(err);
1259 }
1260 return skb;
1261}
1262
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001263struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001264{
1265 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1266 struct sk_buff *skb;
1267 int err, count, hlen = L2CAP_HDR_SIZE;
1268 struct l2cap_hdr *lh;
1269
1270 BT_DBG("sk %p len %d", sk, (int)len);
1271
1272 count = min_t(unsigned int, (conn->mtu - hlen), len);
1273 skb = bt_skb_send_alloc(sk, count + hlen,
1274 msg->msg_flags & MSG_DONTWAIT, &err);
1275 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001276 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001277
1278 /* Create L2CAP header */
1279 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1280 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1281 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1282
1283 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1284 if (unlikely(err < 0)) {
1285 kfree_skb(skb);
1286 return ERR_PTR(err);
1287 }
1288 return skb;
1289}
1290
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001291struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001292{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001293 struct sock *sk = chan->sk;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001294 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1295 struct sk_buff *skb;
1296 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1297 struct l2cap_hdr *lh;
1298
1299 BT_DBG("sk %p len %d", sk, (int)len);
1300
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001301 if (!conn)
1302 return ERR_PTR(-ENOTCONN);
1303
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001304 if (sdulen)
1305 hlen += 2;
1306
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001307 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001308 hlen += 2;
1309
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001310 count = min_t(unsigned int, (conn->mtu - hlen), len);
1311 skb = bt_skb_send_alloc(sk, count + hlen,
1312 msg->msg_flags & MSG_DONTWAIT, &err);
1313 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001314 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001315
1316 /* Create L2CAP header */
1317 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1318 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1319 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1320 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001321 if (sdulen)
1322 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001323
1324 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1325 if (unlikely(err < 0)) {
1326 kfree_skb(skb);
1327 return ERR_PTR(err);
1328 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001329
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001330 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001331 put_unaligned_le16(0, skb_put(skb, 2));
1332
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001333 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001334 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335}
1336
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001337int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001338{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001339 struct sk_buff *skb;
1340 struct sk_buff_head sar_queue;
1341 u16 control;
1342 size_t size = 0;
1343
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001344 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001345 control = L2CAP_SDU_START;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001346 skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001347 if (IS_ERR(skb))
1348 return PTR_ERR(skb);
1349
1350 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001351 len -= chan->remote_mps;
1352 size += chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001353
1354 while (len > 0) {
1355 size_t buflen;
1356
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001357 if (len > chan->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001358 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001359 buflen = chan->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001360 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001361 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001362 buflen = len;
1363 }
1364
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001365 skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001366 if (IS_ERR(skb)) {
1367 skb_queue_purge(&sar_queue);
1368 return PTR_ERR(skb);
1369 }
1370
1371 __skb_queue_tail(&sar_queue, skb);
1372 len -= buflen;
1373 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001374 }
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03001375 skb_queue_splice_tail(&sar_queue, &chan->tx_q);
1376 if (chan->tx_send_head == NULL)
1377 chan->tx_send_head = sar_queue.next;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001378
1379 return size;
1380}
1381
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382static void l2cap_chan_ready(struct sock *sk)
1383{
1384 struct sock *parent = bt_sk(sk)->parent;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001385 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
1387 BT_DBG("sk %p, parent %p", sk, parent);
1388
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001389 chan->conf_state = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 l2cap_sock_clear_timer(sk);
1391
1392 if (!parent) {
1393 /* Outgoing channel.
1394 * Wake up socket sleeping on connect.
1395 */
1396 sk->sk_state = BT_CONNECTED;
1397 sk->sk_state_change(sk);
1398 } else {
1399 /* Incoming channel.
1400 * Wake up socket sleeping on accept.
1401 */
1402 parent->sk_data_ready(parent, 0);
1403 }
1404}
1405
1406/* Copy frame to all raw sockets on that connection */
1407static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1408{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001410 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411
1412 BT_DBG("conn %p", conn);
1413
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001414 read_lock(&conn->chan_lock);
1415 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001416 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 if (sk->sk_type != SOCK_RAW)
1418 continue;
1419
1420 /* Don't send frame to the socket it came from */
1421 if (skb->sk == sk)
1422 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001423 nskb = skb_clone(skb, GFP_ATOMIC);
1424 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 continue;
1426
1427 if (sock_queue_rcv_skb(sk, nskb))
1428 kfree_skb(nskb);
1429 }
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03001430 read_unlock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431}
1432
1433/* ---- L2CAP signalling commands ---- */
1434static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1435 u8 code, u8 ident, u16 dlen, void *data)
1436{
1437 struct sk_buff *skb, **frag;
1438 struct l2cap_cmd_hdr *cmd;
1439 struct l2cap_hdr *lh;
1440 int len, count;
1441
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001442 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1443 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
1445 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1446 count = min_t(unsigned int, conn->mtu, len);
1447
1448 skb = bt_skb_alloc(count, GFP_ATOMIC);
1449 if (!skb)
1450 return NULL;
1451
1452 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001453 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001454
1455 if (conn->hcon->type == LE_LINK)
1456 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1457 else
1458 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459
1460 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1461 cmd->code = code;
1462 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001463 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
1465 if (dlen) {
1466 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1467 memcpy(skb_put(skb, count), data, count);
1468 data += count;
1469 }
1470
1471 len -= skb->len;
1472
1473 /* Continuation fragments (no L2CAP header) */
1474 frag = &skb_shinfo(skb)->frag_list;
1475 while (len) {
1476 count = min_t(unsigned int, conn->mtu, len);
1477
1478 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1479 if (!*frag)
1480 goto fail;
1481
1482 memcpy(skb_put(*frag, count), data, count);
1483
1484 len -= count;
1485 data += count;
1486
1487 frag = &(*frag)->next;
1488 }
1489
1490 return skb;
1491
1492fail:
1493 kfree_skb(skb);
1494 return NULL;
1495}
1496
1497static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1498{
1499 struct l2cap_conf_opt *opt = *ptr;
1500 int len;
1501
1502 len = L2CAP_CONF_OPT_SIZE + opt->len;
1503 *ptr += len;
1504
1505 *type = opt->type;
1506 *olen = opt->len;
1507
1508 switch (opt->len) {
1509 case 1:
1510 *val = *((u8 *) opt->val);
1511 break;
1512
1513 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001514 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 break;
1516
1517 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001518 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 break;
1520
1521 default:
1522 *val = (unsigned long) opt->val;
1523 break;
1524 }
1525
1526 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1527 return len;
1528}
1529
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1531{
1532 struct l2cap_conf_opt *opt = *ptr;
1533
1534 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1535
1536 opt->type = type;
1537 opt->len = len;
1538
1539 switch (len) {
1540 case 1:
1541 *((u8 *) opt->val) = val;
1542 break;
1543
1544 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001545 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 break;
1547
1548 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001549 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 break;
1551
1552 default:
1553 memcpy(opt->val, (void *) val, len);
1554 break;
1555 }
1556
1557 *ptr += L2CAP_CONF_OPT_SIZE + len;
1558}
1559
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001560static void l2cap_ack_timeout(unsigned long arg)
1561{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001562 struct l2cap_chan *chan = (void *) arg;
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001563
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001564 bh_lock_sock(chan->sk);
1565 l2cap_send_ack(chan);
1566 bh_unlock_sock(chan->sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001567}
1568
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001569static inline void l2cap_ertm_init(struct l2cap_chan *chan)
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001570{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03001571 struct sock *sk = chan->sk;
1572
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001573 chan->expected_ack_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001574 chan->unacked_frames = 0;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03001575 chan->buffer_seq = 0;
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03001576 chan->num_acked = 0;
1577 chan->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001578
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03001579 setup_timer(&chan->retrans_timer, l2cap_retrans_timeout,
1580 (unsigned long) chan);
1581 setup_timer(&chan->monitor_timer, l2cap_monitor_timeout,
1582 (unsigned long) chan);
1583 setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001584
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03001585 skb_queue_head_init(&chan->srej_q);
1586 skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001587
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03001588 INIT_LIST_HEAD(&chan->srej_l);
1589
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03001590 INIT_WORK(&chan->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001591
1592 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001593}
1594
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001595static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1596{
1597 switch (mode) {
1598 case L2CAP_MODE_STREAMING:
1599 case L2CAP_MODE_ERTM:
1600 if (l2cap_mode_supported(mode, remote_feat_mask))
1601 return mode;
1602 /* fall through */
1603 default:
1604 return L2CAP_MODE_BASIC;
1605 }
1606}
1607
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001608static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001610 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611 struct l2cap_conf_req *req = data;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001612 struct l2cap_conf_rfc rfc = { .mode = chan->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 void *ptr = req->data;
1614
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03001615 BT_DBG("chan %p", chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001617 if (chan->num_conf_req || chan->num_conf_rsp)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001618 goto done;
1619
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001620 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001621 case L2CAP_MODE_STREAMING:
1622 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001623 if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001624 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001625
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001626 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001627 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001628 chan->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001629 break;
1630 }
1631
1632done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001633 if (chan->imtu != L2CAP_DEFAULT_MTU)
1634 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001635
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001636 switch (chan->mode) {
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001637 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001638 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1639 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1640 break;
1641
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001642 rfc.mode = L2CAP_MODE_BASIC;
1643 rfc.txwin_size = 0;
1644 rfc.max_transmit = 0;
1645 rfc.retrans_timeout = 0;
1646 rfc.monitor_timeout = 0;
1647 rfc.max_pdu_size = 0;
1648
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001649 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1650 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001651 break;
1652
1653 case L2CAP_MODE_ERTM:
1654 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001655 rfc.txwin_size = chan->tx_win;
1656 rfc.max_transmit = chan->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001657 rfc.retrans_timeout = 0;
1658 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001659 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001660 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001661 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001662
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001663 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1664 (unsigned long) &rfc);
1665
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001666 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1667 break;
1668
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001669 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001670 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001671 chan->fcs = L2CAP_FCS_NONE;
1672 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001673 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001674 break;
1675
1676 case L2CAP_MODE_STREAMING:
1677 rfc.mode = L2CAP_MODE_STREAMING;
1678 rfc.txwin_size = 0;
1679 rfc.max_transmit = 0;
1680 rfc.retrans_timeout = 0;
1681 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001682 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001683 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001684 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001685
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001686 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1687 (unsigned long) &rfc);
1688
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001689 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1690 break;
1691
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001692 if (chan->fcs == L2CAP_FCS_NONE ||
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001693 chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001694 chan->fcs = L2CAP_FCS_NONE;
1695 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001696 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001697 break;
1698 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001700 req->dcid = cpu_to_le16(pi->dcid);
1701 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702
1703 return ptr - data;
1704}
1705
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001706static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707{
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001708 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001709 struct l2cap_conf_rsp *rsp = data;
1710 void *ptr = rsp->data;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001711 void *req = chan->conf_req;
1712 int len = chan->conf_len;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001713 int type, hint, olen;
1714 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001715 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001716 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001717 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001719 BT_DBG("chan %p", chan);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001720
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001721 while (len >= L2CAP_CONF_OPT_SIZE) {
1722 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001724 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001725 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001726
1727 switch (type) {
1728 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001729 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001730 break;
1731
1732 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001733 chan->flush_to = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001734 break;
1735
1736 case L2CAP_CONF_QOS:
1737 break;
1738
Marcel Holtmann6464f352007-10-20 13:39:51 +02001739 case L2CAP_CONF_RFC:
1740 if (olen == sizeof(rfc))
1741 memcpy(&rfc, (void *) val, olen);
1742 break;
1743
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001744 case L2CAP_CONF_FCS:
1745 if (val == L2CAP_FCS_NONE)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001746 chan->conf_state |= L2CAP_CONF_NO_FCS_RECV;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001747
1748 break;
1749
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001750 default:
1751 if (hint)
1752 break;
1753
1754 result = L2CAP_CONF_UNKNOWN;
1755 *((u8 *) ptr++) = type;
1756 break;
1757 }
1758 }
1759
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001760 if (chan->num_conf_rsp || chan->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001761 goto done;
1762
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001763 switch (chan->mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001764 case L2CAP_MODE_STREAMING:
1765 case L2CAP_MODE_ERTM:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001766 if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001767 chan->mode = l2cap_select_mode(rfc.mode,
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001768 pi->conn->feat_mask);
1769 break;
1770 }
1771
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001772 if (chan->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001773 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001774
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001775 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001776 }
1777
1778done:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001779 if (chan->mode != rfc.mode) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001780 result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001781 rfc.mode = chan->mode;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001782
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03001783 if (chan->num_conf_rsp == 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001784 return -ECONNREFUSED;
1785
1786 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1787 sizeof(rfc), (unsigned long) &rfc);
1788 }
1789
1790
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001791 if (result == L2CAP_CONF_SUCCESS) {
1792 /* Configure output options and let the other side know
1793 * which ones we don't like. */
1794
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001795 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1796 result = L2CAP_CONF_UNACCEPT;
1797 else {
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001798 chan->omtu = mtu;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001799 chan->conf_state |= L2CAP_CONF_MTU_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001800 }
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001801 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001802
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001803 switch (rfc.mode) {
1804 case L2CAP_MODE_BASIC:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001805 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001806 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001807 break;
1808
1809 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001810 chan->remote_tx_win = rfc.txwin_size;
1811 chan->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001812
1813 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1814 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001815
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001816 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001817
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001818 rfc.retrans_timeout =
1819 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1820 rfc.monitor_timeout =
1821 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001822
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001823 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001824
1825 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1826 sizeof(rfc), (unsigned long) &rfc);
1827
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001828 break;
1829
1830 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001831 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1832 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001833
Gustavo F. Padovan2c03a7a2011-03-25 20:15:28 -03001834 chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001835
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001836 chan->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001837
1838 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1839 sizeof(rfc), (unsigned long) &rfc);
1840
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001841 break;
1842
1843 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001844 result = L2CAP_CONF_UNACCEPT;
1845
1846 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001847 rfc.mode = chan->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001848 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001849
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001850 if (result == L2CAP_CONF_SUCCESS)
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001851 chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001852 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001853 rsp->scid = cpu_to_le16(pi->dcid);
1854 rsp->result = cpu_to_le16(result);
1855 rsp->flags = cpu_to_le16(0x0000);
1856
1857 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858}
1859
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001860static 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 -03001861{
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001862 struct sock *sk = chan->sk;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001863 struct l2cap_pinfo *pi = l2cap_pi(sk);
1864 struct l2cap_conf_req *req = data;
1865 void *ptr = req->data;
1866 int type, olen;
1867 unsigned long val;
1868 struct l2cap_conf_rfc rfc;
1869
1870 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1871
1872 while (len >= L2CAP_CONF_OPT_SIZE) {
1873 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1874
1875 switch (type) {
1876 case L2CAP_CONF_MTU:
1877 if (val < L2CAP_DEFAULT_MIN_MTU) {
1878 *result = L2CAP_CONF_UNACCEPT;
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001879 chan->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001880 } else
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001881 chan->imtu = val;
1882 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001883 break;
1884
1885 case L2CAP_CONF_FLUSH_TO:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001886 chan->flush_to = val;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001887 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001888 2, chan->flush_to);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001889 break;
1890
1891 case L2CAP_CONF_RFC:
1892 if (olen == sizeof(rfc))
1893 memcpy(&rfc, (void *)val, olen);
1894
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001895 if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001896 rfc.mode != chan->mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001897 return -ECONNREFUSED;
1898
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001899 chan->fcs = 0;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001900
1901 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1902 sizeof(rfc), (unsigned long) &rfc);
1903 break;
1904 }
1905 }
1906
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001907 if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001908 return -ECONNREFUSED;
1909
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001910 chan->mode = rfc.mode;
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001911
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001912 if (*result == L2CAP_CONF_SUCCESS) {
1913 switch (rfc.mode) {
1914 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001915 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1916 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
1917 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001918 break;
1919 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001920 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001921 }
1922 }
1923
1924 req->dcid = cpu_to_le16(pi->dcid);
1925 req->flags = cpu_to_le16(0x0000);
1926
1927 return ptr - data;
1928}
1929
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001930static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931{
1932 struct l2cap_conf_rsp *rsp = data;
1933 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001935 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001937 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001938 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001939 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940
1941 return ptr - data;
1942}
1943
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001944void __l2cap_connect_rsp_defer(struct sock *sk)
1945{
1946 struct l2cap_conn_rsp rsp;
1947 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1948 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
1949 u8 buf[128];
1950
1951 sk->sk_state = BT_CONFIG;
1952
1953 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1954 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1955 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1956 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1957 l2cap_send_cmd(conn, chan->ident,
1958 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1959
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001960 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001961 return;
1962
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03001963 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovan710f9b02011-03-25 14:30:37 -03001964 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1965 l2cap_build_conf_req(chan, buf), buf);
1966 chan->num_conf_req++;
1967}
1968
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001969static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001970{
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001971 int type, olen;
1972 unsigned long val;
1973 struct l2cap_conf_rfc rfc;
1974
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001975 BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001976
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001977 if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001978 return;
1979
1980 while (len >= L2CAP_CONF_OPT_SIZE) {
1981 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1982
1983 switch (type) {
1984 case L2CAP_CONF_RFC:
1985 if (olen == sizeof(rfc))
1986 memcpy(&rfc, (void *)val, olen);
1987 goto done;
1988 }
1989 }
1990
1991done:
1992 switch (rfc.mode) {
1993 case L2CAP_MODE_ERTM:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001994 chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1995 chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
1996 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001997 break;
1998 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03001999 chan->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002000 }
2001}
2002
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002003static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2004{
2005 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
2006
2007 if (rej->reason != 0x0000)
2008 return 0;
2009
2010 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2011 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002012 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002013
2014 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002015 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002016
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002017 l2cap_conn_start(conn);
2018 }
2019
2020 return 0;
2021}
2022
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2024{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2026 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002027 struct l2cap_chan *chan = NULL;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002028 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002029 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030
2031 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002032 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033
2034 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2035
2036 /* Check if we have socket listening on psm */
2037 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2038 if (!parent) {
2039 result = L2CAP_CR_BAD_PSM;
2040 goto sendresp;
2041 }
2042
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002043 bh_lock_sock(parent);
2044
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002045 /* Check if the ACL is secure enough (if not SDP) */
2046 if (psm != cpu_to_le16(0x0001) &&
2047 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002048 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002049 result = L2CAP_CR_SEC_BLOCK;
2050 goto response;
2051 }
2052
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 result = L2CAP_CR_NO_MEM;
2054
2055 /* Check for backlog size */
2056 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002057 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058 goto response;
2059 }
2060
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002061 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 if (!sk)
2063 goto response;
2064
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002065 chan = l2cap_chan_alloc(sk);
2066 if (!chan) {
2067 l2cap_sock_kill(sk);
2068 goto response;
2069 }
2070
Gustavo F. Padovan5d41ce12011-04-08 15:40:02 -03002071 l2cap_pi(sk)->chan = chan;
2072
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002073 write_lock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074
2075 /* Check if we already have channel with that dcid */
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002076 if (__l2cap_get_chan_by_dcid(conn, scid)) {
2077 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 sock_set_flag(sk, SOCK_ZAPPED);
2079 l2cap_sock_kill(sk);
2080 goto response;
2081 }
2082
2083 hci_conn_hold(conn->hcon);
2084
2085 l2cap_sock_init(sk, parent);
2086 bacpy(&bt_sk(sk)->src, conn->src);
2087 bacpy(&bt_sk(sk)->dst, conn->dst);
2088 l2cap_pi(sk)->psm = psm;
2089 l2cap_pi(sk)->dcid = scid;
2090
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002091 bt_accept_enqueue(parent, sk);
2092
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002093 __l2cap_chan_add(conn, chan);
2094
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 dcid = l2cap_pi(sk)->scid;
2096
2097 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2098
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002099 chan->ident = cmd->ident;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100
Marcel Holtmann984947d2009-02-06 23:35:19 +01002101 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03002102 if (l2cap_check_security(chan)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002103 if (bt_sk(sk)->defer_setup) {
2104 sk->sk_state = BT_CONNECT2;
2105 result = L2CAP_CR_PEND;
2106 status = L2CAP_CS_AUTHOR_PEND;
2107 parent->sk_data_ready(parent, 0);
2108 } else {
2109 sk->sk_state = BT_CONFIG;
2110 result = L2CAP_CR_SUCCESS;
2111 status = L2CAP_CS_NO_INFO;
2112 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002113 } else {
2114 sk->sk_state = BT_CONNECT2;
2115 result = L2CAP_CR_PEND;
2116 status = L2CAP_CS_AUTHEN_PEND;
2117 }
2118 } else {
2119 sk->sk_state = BT_CONNECT2;
2120 result = L2CAP_CR_PEND;
2121 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 }
2123
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002124 write_unlock_bh(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125
2126response:
2127 bh_unlock_sock(parent);
2128
2129sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002130 rsp.scid = cpu_to_le16(scid);
2131 rsp.dcid = cpu_to_le16(dcid);
2132 rsp.result = cpu_to_le16(result);
2133 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002135
2136 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2137 struct l2cap_info_req info;
2138 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2139
2140 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2141 conn->info_ident = l2cap_get_ident(conn);
2142
2143 mod_timer(&conn->info_timer, jiffies +
2144 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2145
2146 l2cap_send_cmd(conn, conn->info_ident,
2147 L2CAP_INFO_REQ, sizeof(info), &info);
2148 }
2149
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002150 if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002151 result == L2CAP_CR_SUCCESS) {
2152 u8 buf[128];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002153 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002154 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002155 l2cap_build_conf_req(chan, buf), buf);
2156 chan->num_conf_req++;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002157 }
2158
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 return 0;
2160}
2161
2162static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2163{
2164 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2165 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002166 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 struct sock *sk;
2168 u8 req[128];
2169
2170 scid = __le16_to_cpu(rsp->scid);
2171 dcid = __le16_to_cpu(rsp->dcid);
2172 result = __le16_to_cpu(rsp->result);
2173 status = __le16_to_cpu(rsp->status);
2174
2175 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2176
2177 if (scid) {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002178 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002179 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002180 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 } else {
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002182 chan = l2cap_get_chan_by_ident(conn, cmd->ident);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002183 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002184 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 }
2186
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002187 sk = chan->sk;
2188
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 switch (result) {
2190 case L2CAP_CR_SUCCESS:
2191 sk->sk_state = BT_CONFIG;
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03002192 chan->ident = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 l2cap_pi(sk)->dcid = dcid;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002194 chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002195
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002196 if (chan->conf_state & L2CAP_CONF_REQ_SENT)
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002197 break;
2198
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002199 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002200
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002202 l2cap_build_conf_req(chan, req), req);
2203 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 break;
2205
2206 case L2CAP_CR_PEND:
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002207 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 break;
2209
2210 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002211 /* don't delete l2cap channel if sk is owned by user */
2212 if (sock_owned_by_user(sk)) {
2213 sk->sk_state = BT_DISCONN;
2214 l2cap_sock_clear_timer(sk);
2215 l2cap_sock_set_timer(sk, HZ / 5);
2216 break;
2217 }
2218
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002219 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 break;
2221 }
2222
2223 bh_unlock_sock(sk);
2224 return 0;
2225}
2226
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002227static inline void set_default_fcs(struct l2cap_chan *chan)
Mat Martineau8c462b62010-08-24 15:35:42 -07002228{
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002229 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
2230
Mat Martineau8c462b62010-08-24 15:35:42 -07002231 /* FCS is enabled only in ERTM or streaming mode, if one or both
2232 * sides request it.
2233 */
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002234 if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002235 chan->fcs = L2CAP_FCS_NONE;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002236 else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002237 chan->fcs = L2CAP_FCS_CRC16;
Mat Martineau8c462b62010-08-24 15:35:42 -07002238}
2239
Al Viro88219a02007-07-29 00:17:25 -07002240static 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 -07002241{
2242 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2243 u16 dcid, flags;
2244 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002245 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002247 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248
2249 dcid = __le16_to_cpu(req->dcid);
2250 flags = __le16_to_cpu(req->flags);
2251
2252 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2253
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002254 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002255 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 return -ENOENT;
2257
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002258 sk = chan->sk;
2259
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002260 if (sk->sk_state != BT_CONFIG) {
2261 struct l2cap_cmd_rej rej;
2262
2263 rej.reason = cpu_to_le16(0x0002);
2264 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2265 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002266 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002267 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002268
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002269 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002270 len = cmd_len - sizeof(*req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002271 if (chan->conf_len + len > sizeof(chan->conf_req)) {
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002272 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2273 l2cap_build_conf_rsp(sk, rsp,
2274 L2CAP_CONF_REJECT, flags), rsp);
2275 goto unlock;
2276 }
2277
2278 /* Store config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002279 memcpy(chan->conf_req + chan->conf_len, req->data, len);
2280 chan->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281
2282 if (flags & 0x0001) {
2283 /* Incomplete config. Send empty response. */
2284 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002285 l2cap_build_conf_rsp(sk, rsp,
2286 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 goto unlock;
2288 }
2289
2290 /* Complete config. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002291 len = l2cap_parse_conf_req(chan, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002292 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002293 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002295 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002297 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002298 chan->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002299
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002300 /* Reset config buffer. */
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002301 chan->conf_len = 0;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002302
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002303 if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE))
Marcel Holtmann876d9482007-10-20 13:35:42 +02002304 goto unlock;
2305
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002306 if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002307 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002308
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002310
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002311 chan->next_tx_seq = 0;
2312 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002313 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002314 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002315 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002316
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002318 goto unlock;
2319 }
2320
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002321 if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002322 u8 buf[64];
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002323 chan->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002325 l2cap_build_conf_req(chan, buf), buf);
2326 chan->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 }
2328
2329unlock:
2330 bh_unlock_sock(sk);
2331 return 0;
2332}
2333
2334static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2335{
2336 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2337 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002338 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002340 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341
2342 scid = __le16_to_cpu(rsp->scid);
2343 flags = __le16_to_cpu(rsp->flags);
2344 result = __le16_to_cpu(rsp->result);
2345
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002346 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2347 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002349 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002350 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 return 0;
2352
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002353 sk = chan->sk;
2354
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355 switch (result) {
2356 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002357 l2cap_conf_rfc_get(chan, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 break;
2359
2360 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002361 if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002362 char req[64];
2363
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002364 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002365 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002366 goto done;
2367 }
2368
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002369 /* throw out any old stored conf requests */
2370 result = L2CAP_CONF_SUCCESS;
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002371 len = l2cap_parse_conf_rsp(chan, rsp->data, len,
2372 req, &result);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002373 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002374 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002375 goto done;
2376 }
2377
2378 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2379 L2CAP_CONF_REQ, len, req);
Gustavo F. Padovan73ffa902011-03-25 14:16:54 -03002380 chan->num_conf_req++;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002381 if (result != L2CAP_CONF_SUCCESS)
2382 goto done;
2383 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384 }
2385
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002386 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002387 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002389 l2cap_send_disconn_req(conn, chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 goto done;
2391 }
2392
2393 if (flags & 0x01)
2394 goto done;
2395
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002396 chan->conf_state |= L2CAP_CONF_INPUT_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03002398 if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002399 set_default_fcs(chan);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002400
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002402 chan->next_tx_seq = 0;
2403 chan->expected_tx_seq = 0;
Gustavo F. Padovan58d35f82011-04-04 16:16:44 -03002404 skb_queue_head_init(&chan->tx_q);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002405 if (chan->mode == L2CAP_MODE_ERTM)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002406 l2cap_ertm_init(chan);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002407
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408 l2cap_chan_ready(sk);
2409 }
2410
2411done:
2412 bh_unlock_sock(sk);
2413 return 0;
2414}
2415
2416static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2417{
2418 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2419 struct l2cap_disconn_rsp rsp;
2420 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002421 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422 struct sock *sk;
2423
2424 scid = __le16_to_cpu(req->scid);
2425 dcid = __le16_to_cpu(req->dcid);
2426
2427 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2428
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002429 chan = l2cap_get_chan_by_scid(conn, dcid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002430 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431 return 0;
2432
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002433 sk = chan->sk;
2434
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002435 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2436 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2438
2439 sk->sk_shutdown = SHUTDOWN_MASK;
2440
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002441 /* don't delete l2cap channel if sk is owned by user */
2442 if (sock_owned_by_user(sk)) {
2443 sk->sk_state = BT_DISCONN;
2444 l2cap_sock_clear_timer(sk);
2445 l2cap_sock_set_timer(sk, HZ / 5);
2446 bh_unlock_sock(sk);
2447 return 0;
2448 }
2449
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002450 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 bh_unlock_sock(sk);
2452
2453 l2cap_sock_kill(sk);
2454 return 0;
2455}
2456
2457static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2458{
2459 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2460 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002461 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462 struct sock *sk;
2463
2464 scid = __le16_to_cpu(rsp->scid);
2465 dcid = __le16_to_cpu(rsp->dcid);
2466
2467 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2468
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03002469 chan = l2cap_get_chan_by_scid(conn, scid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002470 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471 return 0;
2472
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002473 sk = chan->sk;
2474
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002475 /* don't delete l2cap channel if sk is owned by user */
2476 if (sock_owned_by_user(sk)) {
2477 sk->sk_state = BT_DISCONN;
2478 l2cap_sock_clear_timer(sk);
2479 l2cap_sock_set_timer(sk, HZ / 5);
2480 bh_unlock_sock(sk);
2481 return 0;
2482 }
2483
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002484 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485 bh_unlock_sock(sk);
2486
2487 l2cap_sock_kill(sk);
2488 return 0;
2489}
2490
2491static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2492{
2493 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494 u16 type;
2495
2496 type = __le16_to_cpu(req->type);
2497
2498 BT_DBG("type 0x%4.4x", type);
2499
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002500 if (type == L2CAP_IT_FEAT_MASK) {
2501 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002502 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002503 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2504 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2505 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002506 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002507 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2508 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002509 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002510 l2cap_send_cmd(conn, cmd->ident,
2511 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002512 } else if (type == L2CAP_IT_FIXED_CHAN) {
2513 u8 buf[12];
2514 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2515 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2516 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2517 memcpy(buf + 4, l2cap_fixed_chan, 8);
2518 l2cap_send_cmd(conn, cmd->ident,
2519 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002520 } else {
2521 struct l2cap_info_rsp rsp;
2522 rsp.type = cpu_to_le16(type);
2523 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2524 l2cap_send_cmd(conn, cmd->ident,
2525 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2526 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527
2528 return 0;
2529}
2530
2531static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2532{
2533 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2534 u16 type, result;
2535
2536 type = __le16_to_cpu(rsp->type);
2537 result = __le16_to_cpu(rsp->result);
2538
2539 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2540
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002541 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2542 if (cmd->ident != conn->info_ident ||
2543 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2544 return 0;
2545
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002546 del_timer(&conn->info_timer);
2547
Ville Tervoadb08ed2010-08-04 09:43:33 +03002548 if (result != L2CAP_IR_SUCCESS) {
2549 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2550 conn->info_ident = 0;
2551
2552 l2cap_conn_start(conn);
2553
2554 return 0;
2555 }
2556
Marcel Holtmann984947d2009-02-06 23:35:19 +01002557 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002558 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002559
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002560 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002561 struct l2cap_info_req req;
2562 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2563
2564 conn->info_ident = l2cap_get_ident(conn);
2565
2566 l2cap_send_cmd(conn, conn->info_ident,
2567 L2CAP_INFO_REQ, sizeof(req), &req);
2568 } else {
2569 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2570 conn->info_ident = 0;
2571
2572 l2cap_conn_start(conn);
2573 }
2574 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002575 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002576 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002577
2578 l2cap_conn_start(conn);
2579 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002580
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581 return 0;
2582}
2583
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002584static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002585 u16 to_multiplier)
2586{
2587 u16 max_latency;
2588
2589 if (min > max || min < 6 || max > 3200)
2590 return -EINVAL;
2591
2592 if (to_multiplier < 10 || to_multiplier > 3200)
2593 return -EINVAL;
2594
2595 if (max >= to_multiplier * 8)
2596 return -EINVAL;
2597
2598 max_latency = (to_multiplier * 8 / max) - 1;
2599 if (latency > 499 || latency > max_latency)
2600 return -EINVAL;
2601
2602 return 0;
2603}
2604
2605static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2606 struct l2cap_cmd_hdr *cmd, u8 *data)
2607{
2608 struct hci_conn *hcon = conn->hcon;
2609 struct l2cap_conn_param_update_req *req;
2610 struct l2cap_conn_param_update_rsp rsp;
2611 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002612 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002613
2614 if (!(hcon->link_mode & HCI_LM_MASTER))
2615 return -EINVAL;
2616
2617 cmd_len = __le16_to_cpu(cmd->len);
2618 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2619 return -EPROTO;
2620
2621 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002622 min = __le16_to_cpu(req->min);
2623 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002624 latency = __le16_to_cpu(req->latency);
2625 to_multiplier = __le16_to_cpu(req->to_multiplier);
2626
2627 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2628 min, max, latency, to_multiplier);
2629
2630 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002631
2632 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2633 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002634 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2635 else
2636 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2637
2638 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2639 sizeof(rsp), &rsp);
2640
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002641 if (!err)
2642 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2643
Claudio Takahaside731152011-02-11 19:28:55 -02002644 return 0;
2645}
2646
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002647static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2648 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2649{
2650 int err = 0;
2651
2652 switch (cmd->code) {
2653 case L2CAP_COMMAND_REJ:
2654 l2cap_command_rej(conn, cmd, data);
2655 break;
2656
2657 case L2CAP_CONN_REQ:
2658 err = l2cap_connect_req(conn, cmd, data);
2659 break;
2660
2661 case L2CAP_CONN_RSP:
2662 err = l2cap_connect_rsp(conn, cmd, data);
2663 break;
2664
2665 case L2CAP_CONF_REQ:
2666 err = l2cap_config_req(conn, cmd, cmd_len, data);
2667 break;
2668
2669 case L2CAP_CONF_RSP:
2670 err = l2cap_config_rsp(conn, cmd, data);
2671 break;
2672
2673 case L2CAP_DISCONN_REQ:
2674 err = l2cap_disconnect_req(conn, cmd, data);
2675 break;
2676
2677 case L2CAP_DISCONN_RSP:
2678 err = l2cap_disconnect_rsp(conn, cmd, data);
2679 break;
2680
2681 case L2CAP_ECHO_REQ:
2682 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2683 break;
2684
2685 case L2CAP_ECHO_RSP:
2686 break;
2687
2688 case L2CAP_INFO_REQ:
2689 err = l2cap_information_req(conn, cmd, data);
2690 break;
2691
2692 case L2CAP_INFO_RSP:
2693 err = l2cap_information_rsp(conn, cmd, data);
2694 break;
2695
2696 default:
2697 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2698 err = -EINVAL;
2699 break;
2700 }
2701
2702 return err;
2703}
2704
2705static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2706 struct l2cap_cmd_hdr *cmd, u8 *data)
2707{
2708 switch (cmd->code) {
2709 case L2CAP_COMMAND_REJ:
2710 return 0;
2711
2712 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002713 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002714
2715 case L2CAP_CONN_PARAM_UPDATE_RSP:
2716 return 0;
2717
2718 default:
2719 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2720 return -EINVAL;
2721 }
2722}
2723
2724static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2725 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726{
2727 u8 *data = skb->data;
2728 int len = skb->len;
2729 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002730 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731
2732 l2cap_raw_recv(conn, skb);
2733
2734 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002735 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2737 data += L2CAP_CMD_HDR_SIZE;
2738 len -= L2CAP_CMD_HDR_SIZE;
2739
Al Viro88219a02007-07-29 00:17:25 -07002740 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741
Al Viro88219a02007-07-29 00:17:25 -07002742 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 -07002743
Al Viro88219a02007-07-29 00:17:25 -07002744 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 BT_DBG("corrupted command");
2746 break;
2747 }
2748
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002749 if (conn->hcon->type == LE_LINK)
2750 err = l2cap_le_sig_cmd(conn, &cmd, data);
2751 else
2752 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753
2754 if (err) {
2755 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002756
2757 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758
2759 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002760 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2762 }
2763
Al Viro88219a02007-07-29 00:17:25 -07002764 data += cmd_len;
2765 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 }
2767
2768 kfree_skb(skb);
2769}
2770
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002771static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002772{
2773 u16 our_fcs, rcv_fcs;
2774 int hdr_size = L2CAP_HDR_SIZE + 2;
2775
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03002776 if (chan->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002777 skb_trim(skb, skb->len - 2);
2778 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2779 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2780
2781 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002782 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002783 }
2784 return 0;
2785}
2786
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002787static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002788{
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002789 u16 control = 0;
2790
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002791 chan->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002792
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002793 control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002794
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002795 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002796 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002797 l2cap_send_sframe(chan, control);
2798 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002799 }
2800
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002801 if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
2802 l2cap_retransmit_frames(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002803
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002804 l2cap_ertm_send(chan);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002805
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002806 if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002807 chan->frames_sent == 0) {
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002808 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002809 l2cap_send_sframe(chan, control);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002810 }
2811}
2812
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002813static 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 -03002814{
2815 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002816 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002817
2818 bt_cb(skb)->tx_seq = tx_seq;
2819 bt_cb(skb)->sar = sar;
2820
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002821 next_skb = skb_peek(&chan->srej_q);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002822 if (!next_skb) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002823 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002824 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002825 }
2826
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002827 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002828 if (tx_seq_offset < 0)
2829 tx_seq_offset += 64;
2830
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002831 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002832 if (bt_cb(next_skb)->tx_seq == tx_seq)
2833 return -EINVAL;
2834
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002835 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002836 chan->buffer_seq) % 64;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002837 if (next_tx_seq_offset < 0)
2838 next_tx_seq_offset += 64;
2839
2840 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002841 __skb_queue_before(&chan->srej_q, next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002842 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002843 }
2844
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002845 if (skb_queue_is_last(&chan->srej_q, next_skb))
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002846 break;
2847
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002848 } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002849
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002850 __skb_queue_tail(&chan->srej_q, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002851
2852 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002853}
2854
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002855static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002856{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002857 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002858 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002859 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002860
2861 switch (control & L2CAP_CTRL_SAR) {
2862 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002863 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002864 goto drop;
2865
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002866 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002867 if (!err)
2868 return err;
2869
2870 break;
2871
2872 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002873 if (chan->conn_state & L2CAP_CONN_SAR_SDU)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002874 goto drop;
2875
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002876 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002877
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002878 if (chan->sdu_len > chan->imtu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002879 goto disconnect;
2880
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002881 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
2882 if (!chan->sdu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002883 return -ENOMEM;
2884
2885 /* pull sdu_len bytes only after alloc, because of Local Busy
2886 * condition we have to be sure that this will be executed
2887 * only once, i.e., when alloc does not fail */
2888 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002889
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002890 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002891
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002892 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002893 chan->partial_sdu_len = skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002894 break;
2895
2896 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002897 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002898 goto disconnect;
2899
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002900 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002901 goto disconnect;
2902
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002903 chan->partial_sdu_len += skb->len;
2904 if (chan->partial_sdu_len > chan->sdu_len)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002905 goto drop;
2906
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002907 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002908
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002909 break;
2910
2911 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002912 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002913 goto disconnect;
2914
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002915 if (!chan->sdu)
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002916 goto disconnect;
2917
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002918 if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002919 chan->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002920
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03002921 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002922 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002923
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002924 if (chan->partial_sdu_len != chan->sdu_len)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002925 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002926
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002927 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002928 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002929
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002930 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002931 if (!_skb) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002932 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002933 return -ENOMEM;
2934 }
2935
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002936 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002937 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002938 kfree_skb(_skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002939 chan->conn_state |= L2CAP_CONN_SAR_RETRY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002940 return err;
2941 }
2942
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002943 chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2944 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002945
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002946 kfree_skb(chan->sdu);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002947 break;
2948 }
2949
2950 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002951 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002952
2953drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03002954 kfree_skb(chan->sdu);
2955 chan->sdu = NULL;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002956
2957disconnect:
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002958 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002959 kfree_skb(skb);
2960 return 0;
2961}
2962
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002963static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002964{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002965 struct sk_buff *skb;
2966 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002967 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002968
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002969 while ((skb = skb_dequeue(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002970 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002971 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002972 if (err < 0) {
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03002973 skb_queue_head(&chan->busy_q, skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002974 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002975 }
2976
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002977 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002978 }
2979
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002980 if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002981 goto done;
2982
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03002983 control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002984 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002985 l2cap_send_sframe(chan, control);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03002986 chan->retry_count = 1;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002987
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03002988 del_timer(&chan->retrans_timer);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002989 __mod_monitor_timer();
2990
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002991 chan->conn_state |= L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002992
2993done:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03002994 chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2995 chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002996
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03002997 BT_DBG("chan %p, Exit local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002998
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002999 return 0;
3000}
3001
3002static void l2cap_busy_work(struct work_struct *work)
3003{
3004 DECLARE_WAITQUEUE(wait, current);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003005 struct l2cap_chan *chan =
3006 container_of(work, struct l2cap_chan, busy_work);
3007 struct sock *sk = chan->sk;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003008 int n_tries = 0, timeo = HZ/5, err;
3009 struct sk_buff *skb;
3010
3011 lock_sock(sk);
3012
3013 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003014 while ((skb = skb_peek(&chan->busy_q))) {
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003015 set_current_state(TASK_INTERRUPTIBLE);
3016
3017 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3018 err = -EBUSY;
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003019 l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, EBUSY);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003020 break;
3021 }
3022
3023 if (!timeo)
3024 timeo = HZ/5;
3025
3026 if (signal_pending(current)) {
3027 err = sock_intr_errno(timeo);
3028 break;
3029 }
3030
3031 release_sock(sk);
3032 timeo = schedule_timeout(timeo);
3033 lock_sock(sk);
3034
3035 err = sock_error(sk);
3036 if (err)
3037 break;
3038
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003039 if (l2cap_try_push_rx_skb(chan) == 0)
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003040 break;
3041 }
3042
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003043 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003044 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003045
3046 release_sock(sk);
3047}
3048
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003049static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003050{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003051 int sctrl, err;
3052
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003053 if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003054 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003055 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003056 return l2cap_try_push_rx_skb(chan);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003057
3058
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003059 }
3060
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003061 err = l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003062 if (err >= 0) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003063 chan->buffer_seq = (chan->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003064 return err;
3065 }
3066
3067 /* Busy Condition */
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003068 BT_DBG("chan %p, Enter local busy", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003069
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003070 chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003071 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003072 __skb_queue_tail(&chan->busy_q, skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003073
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003074 sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003075 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003076 l2cap_send_sframe(chan, sctrl);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003077
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003078 chan->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003079
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003080 del_timer(&chan->ack_timer);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003081
Gustavo F. Padovan311bb892011-03-25 20:41:00 -03003082 queue_work(_busy_wq, &chan->busy_work);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003083
3084 return err;
3085}
3086
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003087static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003088{
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003089 struct sk_buff *_skb;
3090 int err = -EINVAL;
3091
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003092 /*
3093 * TODO: We have to notify the userland if some data is lost with the
3094 * Streaming Mode.
3095 */
3096
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003097 switch (control & L2CAP_CTRL_SAR) {
3098 case L2CAP_SDU_UNSEGMENTED:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003099 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003100 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003101 break;
3102 }
3103
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003104 err = sock_queue_rcv_skb(chan->sk, skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003105 if (!err)
3106 return 0;
3107
3108 break;
3109
3110 case L2CAP_SDU_START:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003111 if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003112 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003113 break;
3114 }
3115
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003116 chan->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003117 skb_pull(skb, 2);
3118
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003119 if (chan->sdu_len > chan->imtu) {
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003120 err = -EMSGSIZE;
3121 break;
3122 }
3123
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003124 chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
3125 if (!chan->sdu) {
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003126 err = -ENOMEM;
3127 break;
3128 }
3129
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003130 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003131
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003132 chan->conn_state |= L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003133 chan->partial_sdu_len = skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003134 err = 0;
3135 break;
3136
3137 case L2CAP_SDU_CONTINUE:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003138 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003139 break;
3140
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003141 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003142
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003143 chan->partial_sdu_len += skb->len;
3144 if (chan->partial_sdu_len > chan->sdu_len)
3145 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003146 else
3147 err = 0;
3148
3149 break;
3150
3151 case L2CAP_SDU_END:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003152 if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003153 break;
3154
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003155 memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003156
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003157 chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003158 chan->partial_sdu_len += skb->len;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003159
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003160 if (chan->partial_sdu_len > chan->imtu)
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003161 goto drop;
3162
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003163 if (chan->partial_sdu_len == chan->sdu_len) {
3164 _skb = skb_clone(chan->sdu, GFP_ATOMIC);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003165 err = sock_queue_rcv_skb(chan->sk, _skb);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003166 if (err < 0)
3167 kfree_skb(_skb);
3168 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003169 err = 0;
3170
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003171drop:
Gustavo F. Padovan6f61fd472011-03-25 20:09:37 -03003172 kfree_skb(chan->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003173 break;
3174 }
3175
3176 kfree_skb(skb);
3177 return err;
3178}
3179
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003180static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003181{
3182 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003183 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003184
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003185 while ((skb = skb_peek(&chan->srej_q))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003186 if (bt_cb(skb)->tx_seq != tx_seq)
3187 break;
3188
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003189 skb = skb_dequeue(&chan->srej_q);
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003190 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003191 l2cap_ertm_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003192 chan->buffer_seq_srej =
3193 (chan->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003194 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003195 }
3196}
3197
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003198static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003199{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003200 struct srej_list *l, *tmp;
3201 u16 control;
3202
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003203 list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003204 if (l->tx_seq == tx_seq) {
3205 list_del(&l->list);
3206 kfree(l);
3207 return;
3208 }
3209 control = L2CAP_SUPER_SELECT_REJECT;
3210 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003211 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003212 list_del(&l->list);
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003213 list_add_tail(&l->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003214 }
3215}
3216
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003217static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003218{
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003219 struct srej_list *new;
3220 u16 control;
3221
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003222 while (tx_seq != chan->expected_tx_seq) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003223 control = L2CAP_SUPER_SELECT_REJECT;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003224 control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003225 l2cap_send_sframe(chan, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003226
3227 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003228 new->tx_seq = chan->expected_tx_seq;
3229 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003230 list_add_tail(&new->list, &chan->srej_l);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003231 }
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003232 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003233}
3234
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003235static 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 -03003236{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003237 struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003238 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003239 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003240 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003241 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003242 int num_to_ack = (chan->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003243 int err = 0;
3244
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003245 BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
3246 tx_seq, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003247
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003248 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003249 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003250 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003251 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003252 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003253 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003254 }
3255
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003256 chan->expected_ack_seq = req_seq;
3257 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003258
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003259 if (tx_seq == chan->expected_tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003260 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003261
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003262 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003263 if (tx_seq_offset < 0)
3264 tx_seq_offset += 64;
3265
3266 /* invalid tx_seq */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003267 if (tx_seq_offset >= chan->tx_win) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003268 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003269 goto drop;
3270 }
3271
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003272 if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003273 goto drop;
3274
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003275 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003276 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003277
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003278 first = list_first_entry(&chan->srej_l,
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003279 struct srej_list, list);
3280 if (tx_seq == first->tx_seq) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003281 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003282 l2cap_check_srej_gap(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003283
3284 list_del(&first->list);
3285 kfree(first);
3286
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003287 if (list_empty(&chan->srej_l)) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003288 chan->buffer_seq = chan->buffer_seq_srej;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003289 chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
3290 l2cap_send_ack(chan);
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003291 BT_DBG("chan %p, Exit SREJ_SENT", chan);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003292 }
3293 } else {
3294 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003295
3296 /* duplicated tx_seq */
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003297 if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003298 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003299
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003300 list_for_each_entry(l, &chan->srej_l, list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003301 if (l->tx_seq == tx_seq) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003302 l2cap_resend_srejframe(chan, tx_seq);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003303 return 0;
3304 }
3305 }
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003306 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003307 }
3308 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003309 expected_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003310 (chan->expected_tx_seq - chan->buffer_seq) % 64;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003311 if (expected_tx_seq_offset < 0)
3312 expected_tx_seq_offset += 64;
3313
3314 /* duplicated tx_seq */
3315 if (tx_seq_offset < expected_tx_seq_offset)
3316 goto drop;
3317
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003318 chan->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003319
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003320 BT_DBG("chan %p, Enter SREJ", chan);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003321
Gustavo F. Padovan39d5a3e2011-04-04 15:40:12 -03003322 INIT_LIST_HEAD(&chan->srej_l);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003323 chan->buffer_seq_srej = chan->buffer_seq;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003324
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003325 __skb_queue_head_init(&chan->srej_q);
3326 __skb_queue_head_init(&chan->busy_q);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003327 l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003328
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003329 chan->conn_state |= L2CAP_CONN_SEND_PBIT;
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003330
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003331 l2cap_send_srejframe(chan, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003332
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003333 del_timer(&chan->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003334 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003335 return 0;
3336
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003337expected:
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003338 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003339
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003340 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003341 bt_cb(skb)->tx_seq = tx_seq;
3342 bt_cb(skb)->sar = sar;
Gustavo F. Padovanf1c67752011-03-25 20:36:10 -03003343 __skb_queue_tail(&chan->srej_q, skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003344 return 0;
3345 }
3346
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003347 err = l2cap_push_rx_skb(chan, skb, rx_control);
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003348 if (err < 0)
3349 return 0;
3350
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003351 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003352 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3353 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003354 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003355 l2cap_retransmit_frames(chan);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003356 }
3357
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003358 __mod_ack_timer();
3359
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003360 chan->num_acked = (chan->num_acked + 1) % num_to_ack;
3361 if (chan->num_acked == num_to_ack - 1)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003362 l2cap_send_ack(chan);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003363
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003364 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003365
3366drop:
3367 kfree_skb(skb);
3368 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003369}
3370
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003371static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003372{
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003373 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003374 rx_control);
3375
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003376 chan->expected_ack_seq = __get_reqseq(rx_control);
3377 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003378
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003379 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003380 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3381 if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
3382 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003383 (chan->unacked_frames > 0))
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003384 __mod_retrans_timer();
3385
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003386 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3387 l2cap_send_srejtail(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003388 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003389 l2cap_send_i_or_rr_or_rnr(chan);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003390 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003391
3392 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003393 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003394
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003395 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3396 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003397 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003398 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003399
3400 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003401 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003402 (chan->unacked_frames > 0))
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003403 __mod_retrans_timer();
3404
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003405 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3406 if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
3407 l2cap_send_ack(chan);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003408 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003409 l2cap_ertm_send(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003410 }
3411}
3412
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003413static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003414{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003415 u8 tx_seq = __get_reqseq(rx_control);
3416
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003417 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003418
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003419 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003420
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003421 chan->expected_ack_seq = tx_seq;
3422 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003423
3424 if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003425 if (chan->conn_state & L2CAP_CONN_REJ_ACT)
3426 chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003427 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003428 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003429 } else {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003430 l2cap_retransmit_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003431
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003432 if (chan->conn_state & L2CAP_CONN_WAIT_F)
3433 chan->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003434 }
3435}
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003436static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003437{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003438 u8 tx_seq = __get_reqseq(rx_control);
3439
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003440 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003441
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003442 chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003443
3444 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003445 chan->expected_ack_seq = tx_seq;
3446 l2cap_drop_acked_frames(chan);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003447
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003448 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
3449 l2cap_retransmit_one_frame(chan, tx_seq);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003450
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003451 l2cap_ertm_send(chan);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003452
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003453 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003454 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003455 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003456 }
3457 } else if (rx_control & L2CAP_CTRL_FINAL) {
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003458 if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003459 chan->srej_save_reqseq == tx_seq)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003460 chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003461 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003462 l2cap_retransmit_one_frame(chan, tx_seq);
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);
3465 if (chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003466 chan->srej_save_reqseq = tx_seq;
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003467 chan->conn_state |= L2CAP_CONN_SREJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003468 }
3469 }
3470}
3471
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003472static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003473{
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003474 u8 tx_seq = __get_reqseq(rx_control);
3475
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003476 BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003477
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003478 chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003479 chan->expected_ack_seq = tx_seq;
3480 l2cap_drop_acked_frames(chan);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003481
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003482 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003483 chan->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003484
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003485 if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003486 del_timer(&chan->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003487 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003488 l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003489 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003490 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003491
3492 if (rx_control & L2CAP_CTRL_POLL)
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003493 l2cap_send_srejtail(chan);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003494 else
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003495 l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003496}
3497
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003498static 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 -03003499{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003500 BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003501
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003502 if (L2CAP_CTRL_FINAL & rx_control &&
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003503 chan->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003504 del_timer(&chan->monitor_timer);
Gustavo F. Padovan6a026612011-04-01 00:38:50 -03003505 if (chan->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003506 __mod_retrans_timer();
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003507 chan->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003508 }
3509
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003510 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3511 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003512 l2cap_data_channel_rrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003513 break;
3514
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003515 case L2CAP_SUPER_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003516 l2cap_data_channel_rejframe(chan, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003517 break;
3518
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003519 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003520 l2cap_data_channel_srejframe(chan, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003521 break;
3522
3523 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003524 l2cap_data_channel_rnrframe(chan, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003525 break;
3526 }
3527
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003528 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003529 return 0;
3530}
3531
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003532static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3533{
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003534 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003535 struct l2cap_pinfo *pi = l2cap_pi(sk);
3536 u16 control;
3537 u8 req_seq;
3538 int len, next_tx_seq_offset, req_seq_offset;
3539
3540 control = get_unaligned_le16(skb->data);
3541 skb_pull(skb, 2);
3542 len = skb->len;
3543
3544 /*
3545 * We can just drop the corrupted I-frame here.
3546 * Receiver will miss it and start proper recovery
3547 * procedures and ask retransmission.
3548 */
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003549 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003550 goto drop;
3551
3552 if (__is_sar_start(control) && __is_iframe(control))
3553 len -= 2;
3554
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003555 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003556 len -= 2;
3557
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003558 if (len > chan->mps) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003559 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003560 goto drop;
3561 }
3562
3563 req_seq = __get_reqseq(control);
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003564 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003565 if (req_seq_offset < 0)
3566 req_seq_offset += 64;
3567
3568 next_tx_seq_offset =
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003569 (chan->next_tx_seq - chan->expected_ack_seq) % 64;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003570 if (next_tx_seq_offset < 0)
3571 next_tx_seq_offset += 64;
3572
3573 /* check for invalid req-seq */
3574 if (req_seq_offset > next_tx_seq_offset) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003575 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003576 goto drop;
3577 }
3578
3579 if (__is_iframe(control)) {
3580 if (len < 0) {
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003581 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003582 goto drop;
3583 }
3584
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003585 l2cap_data_channel_iframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003586 } else {
3587 if (len != 0) {
3588 BT_ERR("%d", len);
Gustavo F. Padovane92c8e72011-04-01 00:53:45 -03003589 l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003590 goto drop;
3591 }
3592
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003593 l2cap_data_channel_sframe(chan, control, skb);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003594 }
3595
3596 return 0;
3597
3598drop:
3599 kfree_skb(skb);
3600 return 0;
3601}
3602
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3604{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003605 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003607 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003608 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003609 u8 tx_seq;
3610 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003612 chan = l2cap_get_chan_by_scid(conn, cid);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003613 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614 BT_DBG("unknown cid 0x%4.4x", cid);
3615 goto drop;
3616 }
3617
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003618 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003619 pi = l2cap_pi(sk);
3620
Gustavo F. Padovan49208c92011-04-04 15:59:54 -03003621 BT_DBG("chan %p, len %d", chan, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622
3623 if (sk->sk_state != BT_CONNECTED)
3624 goto drop;
3625
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003626 switch (chan->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003627 case L2CAP_MODE_BASIC:
3628 /* If socket recv buffers overflows we drop data here
3629 * which is *bad* because L2CAP has to be reliable.
3630 * But we don't have any other choice. L2CAP doesn't
3631 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003633 if (chan->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003634 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003636 if (!sock_queue_rcv_skb(sk, skb))
3637 goto done;
3638 break;
3639
3640 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003641 if (!sock_owned_by_user(sk)) {
3642 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003643 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003644 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003645 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003646 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003647
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003648 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003649
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003650 case L2CAP_MODE_STREAMING:
3651 control = get_unaligned_le16(skb->data);
3652 skb_pull(skb, 2);
3653 len = skb->len;
3654
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003655 if (l2cap_check_fcs(chan, skb))
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003656 goto drop;
3657
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003658 if (__is_sar_start(control))
3659 len -= 2;
3660
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003661 if (chan->fcs == L2CAP_FCS_CRC16)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003662 len -= 2;
3663
Gustavo F. Padovan47d1ec62011-04-13 15:57:03 -03003664 if (len > chan->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003665 goto drop;
3666
3667 tx_seq = __get_txseq(control);
3668
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003669 if (chan->expected_tx_seq == tx_seq)
3670 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003671 else
Gustavo F. Padovan42e5c802011-03-25 19:58:34 -03003672 chan->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003673
Gustavo F. Padovan525cd182011-03-25 19:43:39 -03003674 l2cap_streaming_reassembly_sdu(chan, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003675
3676 goto done;
3677
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003678 default:
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003679 BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003680 break;
3681 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682
3683drop:
3684 kfree_skb(skb);
3685
3686done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003687 if (sk)
3688 bh_unlock_sock(sk);
3689
Linus Torvalds1da177e2005-04-16 15:20:36 -07003690 return 0;
3691}
3692
Al Viro8e036fc2007-07-29 00:16:36 -07003693static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694{
3695 struct sock *sk;
3696
3697 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3698 if (!sk)
3699 goto drop;
3700
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003701 bh_lock_sock(sk);
3702
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703 BT_DBG("sk %p, len %d", sk, skb->len);
3704
3705 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3706 goto drop;
3707
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003708 if (l2cap_pi(sk)->chan->imtu < skb->len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709 goto drop;
3710
3711 if (!sock_queue_rcv_skb(sk, skb))
3712 goto done;
3713
3714drop:
3715 kfree_skb(skb);
3716
3717done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003718 if (sk)
3719 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720 return 0;
3721}
3722
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003723static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
3724{
3725 struct sock *sk;
3726
3727 sk = l2cap_get_sock_by_scid(0, cid, conn->src);
3728 if (!sk)
3729 goto drop;
3730
3731 bh_lock_sock(sk);
3732
3733 BT_DBG("sk %p, len %d", sk, skb->len);
3734
3735 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3736 goto drop;
3737
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03003738 if (l2cap_pi(sk)->chan->imtu < skb->len)
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003739 goto drop;
3740
3741 if (!sock_queue_rcv_skb(sk, skb))
3742 goto done;
3743
3744drop:
3745 kfree_skb(skb);
3746
3747done:
3748 if (sk)
3749 bh_unlock_sock(sk);
3750 return 0;
3751}
3752
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3754{
3755 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003756 u16 cid, len;
3757 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758
3759 skb_pull(skb, L2CAP_HDR_SIZE);
3760 cid = __le16_to_cpu(lh->cid);
3761 len = __le16_to_cpu(lh->len);
3762
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003763 if (len != skb->len) {
3764 kfree_skb(skb);
3765 return;
3766 }
3767
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3769
3770 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003771 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003772 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773 l2cap_sig_channel(conn, skb);
3774 break;
3775
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003776 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003777 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778 skb_pull(skb, 2);
3779 l2cap_conless_channel(conn, psm, skb);
3780 break;
3781
Gustavo F. Padovan9f69bda2011-04-07 16:40:25 -03003782 case L2CAP_CID_LE_DATA:
3783 l2cap_att_channel(conn, cid, skb);
3784 break;
3785
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786 default:
3787 l2cap_data_channel(conn, cid, skb);
3788 break;
3789 }
3790}
3791
3792/* ---- L2CAP interface with lower layer (HCI) ---- */
3793
3794static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3795{
3796 int exact = 0, lm1 = 0, lm2 = 0;
3797 register struct sock *sk;
3798 struct hlist_node *node;
3799
3800 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003801 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802
3803 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3804
3805 /* Find listening sockets and check their link_mode */
3806 read_lock(&l2cap_sk_list.lock);
3807 sk_for_each(sk, node, &l2cap_sk_list.head) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003808 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
3809
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 if (sk->sk_state != BT_LISTEN)
3811 continue;
3812
3813 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003814 lm1 |= HCI_LM_ACCEPT;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003815 if (chan->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003816 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003818 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3819 lm2 |= HCI_LM_ACCEPT;
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003820 if (chan->role_switch)
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003821 lm2 |= HCI_LM_MASTER;
3822 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003823 }
3824 read_unlock(&l2cap_sk_list.lock);
3825
3826 return exact ? lm1 : lm2;
3827}
3828
3829static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3830{
Marcel Holtmann01394182006-07-03 10:02:46 +02003831 struct l2cap_conn *conn;
3832
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3834
Ville Tervoacd7d372011-02-10 22:38:49 -03003835 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003836 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837
3838 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839 conn = l2cap_conn_add(hcon, status);
3840 if (conn)
3841 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003842 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843 l2cap_conn_del(hcon, bt_err(status));
3844
3845 return 0;
3846}
3847
Marcel Holtmann2950f212009-02-12 14:02:50 +01003848static int l2cap_disconn_ind(struct hci_conn *hcon)
3849{
3850 struct l2cap_conn *conn = hcon->l2cap_data;
3851
3852 BT_DBG("hcon %p", hcon);
3853
3854 if (hcon->type != ACL_LINK || !conn)
3855 return 0x13;
3856
3857 return conn->disc_reason;
3858}
3859
3860static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861{
3862 BT_DBG("hcon %p reason %d", hcon, reason);
3863
Ville Tervoacd7d372011-02-10 22:38:49 -03003864 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003865 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003866
3867 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003868
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869 return 0;
3870}
3871
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003872static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003873{
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003874 struct sock *sk = chan->sk;
3875
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003876 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003877 return;
3878
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003879 if (encrypt == 0x00) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003880 if (chan->sec_level == BT_SECURITY_MEDIUM) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003881 l2cap_sock_clear_timer(sk);
3882 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003883 } else if (chan->sec_level == BT_SECURITY_HIGH)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003884 __l2cap_sock_close(sk, ECONNREFUSED);
3885 } else {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003886 if (chan->sec_level == BT_SECURITY_MEDIUM)
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003887 l2cap_sock_clear_timer(sk);
3888 }
3889}
3890
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003891static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892{
Marcel Holtmann40be4922008-07-14 20:13:50 +02003893 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003894 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895
Marcel Holtmann01394182006-07-03 10:02:46 +02003896 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003898
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899 BT_DBG("conn %p", conn);
3900
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003901 read_lock(&conn->chan_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003903 list_for_each_entry(chan, &conn->chan_l, list) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003904 struct sock *sk = chan->sk;
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003905
Linus Torvalds1da177e2005-04-16 15:20:36 -07003906 bh_lock_sock(sk);
3907
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003908 if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003909 bh_unlock_sock(sk);
3910 continue;
3911 }
3912
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003913 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003914 sk->sk_state == BT_CONFIG)) {
Gustavo F. Padovan43434782011-04-12 18:31:57 -03003915 l2cap_check_encryption(chan, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003916 bh_unlock_sock(sk);
3917 continue;
3918 }
3919
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003920 if (sk->sk_state == BT_CONNECT) {
3921 if (!status) {
3922 struct l2cap_conn_req req;
3923 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3924 req.psm = l2cap_pi(sk)->psm;
3925
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003926 chan->ident = l2cap_get_ident(conn);
Gustavo F. Padovanb4450032011-04-12 18:15:09 -03003927 chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003928
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003929 l2cap_send_cmd(conn, chan->ident,
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003930 L2CAP_CONN_REQ, sizeof(req), &req);
3931 } else {
3932 l2cap_sock_clear_timer(sk);
3933 l2cap_sock_set_timer(sk, HZ / 10);
3934 }
3935 } else if (sk->sk_state == BT_CONNECT2) {
3936 struct l2cap_conn_rsp rsp;
3937 __u16 result;
3938
3939 if (!status) {
3940 sk->sk_state = BT_CONFIG;
3941 result = L2CAP_CR_SUCCESS;
3942 } else {
3943 sk->sk_state = BT_DISCONN;
3944 l2cap_sock_set_timer(sk, HZ / 10);
3945 result = L2CAP_CR_SEC_BLOCK;
3946 }
3947
3948 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3949 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3950 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003951 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Gustavo F. Padovanfc7f8a72011-03-25 13:59:37 -03003952 l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
3953 sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954 }
3955
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956 bh_unlock_sock(sk);
3957 }
3958
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03003959 read_unlock(&conn->chan_lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003960
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961 return 0;
3962}
3963
3964static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3965{
3966 struct l2cap_conn *conn = hcon->l2cap_data;
3967
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003968 if (!conn)
3969 conn = l2cap_conn_add(hcon, 0);
3970
3971 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972 goto drop;
3973
3974 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3975
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003976 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003978 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003979 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980 int len;
3981
3982 if (conn->rx_len) {
3983 BT_ERR("Unexpected start frame (len %d)", skb->len);
3984 kfree_skb(conn->rx_skb);
3985 conn->rx_skb = NULL;
3986 conn->rx_len = 0;
3987 l2cap_conn_unreliable(conn, ECOMM);
3988 }
3989
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003990 /* Start fragment always begin with Basic L2CAP header */
3991 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992 BT_ERR("Frame is too short (len %d)", skb->len);
3993 l2cap_conn_unreliable(conn, ECOMM);
3994 goto drop;
3995 }
3996
3997 hdr = (struct l2cap_hdr *) skb->data;
3998 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003999 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004000
4001 if (len == skb->len) {
4002 /* Complete frame received */
4003 l2cap_recv_frame(conn, skb);
4004 return 0;
4005 }
4006
4007 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
4008
4009 if (skb->len > len) {
4010 BT_ERR("Frame is too long (len %d, expected len %d)",
4011 skb->len, len);
4012 l2cap_conn_unreliable(conn, ECOMM);
4013 goto drop;
4014 }
4015
Gustavo F. Padovanbaa7e1f2011-03-31 16:17:41 -03004016 chan = l2cap_get_chan_by_scid(conn, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004017
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004018 if (chan && chan->sk) {
4019 struct sock *sk = chan->sk;
4020
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004021 if (chan->imtu < len - L2CAP_HDR_SIZE) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004022 BT_ERR("Frame exceeding recv MTU (len %d, "
4023 "MTU %d)", len,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004024 chan->imtu);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03004025 bh_unlock_sock(sk);
4026 l2cap_conn_unreliable(conn, ECOMM);
4027 goto drop;
4028 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004029 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03004030 }
4031
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004033 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4034 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035 goto drop;
4036
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004037 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004038 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039 conn->rx_len = len - skb->len;
4040 } else {
4041 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4042
4043 if (!conn->rx_len) {
4044 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4045 l2cap_conn_unreliable(conn, ECOMM);
4046 goto drop;
4047 }
4048
4049 if (skb->len > conn->rx_len) {
4050 BT_ERR("Fragment is too long (len %d, expected %d)",
4051 skb->len, conn->rx_len);
4052 kfree_skb(conn->rx_skb);
4053 conn->rx_skb = NULL;
4054 conn->rx_len = 0;
4055 l2cap_conn_unreliable(conn, ECOMM);
4056 goto drop;
4057 }
4058
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004059 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004060 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061 conn->rx_len -= skb->len;
4062
4063 if (!conn->rx_len) {
4064 /* Complete frame received */
4065 l2cap_recv_frame(conn, conn->rx_skb);
4066 conn->rx_skb = NULL;
4067 }
4068 }
4069
4070drop:
4071 kfree_skb(skb);
4072 return 0;
4073}
4074
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004075static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004076{
4077 struct sock *sk;
4078 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079
4080 read_lock_bh(&l2cap_sk_list.lock);
4081
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004082 sk_for_each(sk, node, &l2cap_sk_list.head) {
4083 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004084 struct l2cap_chan *chan = pi->chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004086 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 +01004087 batostr(&bt_sk(sk)->src),
4088 batostr(&bt_sk(sk)->dst),
4089 sk->sk_state, __le16_to_cpu(pi->psm),
4090 pi->scid, pi->dcid,
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03004091 chan->imtu, chan->omtu, chan->sec_level,
4092 chan->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004093 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004096
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004097 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098}
4099
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004100static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4101{
4102 return single_open(file, l2cap_debugfs_show, inode->i_private);
4103}
4104
4105static const struct file_operations l2cap_debugfs_fops = {
4106 .open = l2cap_debugfs_open,
4107 .read = seq_read,
4108 .llseek = seq_lseek,
4109 .release = single_release,
4110};
4111
4112static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114static struct hci_proto l2cap_hci_proto = {
4115 .name = "L2CAP",
4116 .id = HCI_PROTO_L2CAP,
4117 .connect_ind = l2cap_connect_ind,
4118 .connect_cfm = l2cap_connect_cfm,
4119 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004120 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004121 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122 .recv_acldata = l2cap_recv_acldata
4123};
4124
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004125int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126{
4127 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004128
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004129 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130 if (err < 0)
4131 return err;
4132
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004133 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004134 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004135 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004136 goto error;
4137 }
4138
4139 err = hci_register_proto(&l2cap_hci_proto);
4140 if (err < 0) {
4141 BT_ERR("L2CAP protocol registration failed");
4142 bt_sock_unregister(BTPROTO_L2CAP);
4143 goto error;
4144 }
4145
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004146 if (bt_debugfs) {
4147 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4148 bt_debugfs, NULL, &l2cap_debugfs_fops);
4149 if (!l2cap_debugfs)
4150 BT_ERR("Failed to create L2CAP debug file");
4151 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153 return 0;
4154
4155error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004156 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004157 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158 return err;
4159}
4160
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004161void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004163 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004165 flush_workqueue(_busy_wq);
4166 destroy_workqueue(_busy_wq);
4167
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4169 BT_ERR("L2CAP protocol unregistration failed");
4170
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004171 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172}
4173
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004174module_param(disable_ertm, bool, 0644);
4175MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");