blob: e49d8f7b80a551ed8812e38ee1c783f13f605fb4 [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);
73
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030074static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
75
Marcel Holtmann01394182006-07-03 10:02:46 +020076/* ---- L2CAP channels ---- */
Gustavo F. Padovan48454072011-03-25 00:22:30 -030077static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020078{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030079 struct l2cap_chan *c;
80 for (c = l->head; c; c = c->next_c) {
81 if (l2cap_pi(c->sk)->dcid == cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020082 break;
83 }
Gustavo F. Padovan48454072011-03-25 00:22:30 -030084 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020085}
86
Gustavo F. Padovan48454072011-03-25 00:22:30 -030087static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020088{
Gustavo F. Padovan48454072011-03-25 00:22:30 -030089 struct l2cap_chan *c;
90 for (c = l->head; c; c = c->next_c) {
91 if (l2cap_pi(c->sk)->scid == cid)
Marcel Holtmann01394182006-07-03 10:02:46 +020092 break;
93 }
Gustavo F. Padovan48454072011-03-25 00:22:30 -030094 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +020095}
96
97/* Find channel with given SCID.
98 * Returns locked socket */
Gustavo F. Padovan48454072011-03-25 00:22:30 -030099static inline struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
Marcel Holtmann01394182006-07-03 10:02:46 +0200100{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300101 struct l2cap_chan *c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200102 read_lock(&l->lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300103 c = __l2cap_get_chan_by_scid(l, cid);
104 if (c)
105 bh_lock_sock(c->sk);
Marcel Holtmann01394182006-07-03 10:02:46 +0200106 read_unlock(&l->lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300107 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200108}
109
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300110static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200111{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300112 struct l2cap_chan *c;
113 for (c = l->head; c; c = c->next_c) {
114 if (l2cap_pi(c->sk)->ident == ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200115 break;
116 }
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300117 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200118}
119
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300120static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
Marcel Holtmann01394182006-07-03 10:02:46 +0200121{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300122 struct l2cap_chan *c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200123 read_lock(&l->lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300124 c = __l2cap_get_chan_by_ident(l, ident);
125 if (c)
126 bh_lock_sock(c->sk);
Marcel Holtmann01394182006-07-03 10:02:46 +0200127 read_unlock(&l->lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300128 return c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200129}
130
131static u16 l2cap_alloc_cid(struct l2cap_chan_list *l)
132{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300133 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200134
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300135 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300136 if (!__l2cap_get_chan_by_scid(l, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200137 return cid;
138 }
139
140 return 0;
141}
142
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300143static struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
Marcel Holtmann01394182006-07-03 10:02:46 +0200144{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300145 struct l2cap_chan *chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200146
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300147 chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
148 if (!chan)
149 return NULL;
Marcel Holtmann01394182006-07-03 10:02:46 +0200150
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300151 chan->sk = sk;
152
153 return chan;
Marcel Holtmann01394182006-07-03 10:02:46 +0200154}
155
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300156static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200157{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300158 sock_hold(chan->sk);
159
160 if (l->head)
161 l->head->prev_c = chan;
162
163 chan->next_c = l->head;
164 chan->prev_c = NULL;
165 l->head = chan;
166}
167
168static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct l2cap_chan *chan)
169{
170 struct l2cap_chan *next = chan->next_c, *prev = chan->prev_c;
Marcel Holtmann01394182006-07-03 10:02:46 +0200171
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200172 write_lock_bh(&l->lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300173 if (chan == l->head)
Marcel Holtmann01394182006-07-03 10:02:46 +0200174 l->head = next;
175
176 if (next)
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300177 next->prev_c = prev;
Marcel Holtmann01394182006-07-03 10:02:46 +0200178 if (prev)
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300179 prev->next_c = next;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200180 write_unlock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200181
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300182 __sock_put(chan->sk);
Marcel Holtmann01394182006-07-03 10:02:46 +0200183}
184
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300185static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Marcel Holtmann01394182006-07-03 10:02:46 +0200186{
187 struct l2cap_chan_list *l = &conn->chan_list;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300188 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200189
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300190 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
191 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200192
Marcel Holtmann2950f212009-02-12 14:02:50 +0100193 conn->disc_reason = 0x13;
194
Marcel Holtmann01394182006-07-03 10:02:46 +0200195 l2cap_pi(sk)->conn = conn;
196
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300197 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Ville Tervob62f3282011-02-10 22:38:50 -0300198 if (conn->hcon->type == LE_LINK) {
199 /* LE connection */
200 l2cap_pi(sk)->omtu = L2CAP_LE_DEFAULT_MTU;
201 l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA;
202 l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA;
203 } else {
204 /* Alloc CID for connection-oriented socket */
205 l2cap_pi(sk)->scid = l2cap_alloc_cid(l);
206 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
207 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200208 } else if (sk->sk_type == SOCK_DGRAM) {
209 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300210 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
211 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200212 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
213 } else {
214 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300215 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
216 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200217 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
218 }
219
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300220 __l2cap_chan_link(l, chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200221}
222
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900223/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200224 * Must be called on the locked socket. */
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300225void l2cap_chan_del(struct l2cap_chan *chan, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200226{
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300227 struct sock *sk = chan->sk;
Marcel Holtmann01394182006-07-03 10:02:46 +0200228 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
229 struct sock *parent = bt_sk(sk)->parent;
230
231 l2cap_sock_clear_timer(sk);
232
233 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
234
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900235 if (conn) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200236 /* Unlink from channel list */
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300237 l2cap_chan_unlink(&conn->chan_list, chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200238 l2cap_pi(sk)->conn = NULL;
239 hci_conn_put(conn->hcon);
240 }
241
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200242 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200243 sock_set_flag(sk, SOCK_ZAPPED);
244
245 if (err)
246 sk->sk_err = err;
247
248 if (parent) {
249 bt_accept_unlink(sk);
250 parent->sk_data_ready(parent, 0);
251 } else
252 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300253
254 skb_queue_purge(TX_QUEUE(sk));
255
256 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
257 struct srej_list *l, *tmp;
258
259 del_timer(&l2cap_pi(sk)->retrans_timer);
260 del_timer(&l2cap_pi(sk)->monitor_timer);
261 del_timer(&l2cap_pi(sk)->ack_timer);
262
263 skb_queue_purge(SREJ_QUEUE(sk));
264 skb_queue_purge(BUSY_QUEUE(sk));
265
266 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
267 list_del(&l->list);
268 kfree(l);
269 }
270 }
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300271
272 kfree(chan);
Marcel Holtmann01394182006-07-03 10:02:46 +0200273}
274
Johan Hedberg8556edd32011-01-19 12:06:50 +0530275static inline u8 l2cap_get_auth_type(struct sock *sk)
276{
277 if (sk->sk_type == SOCK_RAW) {
278 switch (l2cap_pi(sk)->sec_level) {
279 case BT_SECURITY_HIGH:
280 return HCI_AT_DEDICATED_BONDING_MITM;
281 case BT_SECURITY_MEDIUM:
282 return HCI_AT_DEDICATED_BONDING;
283 default:
284 return HCI_AT_NO_BONDING;
285 }
286 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
287 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
288 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
289
290 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
291 return HCI_AT_NO_BONDING_MITM;
292 else
293 return HCI_AT_NO_BONDING;
294 } else {
295 switch (l2cap_pi(sk)->sec_level) {
296 case BT_SECURITY_HIGH:
297 return HCI_AT_GENERAL_BONDING_MITM;
298 case BT_SECURITY_MEDIUM:
299 return HCI_AT_GENERAL_BONDING;
300 default:
301 return HCI_AT_NO_BONDING;
302 }
303 }
304}
305
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200306/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100307static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200308{
309 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100310 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200311
Johan Hedberg8556edd32011-01-19 12:06:50 +0530312 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100313
314 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
315 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200316}
317
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200318u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200319{
320 u8 id;
321
322 /* Get next available identificator.
323 * 1 - 128 are used by kernel.
324 * 129 - 199 are reserved.
325 * 200 - 254 are used by utilities like l2ping, etc.
326 */
327
328 spin_lock_bh(&conn->lock);
329
330 if (++conn->tx_ident > 128)
331 conn->tx_ident = 1;
332
333 id = conn->tx_ident;
334
335 spin_unlock_bh(&conn->lock);
336
337 return id;
338}
339
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200340void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200341{
342 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200343 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200344
345 BT_DBG("code 0x%2.2x", code);
346
347 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300348 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200349
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200350 if (lmp_no_flush_capable(conn->hcon->hdev))
351 flags = ACL_START_NO_FLUSH;
352 else
353 flags = ACL_START;
354
355 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200356}
357
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300358static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300359{
360 struct sk_buff *skb;
361 struct l2cap_hdr *lh;
362 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300363 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300364 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200365 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300366
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300367 if (sk->sk_state != BT_CONNECTED)
368 return;
369
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300370 if (pi->fcs == L2CAP_FCS_CRC16)
371 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300372
373 BT_DBG("pi %p, control 0x%2.2x", pi, control);
374
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300375 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300376 control |= L2CAP_CTRL_FRAME_TYPE;
377
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300378 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
379 control |= L2CAP_CTRL_FINAL;
380 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
381 }
382
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300383 if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
384 control |= L2CAP_CTRL_POLL;
385 pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
386 }
387
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300388 skb = bt_skb_alloc(count, GFP_ATOMIC);
389 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300390 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300391
392 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300393 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300394 lh->cid = cpu_to_le16(pi->dcid);
395 put_unaligned_le16(control, skb_put(skb, 2));
396
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300397 if (pi->fcs == L2CAP_FCS_CRC16) {
398 u16 fcs = crc16(0, (u8 *)lh, count - 2);
399 put_unaligned_le16(fcs, skb_put(skb, 2));
400 }
401
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200402 if (lmp_no_flush_capable(conn->hcon->hdev))
403 flags = ACL_START_NO_FLUSH;
404 else
405 flags = ACL_START;
406
407 hci_send_acl(pi->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300408}
409
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300410static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300411{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300412 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300413 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300414 pi->conn_state |= L2CAP_CONN_RNR_SENT;
415 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300416 control |= L2CAP_SUPER_RCV_READY;
417
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300418 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
419
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300420 l2cap_send_sframe(pi, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300421}
422
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300423static inline int __l2cap_no_conn_pending(struct sock *sk)
424{
425 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
426}
427
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200428static void l2cap_do_start(struct sock *sk)
429{
430 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
431
432 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100433 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
434 return;
435
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300436 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200437 struct l2cap_conn_req req;
438 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
439 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200440
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200441 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300442 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200443
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200444 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200445 L2CAP_CONN_REQ, sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200446 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200447 } else {
448 struct l2cap_info_req req;
449 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
450
451 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
452 conn->info_ident = l2cap_get_ident(conn);
453
454 mod_timer(&conn->info_timer, jiffies +
455 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
456
457 l2cap_send_cmd(conn, conn->info_ident,
458 L2CAP_INFO_REQ, sizeof(req), &req);
459 }
460}
461
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300462static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
463{
464 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300465 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300466 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
467
468 switch (mode) {
469 case L2CAP_MODE_ERTM:
470 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
471 case L2CAP_MODE_STREAMING:
472 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
473 default:
474 return 0x00;
475 }
476}
477
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200478void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300479{
480 struct l2cap_disconn_req req;
481
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300482 if (!conn)
483 return;
484
485 skb_queue_purge(TX_QUEUE(sk));
486
487 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
488 del_timer(&l2cap_pi(sk)->retrans_timer);
489 del_timer(&l2cap_pi(sk)->monitor_timer);
490 del_timer(&l2cap_pi(sk)->ack_timer);
491 }
492
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300493 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
494 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
495 l2cap_send_cmd(conn, l2cap_get_ident(conn),
496 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300497
498 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300499 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300500}
501
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200503static void l2cap_conn_start(struct l2cap_conn *conn)
504{
505 struct l2cap_chan_list *l = &conn->chan_list;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300506 struct sock_del_list del, *tmp1, *tmp2;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300507 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200508
509 BT_DBG("conn %p", conn);
510
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300511 INIT_LIST_HEAD(&del.list);
512
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200513 read_lock(&l->lock);
514
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300515 for (chan = l->head; chan; chan = chan->next_c) {
516 struct sock *sk = chan->sk;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200517 bh_lock_sock(sk);
518
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300519 if (sk->sk_type != SOCK_SEQPACKET &&
520 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200521 bh_unlock_sock(sk);
522 continue;
523 }
524
525 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300526 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300527
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300528 if (!l2cap_check_security(sk) ||
529 !__l2cap_no_conn_pending(sk)) {
530 bh_unlock_sock(sk);
531 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200532 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300533
534 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
535 conn->feat_mask)
536 && l2cap_pi(sk)->conf_state &
537 L2CAP_CONF_STATE2_DEVICE) {
538 tmp1 = kzalloc(sizeof(struct sock_del_list),
539 GFP_ATOMIC);
540 tmp1->sk = sk;
541 list_add_tail(&tmp1->list, &del.list);
542 bh_unlock_sock(sk);
543 continue;
544 }
545
546 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
547 req.psm = l2cap_pi(sk)->psm;
548
549 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
550 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
551
552 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
553 L2CAP_CONN_REQ, sizeof(req), &req);
554
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200555 } else if (sk->sk_state == BT_CONNECT2) {
556 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300557 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200558 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
559 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
560
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100561 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100562 if (bt_sk(sk)->defer_setup) {
563 struct sock *parent = bt_sk(sk)->parent;
564 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
565 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
566 parent->sk_data_ready(parent, 0);
567
568 } else {
569 sk->sk_state = BT_CONFIG;
570 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
571 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
572 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200573 } else {
574 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
575 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
576 }
577
578 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
579 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300580
581 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
582 rsp.result != L2CAP_CR_SUCCESS) {
583 bh_unlock_sock(sk);
584 continue;
585 }
586
587 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
588 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
589 l2cap_build_conf_req(sk, buf), buf);
590 l2cap_pi(sk)->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200591 }
592
593 bh_unlock_sock(sk);
594 }
595
596 read_unlock(&l->lock);
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300597
598 list_for_each_entry_safe(tmp1, tmp2, &del.list, list) {
599 bh_lock_sock(tmp1->sk);
600 __l2cap_sock_close(tmp1->sk, ECONNRESET);
601 bh_unlock_sock(tmp1->sk);
602 list_del(&tmp1->list);
603 kfree(tmp1);
604 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200605}
606
Ville Tervob62f3282011-02-10 22:38:50 -0300607/* Find socket with cid and source bdaddr.
608 * Returns closest match, locked.
609 */
610static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
611{
612 struct sock *s, *sk = NULL, *sk1 = NULL;
613 struct hlist_node *node;
614
615 read_lock(&l2cap_sk_list.lock);
616
617 sk_for_each(sk, node, &l2cap_sk_list.head) {
618 if (state && sk->sk_state != state)
619 continue;
620
621 if (l2cap_pi(sk)->scid == cid) {
622 /* Exact match. */
623 if (!bacmp(&bt_sk(sk)->src, src))
624 break;
625
626 /* Closest match */
627 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
628 sk1 = sk;
629 }
630 }
631 s = node ? sk : sk1;
632 if (s)
633 bh_lock_sock(s);
634 read_unlock(&l2cap_sk_list.lock);
635
636 return s;
637}
638
639static void l2cap_le_conn_ready(struct l2cap_conn *conn)
640{
641 struct l2cap_chan_list *list = &conn->chan_list;
642 struct sock *parent, *uninitialized_var(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300643 struct l2cap_chan *chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300644
645 BT_DBG("");
646
647 /* Check if we have socket listening on cid */
648 parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
649 conn->src);
650 if (!parent)
651 return;
652
653 /* Check for backlog size */
654 if (sk_acceptq_is_full(parent)) {
655 BT_DBG("backlog full %d", parent->sk_ack_backlog);
656 goto clean;
657 }
658
659 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
660 if (!sk)
661 goto clean;
662
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300663 chan = l2cap_chan_alloc(sk);
664 if (!chan) {
665 l2cap_sock_kill(sk);
666 goto clean;
667 }
668
Ville Tervob62f3282011-02-10 22:38:50 -0300669 write_lock_bh(&list->lock);
670
671 hci_conn_hold(conn->hcon);
672
673 l2cap_sock_init(sk, parent);
674 bacpy(&bt_sk(sk)->src, conn->src);
675 bacpy(&bt_sk(sk)->dst, conn->dst);
676
Gustavo F. Padovand1010242011-03-25 00:39:48 -0300677 bt_accept_enqueue(parent, sk);
678
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300679 __l2cap_chan_add(conn, chan);
680
681 l2cap_pi(sk)->chan = chan;
Ville Tervob62f3282011-02-10 22:38:50 -0300682
683 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
684
685 sk->sk_state = BT_CONNECTED;
686 parent->sk_data_ready(parent, 0);
687
688 write_unlock_bh(&list->lock);
689
690clean:
691 bh_unlock_sock(parent);
692}
693
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200694static void l2cap_conn_ready(struct l2cap_conn *conn)
695{
696 struct l2cap_chan_list *l = &conn->chan_list;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300697 struct l2cap_chan *chan;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200698
699 BT_DBG("conn %p", conn);
700
Ville Tervob62f3282011-02-10 22:38:50 -0300701 if (!conn->hcon->out && conn->hcon->type == LE_LINK)
702 l2cap_le_conn_ready(conn);
703
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200704 read_lock(&l->lock);
705
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300706 for (chan = l->head; chan; chan = chan->next_c) {
707 struct sock *sk = chan->sk;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200708 bh_lock_sock(sk);
709
Ville Tervoacd7d372011-02-10 22:38:49 -0300710 if (conn->hcon->type == LE_LINK) {
711 l2cap_sock_clear_timer(sk);
712 sk->sk_state = BT_CONNECTED;
713 sk->sk_state_change(sk);
714 }
715
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300716 if (sk->sk_type != SOCK_SEQPACKET &&
717 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200718 l2cap_sock_clear_timer(sk);
719 sk->sk_state = BT_CONNECTED;
720 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200721 } else if (sk->sk_state == BT_CONNECT)
722 l2cap_do_start(sk);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200723
724 bh_unlock_sock(sk);
725 }
726
727 read_unlock(&l->lock);
728}
729
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200730/* Notify sockets that we cannot guaranty reliability anymore */
731static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
732{
733 struct l2cap_chan_list *l = &conn->chan_list;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300734 struct l2cap_chan *chan;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200735
736 BT_DBG("conn %p", conn);
737
738 read_lock(&l->lock);
739
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300740 for (chan = l->head; chan; chan = chan->next_c) {
741 struct sock *sk = chan->sk;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100742 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200743 sk->sk_err = err;
744 }
745
746 read_unlock(&l->lock);
747}
748
749static void l2cap_info_timeout(unsigned long arg)
750{
751 struct l2cap_conn *conn = (void *) arg;
752
Marcel Holtmann984947d2009-02-06 23:35:19 +0100753 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100754 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100755
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200756 l2cap_conn_start(conn);
757}
758
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
760{
Marcel Holtmann01394182006-07-03 10:02:46 +0200761 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762
Marcel Holtmann01394182006-07-03 10:02:46 +0200763 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 return conn;
765
Marcel Holtmann01394182006-07-03 10:02:46 +0200766 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
767 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769
770 hcon->l2cap_data = conn;
771 conn->hcon = hcon;
772
Marcel Holtmann01394182006-07-03 10:02:46 +0200773 BT_DBG("hcon %p conn %p", hcon, conn);
774
Ville Tervoacd7d372011-02-10 22:38:49 -0300775 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
776 conn->mtu = hcon->hdev->le_mtu;
777 else
778 conn->mtu = hcon->hdev->acl_mtu;
779
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 conn->src = &hcon->hdev->bdaddr;
781 conn->dst = &hcon->dst;
782
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200783 conn->feat_mask = 0;
784
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 spin_lock_init(&conn->lock);
786 rwlock_init(&conn->chan_list.lock);
787
Ville Tervob62f3282011-02-10 22:38:50 -0300788 if (hcon->type != LE_LINK)
789 setup_timer(&conn->info_timer, l2cap_info_timeout,
Dave Young45054dc2009-10-18 20:28:30 +0000790 (unsigned long) conn);
791
Marcel Holtmann2950f212009-02-12 14:02:50 +0100792 conn->disc_reason = 0x13;
793
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 return conn;
795}
796
Marcel Holtmann01394182006-07-03 10:02:46 +0200797static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798{
Marcel Holtmann01394182006-07-03 10:02:46 +0200799 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300800 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 struct sock *sk;
802
Marcel Holtmann01394182006-07-03 10:02:46 +0200803 if (!conn)
804 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805
806 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
807
Wei Yongjun7585b972009-02-25 18:29:52 +0800808 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809
810 /* Kill channels */
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300811 while ((chan = conn->chan_list.head)) {
812 sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 bh_lock_sock(sk);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300814 l2cap_chan_del(chan, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 bh_unlock_sock(sk);
816 l2cap_sock_kill(sk);
817 }
818
Dave Young8e8440f2008-03-03 12:18:55 -0800819 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
820 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800821
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 hcon->l2cap_data = NULL;
823 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824}
825
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300826static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827{
828 struct l2cap_chan_list *l = &conn->chan_list;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200829 write_lock_bh(&l->lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300830 __l2cap_chan_add(conn, chan);
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200831 write_unlock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832}
833
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835
836/* Find socket with psm and source bdaddr.
837 * Returns closest match.
838 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000839static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840{
841 struct sock *sk = NULL, *sk1 = NULL;
842 struct hlist_node *node;
843
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000844 read_lock(&l2cap_sk_list.lock);
845
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 sk_for_each(sk, node, &l2cap_sk_list.head) {
847 if (state && sk->sk_state != state)
848 continue;
849
850 if (l2cap_pi(sk)->psm == psm) {
851 /* Exact match. */
852 if (!bacmp(&bt_sk(sk)->src, src))
853 break;
854
855 /* Closest match */
856 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
857 sk1 = sk;
858 }
859 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000862
863 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864}
865
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200866int l2cap_do_connect(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867{
868 bdaddr_t *src = &bt_sk(sk)->src;
869 bdaddr_t *dst = &bt_sk(sk)->dst;
870 struct l2cap_conn *conn;
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300871 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 struct hci_conn *hcon;
873 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200874 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200875 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100877 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
878 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300880 hdev = hci_get_route(dst, src);
881 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 return -EHOSTUNREACH;
883
884 hci_dev_lock_bh(hdev);
885
Johan Hedberg8556edd32011-01-19 12:06:50 +0530886 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200887
Ville Tervoacd7d372011-02-10 22:38:49 -0300888 if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
889 hcon = hci_connect(hdev, LE_LINK, dst,
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100890 l2cap_pi(sk)->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300891 else
892 hcon = hci_connect(hdev, ACL_LINK, dst,
893 l2cap_pi(sk)->sec_level, auth_type);
894
Ville Tervo30e76272011-02-22 16:10:53 -0300895 if (IS_ERR(hcon)) {
896 err = PTR_ERR(hcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 goto done;
Ville Tervo30e76272011-02-22 16:10:53 -0300898 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899
900 conn = l2cap_conn_add(hcon, 0);
901 if (!conn) {
902 hci_conn_put(hcon);
Ville Tervo30e76272011-02-22 16:10:53 -0300903 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 goto done;
905 }
906
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300907 chan = l2cap_chan_alloc(sk);
908 if (!chan) {
909 hci_conn_put(hcon);
910 err = -ENOMEM;
911 goto done;
912 }
913
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 /* Update source addr of the socket */
915 bacpy(src, conn->src);
916
Gustavo F. Padovan48454072011-03-25 00:22:30 -0300917 l2cap_chan_add(conn, chan);
918
919 l2cap_pi(sk)->chan = chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920
921 sk->sk_state = BT_CONNECT;
922 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
923
924 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300925 if (sk->sk_type != SOCK_SEQPACKET &&
926 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530928 if (l2cap_check_security(sk))
929 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200930 } else
931 l2cap_do_start(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 }
933
Ville Tervo30e76272011-02-22 16:10:53 -0300934 err = 0;
935
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936done:
937 hci_dev_unlock_bh(hdev);
938 hci_dev_put(hdev);
939 return err;
940}
941
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200942int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300943{
944 DECLARE_WAITQUEUE(wait, current);
945 int err = 0;
946 int timeo = HZ/5;
947
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200948 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300949 while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
950 set_current_state(TASK_INTERRUPTIBLE);
951
952 if (!timeo)
953 timeo = HZ/5;
954
955 if (signal_pending(current)) {
956 err = sock_intr_errno(timeo);
957 break;
958 }
959
960 release_sock(sk);
961 timeo = schedule_timeout(timeo);
962 lock_sock(sk);
963
964 err = sock_error(sk);
965 if (err)
966 break;
967 }
968 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200969 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300970 return err;
971}
972
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300973static void l2cap_monitor_timeout(unsigned long arg)
974{
975 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300976
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300977 BT_DBG("sk %p", sk);
978
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300979 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300980 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300981 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200982 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300983 return;
984 }
985
986 l2cap_pi(sk)->retry_count++;
987 __mod_monitor_timer();
988
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -0300989 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300990 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300991}
992
993static void l2cap_retrans_timeout(unsigned long arg)
994{
995 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300996
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300997 BT_DBG("sk %p", sk);
998
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300999 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001000 l2cap_pi(sk)->retry_count = 1;
1001 __mod_monitor_timer();
1002
1003 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
1004
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03001005 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -03001006 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001007}
1008
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001009static void l2cap_drop_acked_frames(struct sock *sk)
1010{
1011 struct sk_buff *skb;
1012
Gustavo F. Padovan812e7372010-05-01 16:15:42 -03001013 while ((skb = skb_peek(TX_QUEUE(sk))) &&
1014 l2cap_pi(sk)->unacked_frames) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001015 if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
1016 break;
1017
1018 skb = skb_dequeue(TX_QUEUE(sk));
1019 kfree_skb(skb);
1020
1021 l2cap_pi(sk)->unacked_frames--;
1022 }
1023
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001024 if (!l2cap_pi(sk)->unacked_frames)
1025 del_timer(&l2cap_pi(sk)->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001026}
1027
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001028void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001029{
1030 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001031 struct hci_conn *hcon = pi->conn->hcon;
1032 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001033
1034 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
1035
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02001036 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
1037 flags = ACL_START_NO_FLUSH;
1038 else
1039 flags = ACL_START;
1040
1041 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001042}
1043
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001044void l2cap_streaming_send(struct sock *sk)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001045{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001046 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001047 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001048 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001049
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001050 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
1051 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001052 control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001053 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001054
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001055 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001056 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
1057 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001058 }
1059
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -03001060 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001061
1062 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001063 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001064}
1065
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001066static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001067{
1068 struct l2cap_pinfo *pi = l2cap_pi(sk);
1069 struct sk_buff *skb, *tx_skb;
1070 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001071
1072 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001073 if (!skb)
1074 return;
1075
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001076 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001077 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001078 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001079
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001080 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1081 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001082
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001083 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001084
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001085 if (pi->remote_max_tx &&
1086 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001087 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001088 return;
1089 }
1090
1091 tx_skb = skb_clone(skb, GFP_ATOMIC);
1092 bt_cb(skb)->retries++;
1093 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001094
1095 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1096 control |= L2CAP_CTRL_FINAL;
1097 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1098 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001099
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001100 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1101 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03001102
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -03001103 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1104
1105 if (pi->fcs == L2CAP_FCS_CRC16) {
1106 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
1107 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
1108 }
1109
1110 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03001111}
1112
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001113int l2cap_ertm_send(struct sock *sk)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001114{
1115 struct sk_buff *skb, *tx_skb;
1116 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001117 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001118 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001119
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -03001120 if (sk->sk_state != BT_CONNECTED)
1121 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001122
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -03001123 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001124
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001125 if (pi->remote_max_tx &&
1126 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03001127 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001128 break;
1129 }
1130
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001131 tx_skb = skb_clone(skb, GFP_ATOMIC);
1132
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001133 bt_cb(skb)->retries++;
1134
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001135 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001136 control &= L2CAP_CTRL_SAR;
1137
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001138 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1139 control |= L2CAP_CTRL_FINAL;
1140 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1141 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001142 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001143 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1144 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1145
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001146
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001147 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001148 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1149 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1150 }
1151
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001152 l2cap_do_send(sk, tx_skb);
1153
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001154 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001155
1156 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1157 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1158
Suraj Sumangala23e9fde2011-03-09 14:44:05 +05301159 if (bt_cb(skb)->retries == 1)
1160 pi->unacked_frames++;
1161
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001162 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001163
1164 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1165 sk->sk_send_head = NULL;
1166 else
1167 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001168
1169 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001170 }
1171
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001172 return nsent;
1173}
1174
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001175static int l2cap_retransmit_frames(struct sock *sk)
1176{
1177 struct l2cap_pinfo *pi = l2cap_pi(sk);
1178 int ret;
1179
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001180 if (!skb_queue_empty(TX_QUEUE(sk)))
1181 sk->sk_send_head = TX_QUEUE(sk)->next;
1182
1183 pi->next_tx_seq = pi->expected_ack_seq;
1184 ret = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001185 return ret;
1186}
1187
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001188static void l2cap_send_ack(struct l2cap_pinfo *pi)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001189{
1190 struct sock *sk = (struct sock *)pi;
1191 u16 control = 0;
1192
1193 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1194
1195 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1196 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001197 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001198 l2cap_send_sframe(pi, control);
1199 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001200 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001201
Gustavo F. Padovane0f66212010-06-21 18:50:49 -03001202 if (l2cap_ertm_send(sk) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001203 return;
1204
1205 control |= L2CAP_SUPER_RCV_READY;
1206 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001207}
1208
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001209static void l2cap_send_srejtail(struct sock *sk)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001210{
1211 struct srej_list *tail;
1212 u16 control;
1213
1214 control = L2CAP_SUPER_SELECT_REJECT;
1215 control |= L2CAP_CTRL_FINAL;
1216
1217 tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
1218 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1219
1220 l2cap_send_sframe(l2cap_pi(sk), control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001221}
1222
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001223static 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 -07001224{
1225 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001226 struct sk_buff **frag;
1227 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001229 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001230 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231
1232 sent += count;
1233 len -= count;
1234
1235 /* Continuation fragments (no L2CAP header) */
1236 frag = &skb_shinfo(skb)->frag_list;
1237 while (len) {
1238 count = min_t(unsigned int, conn->mtu, len);
1239
1240 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1241 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001242 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001243 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1244 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245
1246 sent += count;
1247 len -= count;
1248
1249 frag = &(*frag)->next;
1250 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251
1252 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001253}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001255struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001256{
1257 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1258 struct sk_buff *skb;
1259 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1260 struct l2cap_hdr *lh;
1261
1262 BT_DBG("sk %p len %d", sk, (int)len);
1263
1264 count = min_t(unsigned int, (conn->mtu - hlen), len);
1265 skb = bt_skb_send_alloc(sk, count + hlen,
1266 msg->msg_flags & MSG_DONTWAIT, &err);
1267 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001268 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001269
1270 /* Create L2CAP header */
1271 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1272 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1273 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1274 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1275
1276 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1277 if (unlikely(err < 0)) {
1278 kfree_skb(skb);
1279 return ERR_PTR(err);
1280 }
1281 return skb;
1282}
1283
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001284struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001285{
1286 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1287 struct sk_buff *skb;
1288 int err, count, hlen = L2CAP_HDR_SIZE;
1289 struct l2cap_hdr *lh;
1290
1291 BT_DBG("sk %p len %d", sk, (int)len);
1292
1293 count = min_t(unsigned int, (conn->mtu - hlen), len);
1294 skb = bt_skb_send_alloc(sk, count + hlen,
1295 msg->msg_flags & MSG_DONTWAIT, &err);
1296 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001297 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001298
1299 /* Create L2CAP header */
1300 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1301 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1302 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1303
1304 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1305 if (unlikely(err < 0)) {
1306 kfree_skb(skb);
1307 return ERR_PTR(err);
1308 }
1309 return skb;
1310}
1311
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001312struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001313{
1314 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1315 struct sk_buff *skb;
1316 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1317 struct l2cap_hdr *lh;
1318
1319 BT_DBG("sk %p len %d", sk, (int)len);
1320
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001321 if (!conn)
1322 return ERR_PTR(-ENOTCONN);
1323
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001324 if (sdulen)
1325 hlen += 2;
1326
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001327 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1328 hlen += 2;
1329
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001330 count = min_t(unsigned int, (conn->mtu - hlen), len);
1331 skb = bt_skb_send_alloc(sk, count + hlen,
1332 msg->msg_flags & MSG_DONTWAIT, &err);
1333 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001334 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001335
1336 /* Create L2CAP header */
1337 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1338 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1339 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1340 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001341 if (sdulen)
1342 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001343
1344 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1345 if (unlikely(err < 0)) {
1346 kfree_skb(skb);
1347 return ERR_PTR(err);
1348 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001349
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001350 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1351 put_unaligned_le16(0, skb_put(skb, 2));
1352
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001353 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001354 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355}
1356
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001357int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001358{
1359 struct l2cap_pinfo *pi = l2cap_pi(sk);
1360 struct sk_buff *skb;
1361 struct sk_buff_head sar_queue;
1362 u16 control;
1363 size_t size = 0;
1364
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001365 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001366 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001367 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001368 if (IS_ERR(skb))
1369 return PTR_ERR(skb);
1370
1371 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001372 len -= pi->remote_mps;
1373 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001374
1375 while (len > 0) {
1376 size_t buflen;
1377
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001378 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001379 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001380 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001381 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001382 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001383 buflen = len;
1384 }
1385
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001386 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001387 if (IS_ERR(skb)) {
1388 skb_queue_purge(&sar_queue);
1389 return PTR_ERR(skb);
1390 }
1391
1392 __skb_queue_tail(&sar_queue, skb);
1393 len -= buflen;
1394 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001395 }
1396 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1397 if (sk->sk_send_head == NULL)
1398 sk->sk_send_head = sar_queue.next;
1399
1400 return size;
1401}
1402
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403static void l2cap_chan_ready(struct sock *sk)
1404{
1405 struct sock *parent = bt_sk(sk)->parent;
1406
1407 BT_DBG("sk %p, parent %p", sk, parent);
1408
1409 l2cap_pi(sk)->conf_state = 0;
1410 l2cap_sock_clear_timer(sk);
1411
1412 if (!parent) {
1413 /* Outgoing channel.
1414 * Wake up socket sleeping on connect.
1415 */
1416 sk->sk_state = BT_CONNECTED;
1417 sk->sk_state_change(sk);
1418 } else {
1419 /* Incoming channel.
1420 * Wake up socket sleeping on accept.
1421 */
1422 parent->sk_data_ready(parent, 0);
1423 }
1424}
1425
1426/* Copy frame to all raw sockets on that connection */
1427static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1428{
1429 struct l2cap_chan_list *l = &conn->chan_list;
1430 struct sk_buff *nskb;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001431 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432
1433 BT_DBG("conn %p", conn);
1434
1435 read_lock(&l->lock);
Gustavo F. Padovan48454072011-03-25 00:22:30 -03001436 for (chan = l->head; chan; chan = chan->next_c) {
1437 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 if (sk->sk_type != SOCK_RAW)
1439 continue;
1440
1441 /* Don't send frame to the socket it came from */
1442 if (skb->sk == sk)
1443 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001444 nskb = skb_clone(skb, GFP_ATOMIC);
1445 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 continue;
1447
1448 if (sock_queue_rcv_skb(sk, nskb))
1449 kfree_skb(nskb);
1450 }
1451 read_unlock(&l->lock);
1452}
1453
1454/* ---- L2CAP signalling commands ---- */
1455static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1456 u8 code, u8 ident, u16 dlen, void *data)
1457{
1458 struct sk_buff *skb, **frag;
1459 struct l2cap_cmd_hdr *cmd;
1460 struct l2cap_hdr *lh;
1461 int len, count;
1462
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001463 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1464 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465
1466 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1467 count = min_t(unsigned int, conn->mtu, len);
1468
1469 skb = bt_skb_alloc(count, GFP_ATOMIC);
1470 if (!skb)
1471 return NULL;
1472
1473 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001474 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02001475
1476 if (conn->hcon->type == LE_LINK)
1477 lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
1478 else
1479 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480
1481 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1482 cmd->code = code;
1483 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001484 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485
1486 if (dlen) {
1487 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1488 memcpy(skb_put(skb, count), data, count);
1489 data += count;
1490 }
1491
1492 len -= skb->len;
1493
1494 /* Continuation fragments (no L2CAP header) */
1495 frag = &skb_shinfo(skb)->frag_list;
1496 while (len) {
1497 count = min_t(unsigned int, conn->mtu, len);
1498
1499 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1500 if (!*frag)
1501 goto fail;
1502
1503 memcpy(skb_put(*frag, count), data, count);
1504
1505 len -= count;
1506 data += count;
1507
1508 frag = &(*frag)->next;
1509 }
1510
1511 return skb;
1512
1513fail:
1514 kfree_skb(skb);
1515 return NULL;
1516}
1517
1518static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1519{
1520 struct l2cap_conf_opt *opt = *ptr;
1521 int len;
1522
1523 len = L2CAP_CONF_OPT_SIZE + opt->len;
1524 *ptr += len;
1525
1526 *type = opt->type;
1527 *olen = opt->len;
1528
1529 switch (opt->len) {
1530 case 1:
1531 *val = *((u8 *) opt->val);
1532 break;
1533
1534 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001535 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 break;
1537
1538 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001539 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 break;
1541
1542 default:
1543 *val = (unsigned long) opt->val;
1544 break;
1545 }
1546
1547 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1548 return len;
1549}
1550
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1552{
1553 struct l2cap_conf_opt *opt = *ptr;
1554
1555 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1556
1557 opt->type = type;
1558 opt->len = len;
1559
1560 switch (len) {
1561 case 1:
1562 *((u8 *) opt->val) = val;
1563 break;
1564
1565 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001566 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 break;
1568
1569 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001570 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571 break;
1572
1573 default:
1574 memcpy(opt->val, (void *) val, len);
1575 break;
1576 }
1577
1578 *ptr += L2CAP_CONF_OPT_SIZE + len;
1579}
1580
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001581static void l2cap_ack_timeout(unsigned long arg)
1582{
1583 struct sock *sk = (void *) arg;
1584
1585 bh_lock_sock(sk);
1586 l2cap_send_ack(l2cap_pi(sk));
1587 bh_unlock_sock(sk);
1588}
1589
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001590static inline void l2cap_ertm_init(struct sock *sk)
1591{
1592 l2cap_pi(sk)->expected_ack_seq = 0;
1593 l2cap_pi(sk)->unacked_frames = 0;
1594 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03001595 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001596 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001597
1598 setup_timer(&l2cap_pi(sk)->retrans_timer,
1599 l2cap_retrans_timeout, (unsigned long) sk);
1600 setup_timer(&l2cap_pi(sk)->monitor_timer,
1601 l2cap_monitor_timeout, (unsigned long) sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001602 setup_timer(&l2cap_pi(sk)->ack_timer,
1603 l2cap_ack_timeout, (unsigned long) sk);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001604
1605 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001606 __skb_queue_head_init(BUSY_QUEUE(sk));
1607
1608 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001609
1610 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001611}
1612
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001613static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1614{
1615 switch (mode) {
1616 case L2CAP_MODE_STREAMING:
1617 case L2CAP_MODE_ERTM:
1618 if (l2cap_mode_supported(mode, remote_feat_mask))
1619 return mode;
1620 /* fall through */
1621 default:
1622 return L2CAP_MODE_BASIC;
1623 }
1624}
1625
Gustavo F. Padovan68983252011-02-04 03:02:31 -02001626int l2cap_build_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627{
1628 struct l2cap_pinfo *pi = l2cap_pi(sk);
1629 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001630 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 void *ptr = req->data;
1632
1633 BT_DBG("sk %p", sk);
1634
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001635 if (pi->num_conf_req || pi->num_conf_rsp)
1636 goto done;
1637
1638 switch (pi->mode) {
1639 case L2CAP_MODE_STREAMING:
1640 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001641 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001642 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001643
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001644 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001645 default:
1646 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1647 break;
1648 }
1649
1650done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001651 if (pi->imtu != L2CAP_DEFAULT_MTU)
1652 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1653
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001654 switch (pi->mode) {
1655 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001656 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1657 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1658 break;
1659
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001660 rfc.mode = L2CAP_MODE_BASIC;
1661 rfc.txwin_size = 0;
1662 rfc.max_transmit = 0;
1663 rfc.retrans_timeout = 0;
1664 rfc.monitor_timeout = 0;
1665 rfc.max_pdu_size = 0;
1666
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001667 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1668 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001669 break;
1670
1671 case L2CAP_MODE_ERTM:
1672 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001673 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001674 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001675 rfc.retrans_timeout = 0;
1676 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001677 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001678 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001679 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001680
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001681 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1682 (unsigned long) &rfc);
1683
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001684 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1685 break;
1686
1687 if (pi->fcs == L2CAP_FCS_NONE ||
1688 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1689 pi->fcs = L2CAP_FCS_NONE;
1690 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1691 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001692 break;
1693
1694 case L2CAP_MODE_STREAMING:
1695 rfc.mode = L2CAP_MODE_STREAMING;
1696 rfc.txwin_size = 0;
1697 rfc.max_transmit = 0;
1698 rfc.retrans_timeout = 0;
1699 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001700 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001701 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001702 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001703
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001704 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1705 (unsigned long) &rfc);
1706
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001707 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1708 break;
1709
1710 if (pi->fcs == L2CAP_FCS_NONE ||
1711 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1712 pi->fcs = L2CAP_FCS_NONE;
1713 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1714 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001715 break;
1716 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001718 req->dcid = cpu_to_le16(pi->dcid);
1719 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720
1721 return ptr - data;
1722}
1723
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001724static int l2cap_parse_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725{
1726 struct l2cap_pinfo *pi = l2cap_pi(sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001727 struct l2cap_conf_rsp *rsp = data;
1728 void *ptr = rsp->data;
1729 void *req = pi->conf_req;
1730 int len = pi->conf_len;
1731 int type, hint, olen;
1732 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001733 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001734 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001735 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001737 BT_DBG("sk %p", sk);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001738
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001739 while (len >= L2CAP_CONF_OPT_SIZE) {
1740 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001742 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001743 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001744
1745 switch (type) {
1746 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001747 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001748 break;
1749
1750 case L2CAP_CONF_FLUSH_TO:
1751 pi->flush_to = val;
1752 break;
1753
1754 case L2CAP_CONF_QOS:
1755 break;
1756
Marcel Holtmann6464f352007-10-20 13:39:51 +02001757 case L2CAP_CONF_RFC:
1758 if (olen == sizeof(rfc))
1759 memcpy(&rfc, (void *) val, olen);
1760 break;
1761
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001762 case L2CAP_CONF_FCS:
1763 if (val == L2CAP_FCS_NONE)
1764 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1765
1766 break;
1767
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001768 default:
1769 if (hint)
1770 break;
1771
1772 result = L2CAP_CONF_UNKNOWN;
1773 *((u8 *) ptr++) = type;
1774 break;
1775 }
1776 }
1777
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001778 if (pi->num_conf_rsp || pi->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001779 goto done;
1780
1781 switch (pi->mode) {
1782 case L2CAP_MODE_STREAMING:
1783 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001784 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1785 pi->mode = l2cap_select_mode(rfc.mode,
1786 pi->conn->feat_mask);
1787 break;
1788 }
1789
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001790 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001791 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001792
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001793 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001794 }
1795
1796done:
1797 if (pi->mode != rfc.mode) {
1798 result = L2CAP_CONF_UNACCEPT;
1799 rfc.mode = pi->mode;
1800
1801 if (pi->num_conf_rsp == 1)
1802 return -ECONNREFUSED;
1803
1804 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1805 sizeof(rfc), (unsigned long) &rfc);
1806 }
1807
1808
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001809 if (result == L2CAP_CONF_SUCCESS) {
1810 /* Configure output options and let the other side know
1811 * which ones we don't like. */
1812
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001813 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1814 result = L2CAP_CONF_UNACCEPT;
1815 else {
1816 pi->omtu = mtu;
1817 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1818 }
1819 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001820
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001821 switch (rfc.mode) {
1822 case L2CAP_MODE_BASIC:
1823 pi->fcs = L2CAP_FCS_NONE;
1824 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1825 break;
1826
1827 case L2CAP_MODE_ERTM:
1828 pi->remote_tx_win = rfc.txwin_size;
1829 pi->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001830
1831 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
1834 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001835
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001836 rfc.retrans_timeout =
1837 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1838 rfc.monitor_timeout =
1839 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001840
1841 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001842
1843 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1844 sizeof(rfc), (unsigned long) &rfc);
1845
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001846 break;
1847
1848 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001849 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1850 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001851
1852 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001853
1854 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001855
1856 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1857 sizeof(rfc), (unsigned long) &rfc);
1858
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001859 break;
1860
1861 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001862 result = L2CAP_CONF_UNACCEPT;
1863
1864 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001865 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001866 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001867
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001868 if (result == L2CAP_CONF_SUCCESS)
1869 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1870 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001871 rsp->scid = cpu_to_le16(pi->dcid);
1872 rsp->result = cpu_to_le16(result);
1873 rsp->flags = cpu_to_le16(0x0000);
1874
1875 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876}
1877
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001878static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1879{
1880 struct l2cap_pinfo *pi = l2cap_pi(sk);
1881 struct l2cap_conf_req *req = data;
1882 void *ptr = req->data;
1883 int type, olen;
1884 unsigned long val;
1885 struct l2cap_conf_rfc rfc;
1886
1887 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1888
1889 while (len >= L2CAP_CONF_OPT_SIZE) {
1890 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1891
1892 switch (type) {
1893 case L2CAP_CONF_MTU:
1894 if (val < L2CAP_DEFAULT_MIN_MTU) {
1895 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001896 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001897 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001898 pi->imtu = val;
1899 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001900 break;
1901
1902 case L2CAP_CONF_FLUSH_TO:
1903 pi->flush_to = val;
1904 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1905 2, pi->flush_to);
1906 break;
1907
1908 case L2CAP_CONF_RFC:
1909 if (olen == sizeof(rfc))
1910 memcpy(&rfc, (void *)val, olen);
1911
1912 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1913 rfc.mode != pi->mode)
1914 return -ECONNREFUSED;
1915
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001916 pi->fcs = 0;
1917
1918 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1919 sizeof(rfc), (unsigned long) &rfc);
1920 break;
1921 }
1922 }
1923
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001924 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1925 return -ECONNREFUSED;
1926
1927 pi->mode = rfc.mode;
1928
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001929 if (*result == L2CAP_CONF_SUCCESS) {
1930 switch (rfc.mode) {
1931 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001932 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1933 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001934 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001935 break;
1936 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001937 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001938 }
1939 }
1940
1941 req->dcid = cpu_to_le16(pi->dcid);
1942 req->flags = cpu_to_le16(0x0000);
1943
1944 return ptr - data;
1945}
1946
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001947static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948{
1949 struct l2cap_conf_rsp *rsp = data;
1950 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001952 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001954 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001955 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001956 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957
1958 return ptr - data;
1959}
1960
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001961static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1962{
1963 struct l2cap_pinfo *pi = l2cap_pi(sk);
1964 int type, olen;
1965 unsigned long val;
1966 struct l2cap_conf_rfc rfc;
1967
1968 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1969
1970 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1971 return;
1972
1973 while (len >= L2CAP_CONF_OPT_SIZE) {
1974 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1975
1976 switch (type) {
1977 case L2CAP_CONF_RFC:
1978 if (olen == sizeof(rfc))
1979 memcpy(&rfc, (void *)val, olen);
1980 goto done;
1981 }
1982 }
1983
1984done:
1985 switch (rfc.mode) {
1986 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001987 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1988 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001989 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1990 break;
1991 case L2CAP_MODE_STREAMING:
1992 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1993 }
1994}
1995
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001996static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1997{
1998 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
1999
2000 if (rej->reason != 0x0000)
2001 return 0;
2002
2003 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
2004 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002005 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01002006
2007 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002008 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002009
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002010 l2cap_conn_start(conn);
2011 }
2012
2013 return 0;
2014}
2015
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2017{
2018 struct l2cap_chan_list *list = &conn->chan_list;
2019 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2020 struct l2cap_conn_rsp rsp;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002021 struct l2cap_chan *chan;
Nathan Holsteind793fe82010-10-15 11:54:02 -04002022 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002023 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024
2025 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002026 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027
2028 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
2029
2030 /* Check if we have socket listening on psm */
2031 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
2032 if (!parent) {
2033 result = L2CAP_CR_BAD_PSM;
2034 goto sendresp;
2035 }
2036
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00002037 bh_lock_sock(parent);
2038
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002039 /* Check if the ACL is secure enough (if not SDP) */
2040 if (psm != cpu_to_le16(0x0001) &&
2041 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01002042 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02002043 result = L2CAP_CR_SEC_BLOCK;
2044 goto response;
2045 }
2046
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 result = L2CAP_CR_NO_MEM;
2048
2049 /* Check for backlog size */
2050 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002051 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 goto response;
2053 }
2054
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002055 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056 if (!sk)
2057 goto response;
2058
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002059 chan = l2cap_chan_alloc(sk);
2060 if (!chan) {
2061 l2cap_sock_kill(sk);
2062 goto response;
2063 }
2064
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002065 write_lock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066
2067 /* Check if we already have channel with that dcid */
2068 if (__l2cap_get_chan_by_dcid(list, scid)) {
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002069 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 sock_set_flag(sk, SOCK_ZAPPED);
2071 l2cap_sock_kill(sk);
2072 goto response;
2073 }
2074
2075 hci_conn_hold(conn->hcon);
2076
2077 l2cap_sock_init(sk, parent);
2078 bacpy(&bt_sk(sk)->src, conn->src);
2079 bacpy(&bt_sk(sk)->dst, conn->dst);
2080 l2cap_pi(sk)->psm = psm;
2081 l2cap_pi(sk)->dcid = scid;
2082
Gustavo F. Padovand1010242011-03-25 00:39:48 -03002083 bt_accept_enqueue(parent, sk);
2084
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002085 __l2cap_chan_add(conn, chan);
2086
2087 l2cap_pi(sk)->chan = chan;
2088
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 dcid = l2cap_pi(sk)->scid;
2090
2091 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
2092
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 l2cap_pi(sk)->ident = cmd->ident;
2094
Marcel Holtmann984947d2009-02-06 23:35:19 +01002095 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01002096 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01002097 if (bt_sk(sk)->defer_setup) {
2098 sk->sk_state = BT_CONNECT2;
2099 result = L2CAP_CR_PEND;
2100 status = L2CAP_CS_AUTHOR_PEND;
2101 parent->sk_data_ready(parent, 0);
2102 } else {
2103 sk->sk_state = BT_CONFIG;
2104 result = L2CAP_CR_SUCCESS;
2105 status = L2CAP_CS_NO_INFO;
2106 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002107 } else {
2108 sk->sk_state = BT_CONNECT2;
2109 result = L2CAP_CR_PEND;
2110 status = L2CAP_CS_AUTHEN_PEND;
2111 }
2112 } else {
2113 sk->sk_state = BT_CONNECT2;
2114 result = L2CAP_CR_PEND;
2115 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 }
2117
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02002118 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119
2120response:
2121 bh_unlock_sock(parent);
2122
2123sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002124 rsp.scid = cpu_to_le16(scid);
2125 rsp.dcid = cpu_to_le16(dcid);
2126 rsp.result = cpu_to_le16(result);
2127 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002129
2130 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
2131 struct l2cap_info_req info;
2132 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2133
2134 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
2135 conn->info_ident = l2cap_get_ident(conn);
2136
2137 mod_timer(&conn->info_timer, jiffies +
2138 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
2139
2140 l2cap_send_cmd(conn, conn->info_ident,
2141 L2CAP_INFO_REQ, sizeof(info), &info);
2142 }
2143
Nathan Holsteind793fe82010-10-15 11:54:02 -04002144 if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002145 result == L2CAP_CR_SUCCESS) {
2146 u8 buf[128];
2147 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2148 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2149 l2cap_build_conf_req(sk, buf), buf);
2150 l2cap_pi(sk)->num_conf_req++;
2151 }
2152
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 return 0;
2154}
2155
2156static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2157{
2158 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2159 u16 scid, dcid, result, status;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002160 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 struct sock *sk;
2162 u8 req[128];
2163
2164 scid = __le16_to_cpu(rsp->scid);
2165 dcid = __le16_to_cpu(rsp->dcid);
2166 result = __le16_to_cpu(rsp->result);
2167 status = __le16_to_cpu(rsp->status);
2168
2169 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2170
2171 if (scid) {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002172 chan = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2173 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002174 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175 } else {
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002176 chan = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
2177 if (!chan)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002178 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 }
2180
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002181 sk = chan->sk;
2182
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 switch (result) {
2184 case L2CAP_CR_SUCCESS:
2185 sk->sk_state = BT_CONFIG;
2186 l2cap_pi(sk)->ident = 0;
2187 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002188 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2189
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002190 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2191 break;
2192
2193 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2194
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2196 l2cap_build_conf_req(sk, req), req);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002197 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 break;
2199
2200 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002201 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 break;
2203
2204 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002205 /* don't delete l2cap channel if sk is owned by user */
2206 if (sock_owned_by_user(sk)) {
2207 sk->sk_state = BT_DISCONN;
2208 l2cap_sock_clear_timer(sk);
2209 l2cap_sock_set_timer(sk, HZ / 5);
2210 break;
2211 }
2212
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002213 l2cap_chan_del(chan, ECONNREFUSED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 break;
2215 }
2216
2217 bh_unlock_sock(sk);
2218 return 0;
2219}
2220
Mat Martineau8c462b62010-08-24 15:35:42 -07002221static inline void set_default_fcs(struct l2cap_pinfo *pi)
2222{
2223 /* FCS is enabled only in ERTM or streaming mode, if one or both
2224 * sides request it.
2225 */
2226 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2227 pi->fcs = L2CAP_FCS_NONE;
2228 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2229 pi->fcs = L2CAP_FCS_CRC16;
2230}
2231
Al Viro88219a02007-07-29 00:17:25 -07002232static 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 -07002233{
2234 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2235 u16 dcid, flags;
2236 u8 rsp[64];
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002237 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002239 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240
2241 dcid = __le16_to_cpu(req->dcid);
2242 flags = __le16_to_cpu(req->flags);
2243
2244 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2245
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002246 chan = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2247 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 return -ENOENT;
2249
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002250 sk = chan->sk;
2251
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002252 if (sk->sk_state != BT_CONFIG) {
2253 struct l2cap_cmd_rej rej;
2254
2255 rej.reason = cpu_to_le16(0x0002);
2256 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2257 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002258 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002259 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002260
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002261 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002262 len = cmd_len - sizeof(*req);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002263 if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
2264 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2265 l2cap_build_conf_rsp(sk, rsp,
2266 L2CAP_CONF_REJECT, flags), rsp);
2267 goto unlock;
2268 }
2269
2270 /* Store config. */
2271 memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
2272 l2cap_pi(sk)->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273
2274 if (flags & 0x0001) {
2275 /* Incomplete config. Send empty response. */
2276 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002277 l2cap_build_conf_rsp(sk, rsp,
2278 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279 goto unlock;
2280 }
2281
2282 /* Complete config. */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002283 len = l2cap_parse_conf_req(sk, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002284 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002285 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002287 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002289 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002290 l2cap_pi(sk)->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002291
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002292 /* Reset config buffer. */
2293 l2cap_pi(sk)->conf_len = 0;
2294
Marcel Holtmann876d9482007-10-20 13:35:42 +02002295 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2296 goto unlock;
2297
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002299 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002300
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002302
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002303 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002304 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002305 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002306 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2307 l2cap_ertm_init(sk);
2308
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002310 goto unlock;
2311 }
2312
2313 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002314 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002315 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002317 l2cap_build_conf_req(sk, buf), buf);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002318 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319 }
2320
2321unlock:
2322 bh_unlock_sock(sk);
2323 return 0;
2324}
2325
2326static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2327{
2328 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2329 u16 scid, flags, result;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002330 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002332 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333
2334 scid = __le16_to_cpu(rsp->scid);
2335 flags = __le16_to_cpu(rsp->flags);
2336 result = __le16_to_cpu(rsp->result);
2337
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002338 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2339 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002341 chan = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2342 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343 return 0;
2344
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002345 sk = chan->sk;
2346
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 switch (result) {
2348 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002349 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 break;
2351
2352 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002353 if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002354 char req[64];
2355
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002356 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002357 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002358 goto done;
2359 }
2360
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002361 /* throw out any old stored conf requests */
2362 result = L2CAP_CONF_SUCCESS;
2363 len = l2cap_parse_conf_rsp(sk, rsp->data,
2364 len, req, &result);
2365 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002366 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002367 goto done;
2368 }
2369
2370 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2371 L2CAP_CONF_REQ, len, req);
2372 l2cap_pi(sk)->num_conf_req++;
2373 if (result != L2CAP_CONF_SUCCESS)
2374 goto done;
2375 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376 }
2377
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002378 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002379 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002381 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382 goto done;
2383 }
2384
2385 if (flags & 0x01)
2386 goto done;
2387
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2389
2390 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002391 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002392
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002394 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002395 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002396 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002397 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2398 l2cap_ertm_init(sk);
2399
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 l2cap_chan_ready(sk);
2401 }
2402
2403done:
2404 bh_unlock_sock(sk);
2405 return 0;
2406}
2407
2408static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2409{
2410 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2411 struct l2cap_disconn_rsp rsp;
2412 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002413 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 struct sock *sk;
2415
2416 scid = __le16_to_cpu(req->scid);
2417 dcid = __le16_to_cpu(req->dcid);
2418
2419 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2420
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002421 chan = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2422 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 return 0;
2424
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002425 sk = chan->sk;
2426
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002427 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2428 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2430
2431 sk->sk_shutdown = SHUTDOWN_MASK;
2432
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002433 /* don't delete l2cap channel if sk is owned by user */
2434 if (sock_owned_by_user(sk)) {
2435 sk->sk_state = BT_DISCONN;
2436 l2cap_sock_clear_timer(sk);
2437 l2cap_sock_set_timer(sk, HZ / 5);
2438 bh_unlock_sock(sk);
2439 return 0;
2440 }
2441
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002442 l2cap_chan_del(chan, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 bh_unlock_sock(sk);
2444
2445 l2cap_sock_kill(sk);
2446 return 0;
2447}
2448
2449static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2450{
2451 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2452 u16 dcid, scid;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002453 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 struct sock *sk;
2455
2456 scid = __le16_to_cpu(rsp->scid);
2457 dcid = __le16_to_cpu(rsp->dcid);
2458
2459 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2460
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002461 chan = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2462 if (!chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 return 0;
2464
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002465 sk = chan->sk;
2466
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002467 /* don't delete l2cap channel if sk is owned by user */
2468 if (sock_owned_by_user(sk)) {
2469 sk->sk_state = BT_DISCONN;
2470 l2cap_sock_clear_timer(sk);
2471 l2cap_sock_set_timer(sk, HZ / 5);
2472 bh_unlock_sock(sk);
2473 return 0;
2474 }
2475
Gustavo F. Padovan48454072011-03-25 00:22:30 -03002476 l2cap_chan_del(chan, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 bh_unlock_sock(sk);
2478
2479 l2cap_sock_kill(sk);
2480 return 0;
2481}
2482
2483static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2484{
2485 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486 u16 type;
2487
2488 type = __le16_to_cpu(req->type);
2489
2490 BT_DBG("type 0x%4.4x", type);
2491
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002492 if (type == L2CAP_IT_FEAT_MASK) {
2493 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002494 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002495 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2496 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2497 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002498 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002499 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2500 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002501 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002502 l2cap_send_cmd(conn, cmd->ident,
2503 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002504 } else if (type == L2CAP_IT_FIXED_CHAN) {
2505 u8 buf[12];
2506 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2507 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2508 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2509 memcpy(buf + 4, l2cap_fixed_chan, 8);
2510 l2cap_send_cmd(conn, cmd->ident,
2511 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002512 } else {
2513 struct l2cap_info_rsp rsp;
2514 rsp.type = cpu_to_le16(type);
2515 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2516 l2cap_send_cmd(conn, cmd->ident,
2517 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2518 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519
2520 return 0;
2521}
2522
2523static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2524{
2525 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2526 u16 type, result;
2527
2528 type = __le16_to_cpu(rsp->type);
2529 result = __le16_to_cpu(rsp->result);
2530
2531 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2532
Andrei Emeltchenkoe90165b2011-03-25 11:31:41 +02002533 /* L2CAP Info req/rsp are unbound to channels, add extra checks */
2534 if (cmd->ident != conn->info_ident ||
2535 conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
2536 return 0;
2537
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002538 del_timer(&conn->info_timer);
2539
Ville Tervoadb08ed2010-08-04 09:43:33 +03002540 if (result != L2CAP_IR_SUCCESS) {
2541 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2542 conn->info_ident = 0;
2543
2544 l2cap_conn_start(conn);
2545
2546 return 0;
2547 }
2548
Marcel Holtmann984947d2009-02-06 23:35:19 +01002549 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002550 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002551
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002552 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002553 struct l2cap_info_req req;
2554 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2555
2556 conn->info_ident = l2cap_get_ident(conn);
2557
2558 l2cap_send_cmd(conn, conn->info_ident,
2559 L2CAP_INFO_REQ, sizeof(req), &req);
2560 } else {
2561 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2562 conn->info_ident = 0;
2563
2564 l2cap_conn_start(conn);
2565 }
2566 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002567 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002568 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002569
2570 l2cap_conn_start(conn);
2571 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002572
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573 return 0;
2574}
2575
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002576static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
Claudio Takahaside731152011-02-11 19:28:55 -02002577 u16 to_multiplier)
2578{
2579 u16 max_latency;
2580
2581 if (min > max || min < 6 || max > 3200)
2582 return -EINVAL;
2583
2584 if (to_multiplier < 10 || to_multiplier > 3200)
2585 return -EINVAL;
2586
2587 if (max >= to_multiplier * 8)
2588 return -EINVAL;
2589
2590 max_latency = (to_multiplier * 8 / max) - 1;
2591 if (latency > 499 || latency > max_latency)
2592 return -EINVAL;
2593
2594 return 0;
2595}
2596
2597static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
2598 struct l2cap_cmd_hdr *cmd, u8 *data)
2599{
2600 struct hci_conn *hcon = conn->hcon;
2601 struct l2cap_conn_param_update_req *req;
2602 struct l2cap_conn_param_update_rsp rsp;
2603 u16 min, max, latency, to_multiplier, cmd_len;
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002604 int err;
Claudio Takahaside731152011-02-11 19:28:55 -02002605
2606 if (!(hcon->link_mode & HCI_LM_MASTER))
2607 return -EINVAL;
2608
2609 cmd_len = __le16_to_cpu(cmd->len);
2610 if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
2611 return -EPROTO;
2612
2613 req = (struct l2cap_conn_param_update_req *) data;
Gustavo F. Padovane2174ca2011-02-17 19:16:55 -03002614 min = __le16_to_cpu(req->min);
2615 max = __le16_to_cpu(req->max);
Claudio Takahaside731152011-02-11 19:28:55 -02002616 latency = __le16_to_cpu(req->latency);
2617 to_multiplier = __le16_to_cpu(req->to_multiplier);
2618
2619 BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
2620 min, max, latency, to_multiplier);
2621
2622 memset(&rsp, 0, sizeof(rsp));
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002623
2624 err = l2cap_check_conn_param(min, max, latency, to_multiplier);
2625 if (err)
Claudio Takahaside731152011-02-11 19:28:55 -02002626 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
2627 else
2628 rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
2629
2630 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
2631 sizeof(rsp), &rsp);
2632
Claudio Takahasi2ce603e2011-02-16 20:44:53 -02002633 if (!err)
2634 hci_le_conn_update(hcon, min, max, latency, to_multiplier);
2635
Claudio Takahaside731152011-02-11 19:28:55 -02002636 return 0;
2637}
2638
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002639static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
2640 struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
2641{
2642 int err = 0;
2643
2644 switch (cmd->code) {
2645 case L2CAP_COMMAND_REJ:
2646 l2cap_command_rej(conn, cmd, data);
2647 break;
2648
2649 case L2CAP_CONN_REQ:
2650 err = l2cap_connect_req(conn, cmd, data);
2651 break;
2652
2653 case L2CAP_CONN_RSP:
2654 err = l2cap_connect_rsp(conn, cmd, data);
2655 break;
2656
2657 case L2CAP_CONF_REQ:
2658 err = l2cap_config_req(conn, cmd, cmd_len, data);
2659 break;
2660
2661 case L2CAP_CONF_RSP:
2662 err = l2cap_config_rsp(conn, cmd, data);
2663 break;
2664
2665 case L2CAP_DISCONN_REQ:
2666 err = l2cap_disconnect_req(conn, cmd, data);
2667 break;
2668
2669 case L2CAP_DISCONN_RSP:
2670 err = l2cap_disconnect_rsp(conn, cmd, data);
2671 break;
2672
2673 case L2CAP_ECHO_REQ:
2674 l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
2675 break;
2676
2677 case L2CAP_ECHO_RSP:
2678 break;
2679
2680 case L2CAP_INFO_REQ:
2681 err = l2cap_information_req(conn, cmd, data);
2682 break;
2683
2684 case L2CAP_INFO_RSP:
2685 err = l2cap_information_rsp(conn, cmd, data);
2686 break;
2687
2688 default:
2689 BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
2690 err = -EINVAL;
2691 break;
2692 }
2693
2694 return err;
2695}
2696
2697static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
2698 struct l2cap_cmd_hdr *cmd, u8 *data)
2699{
2700 switch (cmd->code) {
2701 case L2CAP_COMMAND_REJ:
2702 return 0;
2703
2704 case L2CAP_CONN_PARAM_UPDATE_REQ:
Claudio Takahaside731152011-02-11 19:28:55 -02002705 return l2cap_conn_param_update_req(conn, cmd, data);
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002706
2707 case L2CAP_CONN_PARAM_UPDATE_RSP:
2708 return 0;
2709
2710 default:
2711 BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
2712 return -EINVAL;
2713 }
2714}
2715
2716static inline void l2cap_sig_channel(struct l2cap_conn *conn,
2717 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718{
2719 u8 *data = skb->data;
2720 int len = skb->len;
2721 struct l2cap_cmd_hdr cmd;
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002722 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723
2724 l2cap_raw_recv(conn, skb);
2725
2726 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002727 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2729 data += L2CAP_CMD_HDR_SIZE;
2730 len -= L2CAP_CMD_HDR_SIZE;
2731
Al Viro88219a02007-07-29 00:17:25 -07002732 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733
Al Viro88219a02007-07-29 00:17:25 -07002734 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 -07002735
Al Viro88219a02007-07-29 00:17:25 -07002736 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 BT_DBG("corrupted command");
2738 break;
2739 }
2740
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02002741 if (conn->hcon->type == LE_LINK)
2742 err = l2cap_le_sig_cmd(conn, &cmd, data);
2743 else
2744 err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745
2746 if (err) {
2747 struct l2cap_cmd_rej rej;
Gustavo F. Padovan2c6d1a22011-03-23 14:38:32 -03002748
2749 BT_ERR("Wrong link type (%d)", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750
2751 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002752 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2754 }
2755
Al Viro88219a02007-07-29 00:17:25 -07002756 data += cmd_len;
2757 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758 }
2759
2760 kfree_skb(skb);
2761}
2762
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002763static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2764{
2765 u16 our_fcs, rcv_fcs;
2766 int hdr_size = L2CAP_HDR_SIZE + 2;
2767
2768 if (pi->fcs == L2CAP_FCS_CRC16) {
2769 skb_trim(skb, skb->len - 2);
2770 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2771 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2772
2773 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002774 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002775 }
2776 return 0;
2777}
2778
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002779static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
2780{
2781 struct l2cap_pinfo *pi = l2cap_pi(sk);
2782 u16 control = 0;
2783
2784 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002785
2786 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2787
2788 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002789 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002790 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002791 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002792 }
2793
Gustavo F. Padovan4ea727e2010-06-03 16:34:20 -03002794 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
2795 l2cap_retransmit_frames(sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002796
2797 l2cap_ertm_send(sk);
2798
2799 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
2800 pi->frames_sent == 0) {
2801 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002802 l2cap_send_sframe(pi, control);
2803 }
2804}
2805
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002806static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002807{
2808 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002809 struct l2cap_pinfo *pi = l2cap_pi(sk);
2810 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002811
2812 bt_cb(skb)->tx_seq = tx_seq;
2813 bt_cb(skb)->sar = sar;
2814
2815 next_skb = skb_peek(SREJ_QUEUE(sk));
2816 if (!next_skb) {
2817 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002818 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002819 }
2820
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002821 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
2822 if (tx_seq_offset < 0)
2823 tx_seq_offset += 64;
2824
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002825 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002826 if (bt_cb(next_skb)->tx_seq == tx_seq)
2827 return -EINVAL;
2828
João Paulo Rechi Vitabfbacc112010-05-31 18:35:44 -03002829 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
2830 pi->buffer_seq) % 64;
2831 if (next_tx_seq_offset < 0)
2832 next_tx_seq_offset += 64;
2833
2834 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002835 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002836 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002837 }
2838
2839 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
2840 break;
2841
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002842 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002843
2844 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002845
2846 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002847}
2848
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002849static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
2850{
2851 struct l2cap_pinfo *pi = l2cap_pi(sk);
2852 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002853 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002854
2855 switch (control & L2CAP_CTRL_SAR) {
2856 case L2CAP_SDU_UNSEGMENTED:
2857 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2858 goto drop;
2859
2860 err = sock_queue_rcv_skb(sk, skb);
2861 if (!err)
2862 return err;
2863
2864 break;
2865
2866 case L2CAP_SDU_START:
2867 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2868 goto drop;
2869
2870 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002871
2872 if (pi->sdu_len > pi->imtu)
2873 goto disconnect;
2874
2875 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002876 if (!pi->sdu)
2877 return -ENOMEM;
2878
2879 /* pull sdu_len bytes only after alloc, because of Local Busy
2880 * condition we have to be sure that this will be executed
2881 * only once, i.e., when alloc does not fail */
2882 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002883
2884 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2885
2886 pi->conn_state |= L2CAP_CONN_SAR_SDU;
2887 pi->partial_sdu_len = skb->len;
2888 break;
2889
2890 case L2CAP_SDU_CONTINUE:
2891 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2892 goto disconnect;
2893
2894 if (!pi->sdu)
2895 goto disconnect;
2896
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002897 pi->partial_sdu_len += skb->len;
2898 if (pi->partial_sdu_len > pi->sdu_len)
2899 goto drop;
2900
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002901 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2902
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002903 break;
2904
2905 case L2CAP_SDU_END:
2906 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2907 goto disconnect;
2908
2909 if (!pi->sdu)
2910 goto disconnect;
2911
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002912 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002913 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002914
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002915 if (pi->partial_sdu_len > pi->imtu)
2916 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002917
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002918 if (pi->partial_sdu_len != pi->sdu_len)
2919 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002920
2921 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002922 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002923
2924 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002925 if (!_skb) {
2926 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2927 return -ENOMEM;
2928 }
2929
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002930 err = sock_queue_rcv_skb(sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002931 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002932 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002933 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2934 return err;
2935 }
2936
2937 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2938 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002939
2940 kfree_skb(pi->sdu);
2941 break;
2942 }
2943
2944 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002945 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002946
2947drop:
2948 kfree_skb(pi->sdu);
2949 pi->sdu = NULL;
2950
2951disconnect:
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002952 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002953 kfree_skb(skb);
2954 return 0;
2955}
2956
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002957static int l2cap_try_push_rx_skb(struct sock *sk)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002958{
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002959 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002960 struct sk_buff *skb;
2961 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002962 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002963
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002964 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
2965 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
2966 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
2967 if (err < 0) {
2968 skb_queue_head(BUSY_QUEUE(sk), skb);
2969 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002970 }
2971
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002972 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002973 }
2974
2975 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
2976 goto done;
2977
2978 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2979 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
2980 l2cap_send_sframe(pi, control);
2981 l2cap_pi(sk)->retry_count = 1;
2982
2983 del_timer(&pi->retrans_timer);
2984 __mod_monitor_timer();
2985
2986 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
2987
2988done:
2989 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2990 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
2991
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002992 BT_DBG("sk %p, Exit local busy", sk);
2993
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002994 return 0;
2995}
2996
2997static void l2cap_busy_work(struct work_struct *work)
2998{
2999 DECLARE_WAITQUEUE(wait, current);
3000 struct l2cap_pinfo *pi =
3001 container_of(work, struct l2cap_pinfo, busy_work);
3002 struct sock *sk = (struct sock *)pi;
3003 int n_tries = 0, timeo = HZ/5, err;
3004 struct sk_buff *skb;
3005
3006 lock_sock(sk);
3007
3008 add_wait_queue(sk_sleep(sk), &wait);
3009 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
3010 set_current_state(TASK_INTERRUPTIBLE);
3011
3012 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
3013 err = -EBUSY;
3014 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
3015 break;
3016 }
3017
3018 if (!timeo)
3019 timeo = HZ/5;
3020
3021 if (signal_pending(current)) {
3022 err = sock_intr_errno(timeo);
3023 break;
3024 }
3025
3026 release_sock(sk);
3027 timeo = schedule_timeout(timeo);
3028 lock_sock(sk);
3029
3030 err = sock_error(sk);
3031 if (err)
3032 break;
3033
3034 if (l2cap_try_push_rx_skb(sk) == 0)
3035 break;
3036 }
3037
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003038 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02003039 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003040
3041 release_sock(sk);
3042}
3043
3044static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
3045{
3046 struct l2cap_pinfo *pi = l2cap_pi(sk);
3047 int sctrl, err;
3048
3049 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
3050 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3051 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03003052 return l2cap_try_push_rx_skb(sk);
3053
3054
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003055 }
3056
3057 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
3058 if (err >= 0) {
3059 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3060 return err;
3061 }
3062
3063 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003064 BT_DBG("sk %p, Enter local busy", sk);
3065
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003066 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
3067 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
3068 __skb_queue_tail(BUSY_QUEUE(sk), skb);
3069
3070 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3071 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
3072 l2cap_send_sframe(pi, sctrl);
3073
3074 pi->conn_state |= L2CAP_CONN_RNR_SENT;
3075
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003076 del_timer(&pi->ack_timer);
3077
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003078 queue_work(_busy_wq, &pi->busy_work);
3079
3080 return err;
3081}
3082
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003083static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003084{
3085 struct l2cap_pinfo *pi = l2cap_pi(sk);
3086 struct sk_buff *_skb;
3087 int err = -EINVAL;
3088
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003089 /*
3090 * TODO: We have to notify the userland if some data is lost with the
3091 * Streaming Mode.
3092 */
3093
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003094 switch (control & L2CAP_CTRL_SAR) {
3095 case L2CAP_SDU_UNSEGMENTED:
3096 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3097 kfree_skb(pi->sdu);
3098 break;
3099 }
3100
3101 err = sock_queue_rcv_skb(sk, skb);
3102 if (!err)
3103 return 0;
3104
3105 break;
3106
3107 case L2CAP_SDU_START:
3108 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
3109 kfree_skb(pi->sdu);
3110 break;
3111 }
3112
3113 pi->sdu_len = get_unaligned_le16(skb->data);
3114 skb_pull(skb, 2);
3115
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03003116 if (pi->sdu_len > pi->imtu) {
3117 err = -EMSGSIZE;
3118 break;
3119 }
3120
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003121 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
3122 if (!pi->sdu) {
3123 err = -ENOMEM;
3124 break;
3125 }
3126
3127 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3128
3129 pi->conn_state |= L2CAP_CONN_SAR_SDU;
3130 pi->partial_sdu_len = skb->len;
3131 err = 0;
3132 break;
3133
3134 case L2CAP_SDU_CONTINUE:
3135 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3136 break;
3137
3138 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3139
3140 pi->partial_sdu_len += skb->len;
3141 if (pi->partial_sdu_len > pi->sdu_len)
3142 kfree_skb(pi->sdu);
3143 else
3144 err = 0;
3145
3146 break;
3147
3148 case L2CAP_SDU_END:
3149 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
3150 break;
3151
3152 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
3153
3154 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
3155 pi->partial_sdu_len += skb->len;
3156
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003157 if (pi->partial_sdu_len > pi->imtu)
3158 goto drop;
3159
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003160 if (pi->partial_sdu_len == pi->sdu_len) {
3161 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
3162 err = sock_queue_rcv_skb(sk, _skb);
3163 if (err < 0)
3164 kfree_skb(_skb);
3165 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003166 err = 0;
3167
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03003168drop:
3169 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03003170 break;
3171 }
3172
3173 kfree_skb(skb);
3174 return err;
3175}
3176
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003177static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
3178{
3179 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003180 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003181
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003182 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003183 if (bt_cb(skb)->tx_seq != tx_seq)
3184 break;
3185
3186 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03003187 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003188 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003189 l2cap_pi(sk)->buffer_seq_srej =
3190 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003191 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003192 }
3193}
3194
3195static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
3196{
3197 struct l2cap_pinfo *pi = l2cap_pi(sk);
3198 struct srej_list *l, *tmp;
3199 u16 control;
3200
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03003201 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003202 if (l->tx_seq == tx_seq) {
3203 list_del(&l->list);
3204 kfree(l);
3205 return;
3206 }
3207 control = L2CAP_SUPER_SELECT_REJECT;
3208 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3209 l2cap_send_sframe(pi, control);
3210 list_del(&l->list);
3211 list_add_tail(&l->list, SREJ_LIST(sk));
3212 }
3213}
3214
3215static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3216{
3217 struct l2cap_pinfo *pi = l2cap_pi(sk);
3218 struct srej_list *new;
3219 u16 control;
3220
3221 while (tx_seq != pi->expected_tx_seq) {
3222 control = L2CAP_SUPER_SELECT_REJECT;
3223 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3224 l2cap_send_sframe(pi, control);
3225
3226 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003227 new->tx_seq = pi->expected_tx_seq;
3228 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003229 list_add_tail(&new->list, SREJ_LIST(sk));
3230 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03003231 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003232}
3233
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003234static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3235{
3236 struct l2cap_pinfo *pi = l2cap_pi(sk);
3237 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003238 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003239 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03003240 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003241 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003242 int err = 0;
3243
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003244 BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
3245 rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003246
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003247 if (L2CAP_CTRL_FINAL & rx_control &&
3248 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003249 del_timer(&pi->monitor_timer);
3250 if (pi->unacked_frames > 0)
3251 __mod_retrans_timer();
3252 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
3253 }
3254
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03003255 pi->expected_ack_seq = req_seq;
3256 l2cap_drop_acked_frames(sk);
3257
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003258 if (tx_seq == pi->expected_tx_seq)
3259 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003260
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003261 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3262 if (tx_seq_offset < 0)
3263 tx_seq_offset += 64;
3264
3265 /* invalid tx_seq */
3266 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003267 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003268 goto drop;
3269 }
3270
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003271 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
3272 goto drop;
3273
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003274 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3275 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003276
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003277 first = list_first_entry(SREJ_LIST(sk),
3278 struct srej_list, list);
3279 if (tx_seq == first->tx_seq) {
3280 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3281 l2cap_check_srej_gap(sk, tx_seq);
3282
3283 list_del(&first->list);
3284 kfree(first);
3285
3286 if (list_empty(SREJ_LIST(sk))) {
3287 pi->buffer_seq = pi->buffer_seq_srej;
3288 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666c2010-05-01 16:15:40 -03003289 l2cap_send_ack(pi);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003290 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003291 }
3292 } else {
3293 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003294
3295 /* duplicated tx_seq */
3296 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
3297 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003298
3299 list_for_each_entry(l, SREJ_LIST(sk), list) {
3300 if (l->tx_seq == tx_seq) {
3301 l2cap_resend_srejframe(sk, tx_seq);
3302 return 0;
3303 }
3304 }
3305 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003306 }
3307 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003308 expected_tx_seq_offset =
3309 (pi->expected_tx_seq - pi->buffer_seq) % 64;
3310 if (expected_tx_seq_offset < 0)
3311 expected_tx_seq_offset += 64;
3312
3313 /* duplicated tx_seq */
3314 if (tx_seq_offset < expected_tx_seq_offset)
3315 goto drop;
3316
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003317 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003318
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003319 BT_DBG("sk %p, Enter SREJ", sk);
3320
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003321 INIT_LIST_HEAD(SREJ_LIST(sk));
3322 pi->buffer_seq_srej = pi->buffer_seq;
3323
3324 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003325 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003326 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3327
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003328 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
3329
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003330 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003331
3332 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003333 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003334 return 0;
3335
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003336expected:
3337 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3338
3339 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003340 bt_cb(skb)->tx_seq = tx_seq;
3341 bt_cb(skb)->sar = sar;
3342 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003343 return 0;
3344 }
3345
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003346 err = l2cap_push_rx_skb(sk, skb, rx_control);
3347 if (err < 0)
3348 return 0;
3349
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003350 if (rx_control & L2CAP_CTRL_FINAL) {
3351 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3352 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003353 else
3354 l2cap_retransmit_frames(sk);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003355 }
3356
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003357 __mod_ack_timer();
3358
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003359 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
3360 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003361 l2cap_send_ack(pi);
3362
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003363 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003364
3365drop:
3366 kfree_skb(skb);
3367 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003368}
3369
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003370static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003371{
3372 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003373
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003374 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3375 rx_control);
3376
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003377 pi->expected_ack_seq = __get_reqseq(rx_control);
3378 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003379
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003380 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003381 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003382 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3383 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3384 (pi->unacked_frames > 0))
3385 __mod_retrans_timer();
3386
3387 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3388 l2cap_send_srejtail(sk);
3389 } else {
3390 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003391 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003392
3393 } else if (rx_control & L2CAP_CTRL_FINAL) {
3394 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003395
3396 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3397 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003398 else
3399 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003400
3401 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003402 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3403 (pi->unacked_frames > 0))
3404 __mod_retrans_timer();
3405
3406 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003407 if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003408 l2cap_send_ack(pi);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003409 else
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003410 l2cap_ertm_send(sk);
3411 }
3412}
3413
3414static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
3415{
3416 struct l2cap_pinfo *pi = l2cap_pi(sk);
3417 u8 tx_seq = __get_reqseq(rx_control);
3418
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003419 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3420
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003421 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3422
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03003423 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003424 l2cap_drop_acked_frames(sk);
3425
3426 if (rx_control & L2CAP_CTRL_FINAL) {
3427 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3428 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003429 else
3430 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003431 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003432 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003433
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03003434 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003435 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003436 }
3437}
3438static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
3439{
3440 struct l2cap_pinfo *pi = l2cap_pi(sk);
3441 u8 tx_seq = __get_reqseq(rx_control);
3442
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003443 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3444
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003445 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3446
3447 if (rx_control & L2CAP_CTRL_POLL) {
3448 pi->expected_ack_seq = tx_seq;
3449 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003450
3451 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003452 l2cap_retransmit_one_frame(sk, tx_seq);
3453
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003454 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003455
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003456 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3457 pi->srej_save_reqseq = tx_seq;
3458 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3459 }
3460 } else if (rx_control & L2CAP_CTRL_FINAL) {
3461 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
3462 pi->srej_save_reqseq == tx_seq)
3463 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
3464 else
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003465 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003466 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003467 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003468 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3469 pi->srej_save_reqseq = tx_seq;
3470 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3471 }
3472 }
3473}
3474
3475static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
3476{
3477 struct l2cap_pinfo *pi = l2cap_pi(sk);
3478 u8 tx_seq = __get_reqseq(rx_control);
3479
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003480 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3481
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003482 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
3483 pi->expected_ack_seq = tx_seq;
3484 l2cap_drop_acked_frames(sk);
3485
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003486 if (rx_control & L2CAP_CTRL_POLL)
3487 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
3488
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003489 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
3490 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003491 if (rx_control & L2CAP_CTRL_POLL)
3492 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003493 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003494 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003495
3496 if (rx_control & L2CAP_CTRL_POLL)
3497 l2cap_send_srejtail(sk);
3498 else
3499 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003500}
3501
3502static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3503{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003504 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3505
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003506 if (L2CAP_CTRL_FINAL & rx_control &&
3507 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003508 del_timer(&l2cap_pi(sk)->monitor_timer);
3509 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003510 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003511 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003512 }
3513
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003514 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3515 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003516 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003517 break;
3518
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003519 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003520 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003521 break;
3522
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003523 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003524 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003525 break;
3526
3527 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003528 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003529 break;
3530 }
3531
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003532 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003533 return 0;
3534}
3535
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003536static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3537{
3538 struct l2cap_pinfo *pi = l2cap_pi(sk);
3539 u16 control;
3540 u8 req_seq;
3541 int len, next_tx_seq_offset, req_seq_offset;
3542
3543 control = get_unaligned_le16(skb->data);
3544 skb_pull(skb, 2);
3545 len = skb->len;
3546
3547 /*
3548 * We can just drop the corrupted I-frame here.
3549 * Receiver will miss it and start proper recovery
3550 * procedures and ask retransmission.
3551 */
3552 if (l2cap_check_fcs(pi, skb))
3553 goto drop;
3554
3555 if (__is_sar_start(control) && __is_iframe(control))
3556 len -= 2;
3557
3558 if (pi->fcs == L2CAP_FCS_CRC16)
3559 len -= 2;
3560
3561 if (len > pi->mps) {
3562 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3563 goto drop;
3564 }
3565
3566 req_seq = __get_reqseq(control);
3567 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
3568 if (req_seq_offset < 0)
3569 req_seq_offset += 64;
3570
3571 next_tx_seq_offset =
3572 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
3573 if (next_tx_seq_offset < 0)
3574 next_tx_seq_offset += 64;
3575
3576 /* check for invalid req-seq */
3577 if (req_seq_offset > next_tx_seq_offset) {
3578 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3579 goto drop;
3580 }
3581
3582 if (__is_iframe(control)) {
3583 if (len < 0) {
3584 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3585 goto drop;
3586 }
3587
3588 l2cap_data_channel_iframe(sk, control, skb);
3589 } else {
3590 if (len != 0) {
3591 BT_ERR("%d", len);
3592 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3593 goto drop;
3594 }
3595
3596 l2cap_data_channel_sframe(sk, control, skb);
3597 }
3598
3599 return 0;
3600
3601drop:
3602 kfree_skb(skb);
3603 return 0;
3604}
3605
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3607{
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003608 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003610 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003611 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003612 u8 tx_seq;
3613 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003615 chan = l2cap_get_chan_by_scid(&conn->chan_list, cid);
3616 if (!chan) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617 BT_DBG("unknown cid 0x%4.4x", cid);
3618 goto drop;
3619 }
3620
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003621 sk = chan->sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003622 pi = l2cap_pi(sk);
3623
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624 BT_DBG("sk %p, len %d", sk, skb->len);
3625
3626 if (sk->sk_state != BT_CONNECTED)
3627 goto drop;
3628
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003629 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003630 case L2CAP_MODE_BASIC:
3631 /* If socket recv buffers overflows we drop data here
3632 * which is *bad* because L2CAP has to be reliable.
3633 * But we don't have any other choice. L2CAP doesn't
3634 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003636 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003637 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003639 if (!sock_queue_rcv_skb(sk, skb))
3640 goto done;
3641 break;
3642
3643 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003644 if (!sock_owned_by_user(sk)) {
3645 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003646 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003647 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003648 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003649 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003650
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003651 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003652
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003653 case L2CAP_MODE_STREAMING:
3654 control = get_unaligned_le16(skb->data);
3655 skb_pull(skb, 2);
3656 len = skb->len;
3657
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003658 if (l2cap_check_fcs(pi, skb))
3659 goto drop;
3660
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003661 if (__is_sar_start(control))
3662 len -= 2;
3663
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003664 if (pi->fcs == L2CAP_FCS_CRC16)
3665 len -= 2;
3666
Nathan Holstein51893f82010-06-09 15:46:25 -04003667 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003668 goto drop;
3669
3670 tx_seq = __get_txseq(control);
3671
3672 if (pi->expected_tx_seq == tx_seq)
3673 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3674 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03003675 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003676
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003677 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003678
3679 goto done;
3680
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003681 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003682 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003683 break;
3684 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685
3686drop:
3687 kfree_skb(skb);
3688
3689done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003690 if (sk)
3691 bh_unlock_sock(sk);
3692
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693 return 0;
3694}
3695
Al Viro8e036fc2007-07-29 00:16:36 -07003696static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697{
3698 struct sock *sk;
3699
3700 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3701 if (!sk)
3702 goto drop;
3703
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003704 bh_lock_sock(sk);
3705
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706 BT_DBG("sk %p, len %d", sk, skb->len);
3707
3708 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3709 goto drop;
3710
3711 if (l2cap_pi(sk)->imtu < skb->len)
3712 goto drop;
3713
3714 if (!sock_queue_rcv_skb(sk, skb))
3715 goto done;
3716
3717drop:
3718 kfree_skb(skb);
3719
3720done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003721 if (sk)
3722 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723 return 0;
3724}
3725
3726static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3727{
3728 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003729 u16 cid, len;
3730 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003731
3732 skb_pull(skb, L2CAP_HDR_SIZE);
3733 cid = __le16_to_cpu(lh->cid);
3734 len = __le16_to_cpu(lh->len);
3735
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003736 if (len != skb->len) {
3737 kfree_skb(skb);
3738 return;
3739 }
3740
Linus Torvalds1da177e2005-04-16 15:20:36 -07003741 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3742
3743 switch (cid) {
Claudio Takahasi3300d9a2011-02-11 19:28:54 -02003744 case L2CAP_CID_LE_SIGNALING:
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003745 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003746 l2cap_sig_channel(conn, skb);
3747 break;
3748
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003749 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003750 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751 skb_pull(skb, 2);
3752 l2cap_conless_channel(conn, psm, skb);
3753 break;
3754
3755 default:
3756 l2cap_data_channel(conn, cid, skb);
3757 break;
3758 }
3759}
3760
3761/* ---- L2CAP interface with lower layer (HCI) ---- */
3762
3763static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3764{
3765 int exact = 0, lm1 = 0, lm2 = 0;
3766 register struct sock *sk;
3767 struct hlist_node *node;
3768
3769 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003770 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771
3772 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3773
3774 /* Find listening sockets and check their link_mode */
3775 read_lock(&l2cap_sk_list.lock);
3776 sk_for_each(sk, node, &l2cap_sk_list.head) {
3777 if (sk->sk_state != BT_LISTEN)
3778 continue;
3779
3780 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003781 lm1 |= HCI_LM_ACCEPT;
3782 if (l2cap_pi(sk)->role_switch)
3783 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003785 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3786 lm2 |= HCI_LM_ACCEPT;
3787 if (l2cap_pi(sk)->role_switch)
3788 lm2 |= HCI_LM_MASTER;
3789 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790 }
3791 read_unlock(&l2cap_sk_list.lock);
3792
3793 return exact ? lm1 : lm2;
3794}
3795
3796static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3797{
Marcel Holtmann01394182006-07-03 10:02:46 +02003798 struct l2cap_conn *conn;
3799
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3801
Ville Tervoacd7d372011-02-10 22:38:49 -03003802 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003803 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804
3805 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806 conn = l2cap_conn_add(hcon, status);
3807 if (conn)
3808 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003809 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 l2cap_conn_del(hcon, bt_err(status));
3811
3812 return 0;
3813}
3814
Marcel Holtmann2950f212009-02-12 14:02:50 +01003815static int l2cap_disconn_ind(struct hci_conn *hcon)
3816{
3817 struct l2cap_conn *conn = hcon->l2cap_data;
3818
3819 BT_DBG("hcon %p", hcon);
3820
3821 if (hcon->type != ACL_LINK || !conn)
3822 return 0x13;
3823
3824 return conn->disc_reason;
3825}
3826
3827static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828{
3829 BT_DBG("hcon %p reason %d", hcon, reason);
3830
Ville Tervoacd7d372011-02-10 22:38:49 -03003831 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003832 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833
3834 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003835
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836 return 0;
3837}
3838
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003839static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3840{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003841 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003842 return;
3843
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003844 if (encrypt == 0x00) {
3845 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3846 l2cap_sock_clear_timer(sk);
3847 l2cap_sock_set_timer(sk, HZ * 5);
3848 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3849 __l2cap_sock_close(sk, ECONNREFUSED);
3850 } else {
3851 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3852 l2cap_sock_clear_timer(sk);
3853 }
3854}
3855
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003856static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857{
3858 struct l2cap_chan_list *l;
Marcel Holtmann40be4922008-07-14 20:13:50 +02003859 struct l2cap_conn *conn = hcon->l2cap_data;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003860 struct l2cap_chan *chan;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861
Marcel Holtmann01394182006-07-03 10:02:46 +02003862 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003864
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865 l = &conn->chan_list;
3866
3867 BT_DBG("conn %p", conn);
3868
3869 read_lock(&l->lock);
3870
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003871 for (chan = l->head; chan; chan = chan->next_c) {
3872 struct sock *sk = chan->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873 bh_lock_sock(sk);
3874
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003875 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3876 bh_unlock_sock(sk);
3877 continue;
3878 }
3879
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003880 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003881 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003882 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003883 bh_unlock_sock(sk);
3884 continue;
3885 }
3886
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003887 if (sk->sk_state == BT_CONNECT) {
3888 if (!status) {
3889 struct l2cap_conn_req req;
3890 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3891 req.psm = l2cap_pi(sk)->psm;
3892
3893 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003894 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003895
3896 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3897 L2CAP_CONN_REQ, sizeof(req), &req);
3898 } else {
3899 l2cap_sock_clear_timer(sk);
3900 l2cap_sock_set_timer(sk, HZ / 10);
3901 }
3902 } else if (sk->sk_state == BT_CONNECT2) {
3903 struct l2cap_conn_rsp rsp;
3904 __u16 result;
3905
3906 if (!status) {
3907 sk->sk_state = BT_CONFIG;
3908 result = L2CAP_CR_SUCCESS;
3909 } else {
3910 sk->sk_state = BT_DISCONN;
3911 l2cap_sock_set_timer(sk, HZ / 10);
3912 result = L2CAP_CR_SEC_BLOCK;
3913 }
3914
3915 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3916 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3917 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003918 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003919 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3920 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921 }
3922
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923 bh_unlock_sock(sk);
3924 }
3925
3926 read_unlock(&l->lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003927
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928 return 0;
3929}
3930
3931static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3932{
3933 struct l2cap_conn *conn = hcon->l2cap_data;
3934
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003935 if (!conn)
3936 conn = l2cap_conn_add(hcon, 0);
3937
3938 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939 goto drop;
3940
3941 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3942
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003943 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944 struct l2cap_hdr *hdr;
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003945 struct l2cap_chan *chan;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003946 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003947 int len;
3948
3949 if (conn->rx_len) {
3950 BT_ERR("Unexpected start frame (len %d)", skb->len);
3951 kfree_skb(conn->rx_skb);
3952 conn->rx_skb = NULL;
3953 conn->rx_len = 0;
3954 l2cap_conn_unreliable(conn, ECOMM);
3955 }
3956
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003957 /* Start fragment always begin with Basic L2CAP header */
3958 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959 BT_ERR("Frame is too short (len %d)", skb->len);
3960 l2cap_conn_unreliable(conn, ECOMM);
3961 goto drop;
3962 }
3963
3964 hdr = (struct l2cap_hdr *) skb->data;
3965 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003966 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967
3968 if (len == skb->len) {
3969 /* Complete frame received */
3970 l2cap_recv_frame(conn, skb);
3971 return 0;
3972 }
3973
3974 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3975
3976 if (skb->len > len) {
3977 BT_ERR("Frame is too long (len %d, expected len %d)",
3978 skb->len, len);
3979 l2cap_conn_unreliable(conn, ECOMM);
3980 goto drop;
3981 }
3982
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003983 chan = l2cap_get_chan_by_scid(&conn->chan_list, cid);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003984
Gustavo F. Padovan48454072011-03-25 00:22:30 -03003985 if (chan && chan->sk) {
3986 struct sock *sk = chan->sk;
3987
3988 if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
3989 BT_ERR("Frame exceeding recv MTU (len %d, "
3990 "MTU %d)", len,
3991 l2cap_pi(sk)->imtu);
3992 bh_unlock_sock(sk);
3993 l2cap_conn_unreliable(conn, ECOMM);
3994 goto drop;
3995 }
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003996 bh_unlock_sock(sk);
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003997 }
3998
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03004000 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
4001 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002 goto drop;
4003
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004004 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004005 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006 conn->rx_len = len - skb->len;
4007 } else {
4008 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
4009
4010 if (!conn->rx_len) {
4011 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
4012 l2cap_conn_unreliable(conn, ECOMM);
4013 goto drop;
4014 }
4015
4016 if (skb->len > conn->rx_len) {
4017 BT_ERR("Fragment is too long (len %d, expected %d)",
4018 skb->len, conn->rx_len);
4019 kfree_skb(conn->rx_skb);
4020 conn->rx_skb = NULL;
4021 conn->rx_len = 0;
4022 l2cap_conn_unreliable(conn, ECOMM);
4023 goto drop;
4024 }
4025
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03004026 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01004027 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028 conn->rx_len -= skb->len;
4029
4030 if (!conn->rx_len) {
4031 /* Complete frame received */
4032 l2cap_recv_frame(conn, conn->rx_skb);
4033 conn->rx_skb = NULL;
4034 }
4035 }
4036
4037drop:
4038 kfree_skb(skb);
4039 return 0;
4040}
4041
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004042static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043{
4044 struct sock *sk;
4045 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046
4047 read_lock_bh(&l2cap_sk_list.lock);
4048
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004049 sk_for_each(sk, node, &l2cap_sk_list.head) {
4050 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004052 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 +01004053 batostr(&bt_sk(sk)->src),
4054 batostr(&bt_sk(sk)->dst),
4055 sk->sk_state, __le16_to_cpu(pi->psm),
4056 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02004057 pi->imtu, pi->omtu, pi->sec_level,
4058 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004059 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004062
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004063 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064}
4065
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004066static int l2cap_debugfs_open(struct inode *inode, struct file *file)
4067{
4068 return single_open(file, l2cap_debugfs_show, inode->i_private);
4069}
4070
4071static const struct file_operations l2cap_debugfs_fops = {
4072 .open = l2cap_debugfs_open,
4073 .read = seq_read,
4074 .llseek = seq_lseek,
4075 .release = single_release,
4076};
4077
4078static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080static struct hci_proto l2cap_hci_proto = {
4081 .name = "L2CAP",
4082 .id = HCI_PROTO_L2CAP,
4083 .connect_ind = l2cap_connect_ind,
4084 .connect_cfm = l2cap_connect_cfm,
4085 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01004086 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01004087 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004088 .recv_acldata = l2cap_recv_acldata
4089};
4090
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004091int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092{
4093 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08004094
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004095 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096 if (err < 0)
4097 return err;
4098
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004099 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004100 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004101 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102 goto error;
4103 }
4104
4105 err = hci_register_proto(&l2cap_hci_proto);
4106 if (err < 0) {
4107 BT_ERR("L2CAP protocol registration failed");
4108 bt_sock_unregister(BTPROTO_L2CAP);
4109 goto error;
4110 }
4111
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004112 if (bt_debugfs) {
4113 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
4114 bt_debugfs, NULL, &l2cap_debugfs_fops);
4115 if (!l2cap_debugfs)
4116 BT_ERR("Failed to create L2CAP debug file");
4117 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119 return 0;
4120
4121error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04004122 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004123 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124 return err;
4125}
4126
Gustavo F. Padovan64274512011-02-07 20:08:52 -02004127void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01004129 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03004131 flush_workqueue(_busy_wq);
4132 destroy_workqueue(_busy_wq);
4133
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
4135 BT_ERR("L2CAP protocol unregistration failed");
4136
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02004137 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138}
4139
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03004140module_param(disable_ertm, bool, 0644);
4141MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");