blob: ba7f9da68998cbb2e6a8f505666444cd2128d744 [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. Padovandd135242010-07-13 11:57:12 -030058#define VERSION "2.15"
Marcel Holtmann44dd46d2009-05-02 19:09:01 -070059
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020060int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020061
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070062static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010063static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030065static struct workqueue_struct *_busy_wq;
66
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020067struct bt_sock_list l2cap_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070068 .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070069};
70
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030071static void l2cap_busy_work(struct work_struct *work);
72
Linus Torvalds1da177e2005-04-16 15:20:36 -070073static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
74 u8 code, u8 ident, u16 dlen, void *data);
75
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030076static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
77
Marcel Holtmann01394182006-07-03 10:02:46 +020078/* ---- L2CAP channels ---- */
79static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
80{
81 struct sock *s;
82 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
83 if (l2cap_pi(s)->dcid == cid)
84 break;
85 }
86 return s;
87}
88
89static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
90{
91 struct sock *s;
92 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
93 if (l2cap_pi(s)->scid == cid)
94 break;
95 }
96 return s;
97}
98
99/* Find channel with given SCID.
100 * Returns locked socket */
101static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
102{
103 struct sock *s;
104 read_lock(&l->lock);
105 s = __l2cap_get_chan_by_scid(l, cid);
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300106 if (s)
107 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200108 read_unlock(&l->lock);
109 return s;
110}
111
112static struct sock *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
113{
114 struct sock *s;
115 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
116 if (l2cap_pi(s)->ident == ident)
117 break;
118 }
119 return s;
120}
121
122static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
123{
124 struct sock *s;
125 read_lock(&l->lock);
126 s = __l2cap_get_chan_by_ident(l, ident);
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300127 if (s)
128 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200129 read_unlock(&l->lock);
130 return s;
131}
132
133static u16 l2cap_alloc_cid(struct l2cap_chan_list *l)
134{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300135 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200136
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300137 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300138 if (!__l2cap_get_chan_by_scid(l, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200139 return cid;
140 }
141
142 return 0;
143}
144
145static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct sock *sk)
146{
147 sock_hold(sk);
148
149 if (l->head)
150 l2cap_pi(l->head)->prev_c = sk;
151
152 l2cap_pi(sk)->next_c = l->head;
153 l2cap_pi(sk)->prev_c = NULL;
154 l->head = sk;
155}
156
157static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk)
158{
159 struct sock *next = l2cap_pi(sk)->next_c, *prev = l2cap_pi(sk)->prev_c;
160
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200161 write_lock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200162 if (sk == l->head)
163 l->head = next;
164
165 if (next)
166 l2cap_pi(next)->prev_c = prev;
167 if (prev)
168 l2cap_pi(prev)->next_c = next;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200169 write_unlock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200170
171 __sock_put(sk);
172}
173
174static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
175{
176 struct l2cap_chan_list *l = &conn->chan_list;
177
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300178 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
179 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200180
Marcel Holtmann2950f212009-02-12 14:02:50 +0100181 conn->disc_reason = 0x13;
182
Marcel Holtmann01394182006-07-03 10:02:46 +0200183 l2cap_pi(sk)->conn = conn;
184
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300185 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200186 /* Alloc CID for connection-oriented socket */
187 l2cap_pi(sk)->scid = l2cap_alloc_cid(l);
188 } else if (sk->sk_type == SOCK_DGRAM) {
189 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300190 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
191 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200192 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
193 } else {
194 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300195 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
196 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200197 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
198 }
199
200 __l2cap_chan_link(l, sk);
201
202 if (parent)
203 bt_accept_enqueue(parent, sk);
204}
205
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900206/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200207 * Must be called on the locked socket. */
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200208void l2cap_chan_del(struct sock *sk, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200209{
210 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
211 struct sock *parent = bt_sk(sk)->parent;
212
213 l2cap_sock_clear_timer(sk);
214
215 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
216
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900217 if (conn) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200218 /* Unlink from channel list */
219 l2cap_chan_unlink(&conn->chan_list, sk);
220 l2cap_pi(sk)->conn = NULL;
221 hci_conn_put(conn->hcon);
222 }
223
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200224 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200225 sock_set_flag(sk, SOCK_ZAPPED);
226
227 if (err)
228 sk->sk_err = err;
229
230 if (parent) {
231 bt_accept_unlink(sk);
232 parent->sk_data_ready(parent, 0);
233 } else
234 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300235
236 skb_queue_purge(TX_QUEUE(sk));
237
238 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
239 struct srej_list *l, *tmp;
240
241 del_timer(&l2cap_pi(sk)->retrans_timer);
242 del_timer(&l2cap_pi(sk)->monitor_timer);
243 del_timer(&l2cap_pi(sk)->ack_timer);
244
245 skb_queue_purge(SREJ_QUEUE(sk));
246 skb_queue_purge(BUSY_QUEUE(sk));
247
248 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
249 list_del(&l->list);
250 kfree(l);
251 }
252 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200253}
254
Johan Hedberg8556edd32011-01-19 12:06:50 +0530255static inline u8 l2cap_get_auth_type(struct sock *sk)
256{
257 if (sk->sk_type == SOCK_RAW) {
258 switch (l2cap_pi(sk)->sec_level) {
259 case BT_SECURITY_HIGH:
260 return HCI_AT_DEDICATED_BONDING_MITM;
261 case BT_SECURITY_MEDIUM:
262 return HCI_AT_DEDICATED_BONDING;
263 default:
264 return HCI_AT_NO_BONDING;
265 }
266 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
267 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
268 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
269
270 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
271 return HCI_AT_NO_BONDING_MITM;
272 else
273 return HCI_AT_NO_BONDING;
274 } else {
275 switch (l2cap_pi(sk)->sec_level) {
276 case BT_SECURITY_HIGH:
277 return HCI_AT_GENERAL_BONDING_MITM;
278 case BT_SECURITY_MEDIUM:
279 return HCI_AT_GENERAL_BONDING;
280 default:
281 return HCI_AT_NO_BONDING;
282 }
283 }
284}
285
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200286/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100287static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200288{
289 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100290 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200291
Johan Hedberg8556edd32011-01-19 12:06:50 +0530292 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100293
294 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
295 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200296}
297
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200298u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200299{
300 u8 id;
301
302 /* Get next available identificator.
303 * 1 - 128 are used by kernel.
304 * 129 - 199 are reserved.
305 * 200 - 254 are used by utilities like l2ping, etc.
306 */
307
308 spin_lock_bh(&conn->lock);
309
310 if (++conn->tx_ident > 128)
311 conn->tx_ident = 1;
312
313 id = conn->tx_ident;
314
315 spin_unlock_bh(&conn->lock);
316
317 return id;
318}
319
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200320void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200321{
322 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200323 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200324
325 BT_DBG("code 0x%2.2x", code);
326
327 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300328 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200329
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200330 if (lmp_no_flush_capable(conn->hcon->hdev))
331 flags = ACL_START_NO_FLUSH;
332 else
333 flags = ACL_START;
334
335 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200336}
337
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300338static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300339{
340 struct sk_buff *skb;
341 struct l2cap_hdr *lh;
342 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300343 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300344 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200345 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300346
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300347 if (sk->sk_state != BT_CONNECTED)
348 return;
349
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300350 if (pi->fcs == L2CAP_FCS_CRC16)
351 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300352
353 BT_DBG("pi %p, control 0x%2.2x", pi, control);
354
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300355 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300356 control |= L2CAP_CTRL_FRAME_TYPE;
357
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300358 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
359 control |= L2CAP_CTRL_FINAL;
360 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
361 }
362
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300363 if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
364 control |= L2CAP_CTRL_POLL;
365 pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
366 }
367
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300368 skb = bt_skb_alloc(count, GFP_ATOMIC);
369 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300370 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300371
372 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300373 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300374 lh->cid = cpu_to_le16(pi->dcid);
375 put_unaligned_le16(control, skb_put(skb, 2));
376
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300377 if (pi->fcs == L2CAP_FCS_CRC16) {
378 u16 fcs = crc16(0, (u8 *)lh, count - 2);
379 put_unaligned_le16(fcs, skb_put(skb, 2));
380 }
381
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200382 if (lmp_no_flush_capable(conn->hcon->hdev))
383 flags = ACL_START_NO_FLUSH;
384 else
385 flags = ACL_START;
386
387 hci_send_acl(pi->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300388}
389
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300390static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300391{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300392 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300393 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300394 pi->conn_state |= L2CAP_CONN_RNR_SENT;
395 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300396 control |= L2CAP_SUPER_RCV_READY;
397
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300398 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
399
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300400 l2cap_send_sframe(pi, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300401}
402
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300403static inline int __l2cap_no_conn_pending(struct sock *sk)
404{
405 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
406}
407
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200408static void l2cap_do_start(struct sock *sk)
409{
410 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
411
412 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100413 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
414 return;
415
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300416 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200417 struct l2cap_conn_req req;
418 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
419 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200420
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200421 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300422 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200423
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200424 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200425 L2CAP_CONN_REQ, sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200426 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200427 } else {
428 struct l2cap_info_req req;
429 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
430
431 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
432 conn->info_ident = l2cap_get_ident(conn);
433
434 mod_timer(&conn->info_timer, jiffies +
435 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
436
437 l2cap_send_cmd(conn, conn->info_ident,
438 L2CAP_INFO_REQ, sizeof(req), &req);
439 }
440}
441
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300442static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
443{
444 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300445 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300446 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
447
448 switch (mode) {
449 case L2CAP_MODE_ERTM:
450 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
451 case L2CAP_MODE_STREAMING:
452 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
453 default:
454 return 0x00;
455 }
456}
457
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200458void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300459{
460 struct l2cap_disconn_req req;
461
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300462 if (!conn)
463 return;
464
465 skb_queue_purge(TX_QUEUE(sk));
466
467 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
468 del_timer(&l2cap_pi(sk)->retrans_timer);
469 del_timer(&l2cap_pi(sk)->monitor_timer);
470 del_timer(&l2cap_pi(sk)->ack_timer);
471 }
472
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300473 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
474 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
475 l2cap_send_cmd(conn, l2cap_get_ident(conn),
476 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300477
478 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300479 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300480}
481
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200483static void l2cap_conn_start(struct l2cap_conn *conn)
484{
485 struct l2cap_chan_list *l = &conn->chan_list;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300486 struct sock_del_list del, *tmp1, *tmp2;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200487 struct sock *sk;
488
489 BT_DBG("conn %p", conn);
490
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300491 INIT_LIST_HEAD(&del.list);
492
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200493 read_lock(&l->lock);
494
495 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
496 bh_lock_sock(sk);
497
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300498 if (sk->sk_type != SOCK_SEQPACKET &&
499 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200500 bh_unlock_sock(sk);
501 continue;
502 }
503
504 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300505 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300506
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300507 if (!l2cap_check_security(sk) ||
508 !__l2cap_no_conn_pending(sk)) {
509 bh_unlock_sock(sk);
510 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200511 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300512
513 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
514 conn->feat_mask)
515 && l2cap_pi(sk)->conf_state &
516 L2CAP_CONF_STATE2_DEVICE) {
517 tmp1 = kzalloc(sizeof(struct sock_del_list),
518 GFP_ATOMIC);
519 tmp1->sk = sk;
520 list_add_tail(&tmp1->list, &del.list);
521 bh_unlock_sock(sk);
522 continue;
523 }
524
525 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
526 req.psm = l2cap_pi(sk)->psm;
527
528 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
529 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
530
531 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
532 L2CAP_CONN_REQ, sizeof(req), &req);
533
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200534 } else if (sk->sk_state == BT_CONNECT2) {
535 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300536 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200537 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
538 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
539
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100540 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100541 if (bt_sk(sk)->defer_setup) {
542 struct sock *parent = bt_sk(sk)->parent;
543 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
544 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
545 parent->sk_data_ready(parent, 0);
546
547 } else {
548 sk->sk_state = BT_CONFIG;
549 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
550 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
551 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200552 } else {
553 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
554 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
555 }
556
557 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
558 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300559
560 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
561 rsp.result != L2CAP_CR_SUCCESS) {
562 bh_unlock_sock(sk);
563 continue;
564 }
565
566 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
567 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
568 l2cap_build_conf_req(sk, buf), buf);
569 l2cap_pi(sk)->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200570 }
571
572 bh_unlock_sock(sk);
573 }
574
575 read_unlock(&l->lock);
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300576
577 list_for_each_entry_safe(tmp1, tmp2, &del.list, list) {
578 bh_lock_sock(tmp1->sk);
579 __l2cap_sock_close(tmp1->sk, ECONNRESET);
580 bh_unlock_sock(tmp1->sk);
581 list_del(&tmp1->list);
582 kfree(tmp1);
583 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200584}
585
586static void l2cap_conn_ready(struct l2cap_conn *conn)
587{
588 struct l2cap_chan_list *l = &conn->chan_list;
589 struct sock *sk;
590
591 BT_DBG("conn %p", conn);
592
593 read_lock(&l->lock);
594
595 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
596 bh_lock_sock(sk);
597
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300598 if (sk->sk_type != SOCK_SEQPACKET &&
599 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200600 l2cap_sock_clear_timer(sk);
601 sk->sk_state = BT_CONNECTED;
602 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200603 } else if (sk->sk_state == BT_CONNECT)
604 l2cap_do_start(sk);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200605
606 bh_unlock_sock(sk);
607 }
608
609 read_unlock(&l->lock);
610}
611
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200612/* Notify sockets that we cannot guaranty reliability anymore */
613static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
614{
615 struct l2cap_chan_list *l = &conn->chan_list;
616 struct sock *sk;
617
618 BT_DBG("conn %p", conn);
619
620 read_lock(&l->lock);
621
622 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100623 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200624 sk->sk_err = err;
625 }
626
627 read_unlock(&l->lock);
628}
629
630static void l2cap_info_timeout(unsigned long arg)
631{
632 struct l2cap_conn *conn = (void *) arg;
633
Marcel Holtmann984947d2009-02-06 23:35:19 +0100634 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100635 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100636
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200637 l2cap_conn_start(conn);
638}
639
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
641{
Marcel Holtmann01394182006-07-03 10:02:46 +0200642 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643
Marcel Holtmann01394182006-07-03 10:02:46 +0200644 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 return conn;
646
Marcel Holtmann01394182006-07-03 10:02:46 +0200647 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
648 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650
651 hcon->l2cap_data = conn;
652 conn->hcon = hcon;
653
Marcel Holtmann01394182006-07-03 10:02:46 +0200654 BT_DBG("hcon %p conn %p", hcon, conn);
655
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 conn->mtu = hcon->hdev->acl_mtu;
657 conn->src = &hcon->hdev->bdaddr;
658 conn->dst = &hcon->dst;
659
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200660 conn->feat_mask = 0;
661
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 spin_lock_init(&conn->lock);
663 rwlock_init(&conn->chan_list.lock);
664
Dave Young45054dc2009-10-18 20:28:30 +0000665 setup_timer(&conn->info_timer, l2cap_info_timeout,
666 (unsigned long) conn);
667
Marcel Holtmann2950f212009-02-12 14:02:50 +0100668 conn->disc_reason = 0x13;
669
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 return conn;
671}
672
Marcel Holtmann01394182006-07-03 10:02:46 +0200673static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674{
Marcel Holtmann01394182006-07-03 10:02:46 +0200675 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 struct sock *sk;
677
Marcel Holtmann01394182006-07-03 10:02:46 +0200678 if (!conn)
679 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680
681 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
682
Wei Yongjun7585b972009-02-25 18:29:52 +0800683 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684
685 /* Kill channels */
686 while ((sk = conn->chan_list.head)) {
687 bh_lock_sock(sk);
688 l2cap_chan_del(sk, err);
689 bh_unlock_sock(sk);
690 l2cap_sock_kill(sk);
691 }
692
Dave Young8e8440f2008-03-03 12:18:55 -0800693 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
694 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800695
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 hcon->l2cap_data = NULL;
697 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698}
699
700static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
701{
702 struct l2cap_chan_list *l = &conn->chan_list;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200703 write_lock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 __l2cap_chan_add(conn, sk, parent);
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200705 write_unlock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706}
707
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
710/* Find socket with psm and source bdaddr.
711 * Returns closest match.
712 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000713static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714{
715 struct sock *sk = NULL, *sk1 = NULL;
716 struct hlist_node *node;
717
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000718 read_lock(&l2cap_sk_list.lock);
719
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 sk_for_each(sk, node, &l2cap_sk_list.head) {
721 if (state && sk->sk_state != state)
722 continue;
723
724 if (l2cap_pi(sk)->psm == psm) {
725 /* Exact match. */
726 if (!bacmp(&bt_sk(sk)->src, src))
727 break;
728
729 /* Closest match */
730 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
731 sk1 = sk;
732 }
733 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000736
737 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738}
739
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200740int l2cap_do_connect(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741{
742 bdaddr_t *src = &bt_sk(sk)->src;
743 bdaddr_t *dst = &bt_sk(sk)->dst;
744 struct l2cap_conn *conn;
745 struct hci_conn *hcon;
746 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200747 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200748 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100750 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
751 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300753 hdev = hci_get_route(dst, src);
754 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 return -EHOSTUNREACH;
756
757 hci_dev_lock_bh(hdev);
758
759 err = -ENOMEM;
760
Johan Hedberg8556edd32011-01-19 12:06:50 +0530761 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200762
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100763 hcon = hci_connect(hdev, ACL_LINK, dst,
764 l2cap_pi(sk)->sec_level, auth_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 if (!hcon)
766 goto done;
767
768 conn = l2cap_conn_add(hcon, 0);
769 if (!conn) {
770 hci_conn_put(hcon);
771 goto done;
772 }
773
774 err = 0;
775
776 /* Update source addr of the socket */
777 bacpy(src, conn->src);
778
779 l2cap_chan_add(conn, sk, NULL);
780
781 sk->sk_state = BT_CONNECT;
782 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
783
784 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300785 if (sk->sk_type != SOCK_SEQPACKET &&
786 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530788 if (l2cap_check_security(sk))
789 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200790 } else
791 l2cap_do_start(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 }
793
794done:
795 hci_dev_unlock_bh(hdev);
796 hci_dev_put(hdev);
797 return err;
798}
799
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200800int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300801{
802 DECLARE_WAITQUEUE(wait, current);
803 int err = 0;
804 int timeo = HZ/5;
805
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200806 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300807 while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
808 set_current_state(TASK_INTERRUPTIBLE);
809
810 if (!timeo)
811 timeo = HZ/5;
812
813 if (signal_pending(current)) {
814 err = sock_intr_errno(timeo);
815 break;
816 }
817
818 release_sock(sk);
819 timeo = schedule_timeout(timeo);
820 lock_sock(sk);
821
822 err = sock_error(sk);
823 if (err)
824 break;
825 }
826 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200827 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300828 return err;
829}
830
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300831static void l2cap_monitor_timeout(unsigned long arg)
832{
833 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300834
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300835 BT_DBG("sk %p", sk);
836
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300837 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300838 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300839 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200840 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300841 return;
842 }
843
844 l2cap_pi(sk)->retry_count++;
845 __mod_monitor_timer();
846
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -0300847 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300848 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300849}
850
851static void l2cap_retrans_timeout(unsigned long arg)
852{
853 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300854
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300855 BT_DBG("sk %p", sk);
856
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300857 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300858 l2cap_pi(sk)->retry_count = 1;
859 __mod_monitor_timer();
860
861 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
862
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -0300863 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300864 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300865}
866
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300867static void l2cap_drop_acked_frames(struct sock *sk)
868{
869 struct sk_buff *skb;
870
Gustavo F. Padovan812e7372010-05-01 16:15:42 -0300871 while ((skb = skb_peek(TX_QUEUE(sk))) &&
872 l2cap_pi(sk)->unacked_frames) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300873 if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
874 break;
875
876 skb = skb_dequeue(TX_QUEUE(sk));
877 kfree_skb(skb);
878
879 l2cap_pi(sk)->unacked_frames--;
880 }
881
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300882 if (!l2cap_pi(sk)->unacked_frames)
883 del_timer(&l2cap_pi(sk)->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300884}
885
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200886void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300887{
888 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200889 struct hci_conn *hcon = pi->conn->hcon;
890 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300891
892 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
893
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200894 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
895 flags = ACL_START_NO_FLUSH;
896 else
897 flags = ACL_START;
898
899 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300900}
901
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200902void l2cap_streaming_send(struct sock *sk)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300903{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -0300904 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300905 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300906 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300907
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -0300908 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
909 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300910 control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -0300911 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300912
Gustavo F. Padovane8235c62010-05-01 16:15:36 -0300913 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -0300914 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
915 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300916 }
917
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -0300918 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300919
920 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300921 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300922}
923
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -0300924static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300925{
926 struct l2cap_pinfo *pi = l2cap_pi(sk);
927 struct sk_buff *skb, *tx_skb;
928 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300929
930 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300931 if (!skb)
932 return;
933
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300934 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300935 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300936 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300937
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300938 if (skb_queue_is_last(TX_QUEUE(sk), skb))
939 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300940
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300941 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300942
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300943 if (pi->remote_max_tx &&
944 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300945 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300946 return;
947 }
948
949 tx_skb = skb_clone(skb, GFP_ATOMIC);
950 bt_cb(skb)->retries++;
951 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -0300952
953 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
954 control |= L2CAP_CTRL_FINAL;
955 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
956 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -0300957
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300958 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
959 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -0300960
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300961 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
962
963 if (pi->fcs == L2CAP_FCS_CRC16) {
964 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
965 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
966 }
967
968 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300969}
970
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200971int l2cap_ertm_send(struct sock *sk)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300972{
973 struct sk_buff *skb, *tx_skb;
974 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300975 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300976 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300977
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300978 if (sk->sk_state != BT_CONNECTED)
979 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300980
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -0300981 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300982
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300983 if (pi->remote_max_tx &&
984 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300985 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300986 break;
987 }
988
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +0200989 tx_skb = skb_clone(skb, GFP_ATOMIC);
990
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300991 bt_cb(skb)->retries++;
992
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300993 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -0300994 control &= L2CAP_CTRL_SAR;
995
Gustavo F. Padovand5392c82010-05-01 16:15:36 -0300996 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
997 control |= L2CAP_CTRL_FINAL;
998 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
999 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001000 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001001 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1002 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1003
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001004
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001005 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001006 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1007 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1008 }
1009
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001010 l2cap_do_send(sk, tx_skb);
1011
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001012 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001013
1014 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1015 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1016
1017 pi->unacked_frames++;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001018 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001019
1020 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1021 sk->sk_send_head = NULL;
1022 else
1023 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001024
1025 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001026 }
1027
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001028 return nsent;
1029}
1030
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001031static int l2cap_retransmit_frames(struct sock *sk)
1032{
1033 struct l2cap_pinfo *pi = l2cap_pi(sk);
1034 int ret;
1035
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001036 if (!skb_queue_empty(TX_QUEUE(sk)))
1037 sk->sk_send_head = TX_QUEUE(sk)->next;
1038
1039 pi->next_tx_seq = pi->expected_ack_seq;
1040 ret = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001041 return ret;
1042}
1043
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001044static void l2cap_send_ack(struct l2cap_pinfo *pi)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001045{
1046 struct sock *sk = (struct sock *)pi;
1047 u16 control = 0;
1048
1049 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1050
1051 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1052 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001053 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001054 l2cap_send_sframe(pi, control);
1055 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001056 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001057
Gustavo F. Padovane0f66212010-06-21 18:50:49 -03001058 if (l2cap_ertm_send(sk) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001059 return;
1060
1061 control |= L2CAP_SUPER_RCV_READY;
1062 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001063}
1064
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001065static void l2cap_send_srejtail(struct sock *sk)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001066{
1067 struct srej_list *tail;
1068 u16 control;
1069
1070 control = L2CAP_SUPER_SELECT_REJECT;
1071 control |= L2CAP_CTRL_FINAL;
1072
1073 tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
1074 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1075
1076 l2cap_send_sframe(l2cap_pi(sk), control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001077}
1078
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001079static 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 -07001080{
1081 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001082 struct sk_buff **frag;
1083 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001085 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001086 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
1088 sent += count;
1089 len -= count;
1090
1091 /* Continuation fragments (no L2CAP header) */
1092 frag = &skb_shinfo(skb)->frag_list;
1093 while (len) {
1094 count = min_t(unsigned int, conn->mtu, len);
1095
1096 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1097 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001098 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001099 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1100 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101
1102 sent += count;
1103 len -= count;
1104
1105 frag = &(*frag)->next;
1106 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107
1108 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001109}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001111struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001112{
1113 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1114 struct sk_buff *skb;
1115 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1116 struct l2cap_hdr *lh;
1117
1118 BT_DBG("sk %p len %d", sk, (int)len);
1119
1120 count = min_t(unsigned int, (conn->mtu - hlen), len);
1121 skb = bt_skb_send_alloc(sk, count + hlen,
1122 msg->msg_flags & MSG_DONTWAIT, &err);
1123 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001124 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001125
1126 /* Create L2CAP header */
1127 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1128 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1129 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1130 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1131
1132 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1133 if (unlikely(err < 0)) {
1134 kfree_skb(skb);
1135 return ERR_PTR(err);
1136 }
1137 return skb;
1138}
1139
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001140struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001141{
1142 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1143 struct sk_buff *skb;
1144 int err, count, hlen = L2CAP_HDR_SIZE;
1145 struct l2cap_hdr *lh;
1146
1147 BT_DBG("sk %p len %d", sk, (int)len);
1148
1149 count = min_t(unsigned int, (conn->mtu - hlen), len);
1150 skb = bt_skb_send_alloc(sk, count + hlen,
1151 msg->msg_flags & MSG_DONTWAIT, &err);
1152 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001153 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001154
1155 /* Create L2CAP header */
1156 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1157 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1158 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1159
1160 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1161 if (unlikely(err < 0)) {
1162 kfree_skb(skb);
1163 return ERR_PTR(err);
1164 }
1165 return skb;
1166}
1167
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001168struct 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 -03001169{
1170 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1171 struct sk_buff *skb;
1172 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1173 struct l2cap_hdr *lh;
1174
1175 BT_DBG("sk %p len %d", sk, (int)len);
1176
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001177 if (!conn)
1178 return ERR_PTR(-ENOTCONN);
1179
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001180 if (sdulen)
1181 hlen += 2;
1182
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001183 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1184 hlen += 2;
1185
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001186 count = min_t(unsigned int, (conn->mtu - hlen), len);
1187 skb = bt_skb_send_alloc(sk, count + hlen,
1188 msg->msg_flags & MSG_DONTWAIT, &err);
1189 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001190 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001191
1192 /* Create L2CAP header */
1193 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1194 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1195 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1196 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001197 if (sdulen)
1198 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001199
1200 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1201 if (unlikely(err < 0)) {
1202 kfree_skb(skb);
1203 return ERR_PTR(err);
1204 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001205
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001206 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1207 put_unaligned_le16(0, skb_put(skb, 2));
1208
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001209 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001210 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211}
1212
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001213int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001214{
1215 struct l2cap_pinfo *pi = l2cap_pi(sk);
1216 struct sk_buff *skb;
1217 struct sk_buff_head sar_queue;
1218 u16 control;
1219 size_t size = 0;
1220
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001221 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001222 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001223 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001224 if (IS_ERR(skb))
1225 return PTR_ERR(skb);
1226
1227 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001228 len -= pi->remote_mps;
1229 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001230
1231 while (len > 0) {
1232 size_t buflen;
1233
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001234 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001235 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001236 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001237 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001238 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001239 buflen = len;
1240 }
1241
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001242 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001243 if (IS_ERR(skb)) {
1244 skb_queue_purge(&sar_queue);
1245 return PTR_ERR(skb);
1246 }
1247
1248 __skb_queue_tail(&sar_queue, skb);
1249 len -= buflen;
1250 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001251 }
1252 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1253 if (sk->sk_send_head == NULL)
1254 sk->sk_send_head = sar_queue.next;
1255
1256 return size;
1257}
1258
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259static void l2cap_chan_ready(struct sock *sk)
1260{
1261 struct sock *parent = bt_sk(sk)->parent;
1262
1263 BT_DBG("sk %p, parent %p", sk, parent);
1264
1265 l2cap_pi(sk)->conf_state = 0;
1266 l2cap_sock_clear_timer(sk);
1267
1268 if (!parent) {
1269 /* Outgoing channel.
1270 * Wake up socket sleeping on connect.
1271 */
1272 sk->sk_state = BT_CONNECTED;
1273 sk->sk_state_change(sk);
1274 } else {
1275 /* Incoming channel.
1276 * Wake up socket sleeping on accept.
1277 */
1278 parent->sk_data_ready(parent, 0);
1279 }
1280}
1281
1282/* Copy frame to all raw sockets on that connection */
1283static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1284{
1285 struct l2cap_chan_list *l = &conn->chan_list;
1286 struct sk_buff *nskb;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001287 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288
1289 BT_DBG("conn %p", conn);
1290
1291 read_lock(&l->lock);
1292 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
1293 if (sk->sk_type != SOCK_RAW)
1294 continue;
1295
1296 /* Don't send frame to the socket it came from */
1297 if (skb->sk == sk)
1298 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001299 nskb = skb_clone(skb, GFP_ATOMIC);
1300 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 continue;
1302
1303 if (sock_queue_rcv_skb(sk, nskb))
1304 kfree_skb(nskb);
1305 }
1306 read_unlock(&l->lock);
1307}
1308
1309/* ---- L2CAP signalling commands ---- */
1310static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1311 u8 code, u8 ident, u16 dlen, void *data)
1312{
1313 struct sk_buff *skb, **frag;
1314 struct l2cap_cmd_hdr *cmd;
1315 struct l2cap_hdr *lh;
1316 int len, count;
1317
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001318 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1319 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320
1321 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1322 count = min_t(unsigned int, conn->mtu, len);
1323
1324 skb = bt_skb_alloc(count, GFP_ATOMIC);
1325 if (!skb)
1326 return NULL;
1327
1328 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001329 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03001330 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331
1332 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1333 cmd->code = code;
1334 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001335 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336
1337 if (dlen) {
1338 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1339 memcpy(skb_put(skb, count), data, count);
1340 data += count;
1341 }
1342
1343 len -= skb->len;
1344
1345 /* Continuation fragments (no L2CAP header) */
1346 frag = &skb_shinfo(skb)->frag_list;
1347 while (len) {
1348 count = min_t(unsigned int, conn->mtu, len);
1349
1350 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1351 if (!*frag)
1352 goto fail;
1353
1354 memcpy(skb_put(*frag, count), data, count);
1355
1356 len -= count;
1357 data += count;
1358
1359 frag = &(*frag)->next;
1360 }
1361
1362 return skb;
1363
1364fail:
1365 kfree_skb(skb);
1366 return NULL;
1367}
1368
1369static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1370{
1371 struct l2cap_conf_opt *opt = *ptr;
1372 int len;
1373
1374 len = L2CAP_CONF_OPT_SIZE + opt->len;
1375 *ptr += len;
1376
1377 *type = opt->type;
1378 *olen = opt->len;
1379
1380 switch (opt->len) {
1381 case 1:
1382 *val = *((u8 *) opt->val);
1383 break;
1384
1385 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001386 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 break;
1388
1389 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001390 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 break;
1392
1393 default:
1394 *val = (unsigned long) opt->val;
1395 break;
1396 }
1397
1398 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1399 return len;
1400}
1401
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1403{
1404 struct l2cap_conf_opt *opt = *ptr;
1405
1406 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1407
1408 opt->type = type;
1409 opt->len = len;
1410
1411 switch (len) {
1412 case 1:
1413 *((u8 *) opt->val) = val;
1414 break;
1415
1416 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001417 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 break;
1419
1420 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001421 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 break;
1423
1424 default:
1425 memcpy(opt->val, (void *) val, len);
1426 break;
1427 }
1428
1429 *ptr += L2CAP_CONF_OPT_SIZE + len;
1430}
1431
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001432static void l2cap_ack_timeout(unsigned long arg)
1433{
1434 struct sock *sk = (void *) arg;
1435
1436 bh_lock_sock(sk);
1437 l2cap_send_ack(l2cap_pi(sk));
1438 bh_unlock_sock(sk);
1439}
1440
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001441static inline void l2cap_ertm_init(struct sock *sk)
1442{
1443 l2cap_pi(sk)->expected_ack_seq = 0;
1444 l2cap_pi(sk)->unacked_frames = 0;
1445 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03001446 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001447 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001448
1449 setup_timer(&l2cap_pi(sk)->retrans_timer,
1450 l2cap_retrans_timeout, (unsigned long) sk);
1451 setup_timer(&l2cap_pi(sk)->monitor_timer,
1452 l2cap_monitor_timeout, (unsigned long) sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001453 setup_timer(&l2cap_pi(sk)->ack_timer,
1454 l2cap_ack_timeout, (unsigned long) sk);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001455
1456 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001457 __skb_queue_head_init(BUSY_QUEUE(sk));
1458
1459 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001460
1461 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001462}
1463
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001464static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1465{
1466 switch (mode) {
1467 case L2CAP_MODE_STREAMING:
1468 case L2CAP_MODE_ERTM:
1469 if (l2cap_mode_supported(mode, remote_feat_mask))
1470 return mode;
1471 /* fall through */
1472 default:
1473 return L2CAP_MODE_BASIC;
1474 }
1475}
1476
Gustavo F. Padovan68983252011-02-04 03:02:31 -02001477int l2cap_build_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478{
1479 struct l2cap_pinfo *pi = l2cap_pi(sk);
1480 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001481 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 void *ptr = req->data;
1483
1484 BT_DBG("sk %p", sk);
1485
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001486 if (pi->num_conf_req || pi->num_conf_rsp)
1487 goto done;
1488
1489 switch (pi->mode) {
1490 case L2CAP_MODE_STREAMING:
1491 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001492 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001493 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001494
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001495 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001496 default:
1497 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1498 break;
1499 }
1500
1501done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001502 if (pi->imtu != L2CAP_DEFAULT_MTU)
1503 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1504
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001505 switch (pi->mode) {
1506 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001507 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1508 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1509 break;
1510
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001511 rfc.mode = L2CAP_MODE_BASIC;
1512 rfc.txwin_size = 0;
1513 rfc.max_transmit = 0;
1514 rfc.retrans_timeout = 0;
1515 rfc.monitor_timeout = 0;
1516 rfc.max_pdu_size = 0;
1517
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001518 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1519 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001520 break;
1521
1522 case L2CAP_MODE_ERTM:
1523 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001524 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001525 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001526 rfc.retrans_timeout = 0;
1527 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001528 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001529 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001530 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001531
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001532 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1533 (unsigned long) &rfc);
1534
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001535 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1536 break;
1537
1538 if (pi->fcs == L2CAP_FCS_NONE ||
1539 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1540 pi->fcs = L2CAP_FCS_NONE;
1541 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1542 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001543 break;
1544
1545 case L2CAP_MODE_STREAMING:
1546 rfc.mode = L2CAP_MODE_STREAMING;
1547 rfc.txwin_size = 0;
1548 rfc.max_transmit = 0;
1549 rfc.retrans_timeout = 0;
1550 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001551 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001552 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001553 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001554
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001555 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1556 (unsigned long) &rfc);
1557
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001558 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1559 break;
1560
1561 if (pi->fcs == L2CAP_FCS_NONE ||
1562 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1563 pi->fcs = L2CAP_FCS_NONE;
1564 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1565 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001566 break;
1567 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568
1569 /* FIXME: Need actual value of the flush timeout */
1570 //if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
1571 // l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to);
1572
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001573 req->dcid = cpu_to_le16(pi->dcid);
1574 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575
1576 return ptr - data;
1577}
1578
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001579static int l2cap_parse_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580{
1581 struct l2cap_pinfo *pi = l2cap_pi(sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001582 struct l2cap_conf_rsp *rsp = data;
1583 void *ptr = rsp->data;
1584 void *req = pi->conf_req;
1585 int len = pi->conf_len;
1586 int type, hint, olen;
1587 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001588 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001589 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001590 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001592 BT_DBG("sk %p", sk);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001593
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001594 while (len >= L2CAP_CONF_OPT_SIZE) {
1595 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001597 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001598 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001599
1600 switch (type) {
1601 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001602 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001603 break;
1604
1605 case L2CAP_CONF_FLUSH_TO:
1606 pi->flush_to = val;
1607 break;
1608
1609 case L2CAP_CONF_QOS:
1610 break;
1611
Marcel Holtmann6464f352007-10-20 13:39:51 +02001612 case L2CAP_CONF_RFC:
1613 if (olen == sizeof(rfc))
1614 memcpy(&rfc, (void *) val, olen);
1615 break;
1616
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001617 case L2CAP_CONF_FCS:
1618 if (val == L2CAP_FCS_NONE)
1619 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1620
1621 break;
1622
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001623 default:
1624 if (hint)
1625 break;
1626
1627 result = L2CAP_CONF_UNKNOWN;
1628 *((u8 *) ptr++) = type;
1629 break;
1630 }
1631 }
1632
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001633 if (pi->num_conf_rsp || pi->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001634 goto done;
1635
1636 switch (pi->mode) {
1637 case L2CAP_MODE_STREAMING:
1638 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001639 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1640 pi->mode = l2cap_select_mode(rfc.mode,
1641 pi->conn->feat_mask);
1642 break;
1643 }
1644
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001645 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001646 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001647
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001648 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001649 }
1650
1651done:
1652 if (pi->mode != rfc.mode) {
1653 result = L2CAP_CONF_UNACCEPT;
1654 rfc.mode = pi->mode;
1655
1656 if (pi->num_conf_rsp == 1)
1657 return -ECONNREFUSED;
1658
1659 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1660 sizeof(rfc), (unsigned long) &rfc);
1661 }
1662
1663
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001664 if (result == L2CAP_CONF_SUCCESS) {
1665 /* Configure output options and let the other side know
1666 * which ones we don't like. */
1667
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001668 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1669 result = L2CAP_CONF_UNACCEPT;
1670 else {
1671 pi->omtu = mtu;
1672 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1673 }
1674 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001675
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001676 switch (rfc.mode) {
1677 case L2CAP_MODE_BASIC:
1678 pi->fcs = L2CAP_FCS_NONE;
1679 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1680 break;
1681
1682 case L2CAP_MODE_ERTM:
1683 pi->remote_tx_win = rfc.txwin_size;
1684 pi->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001685
1686 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1687 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001688
1689 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001690
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001691 rfc.retrans_timeout =
1692 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1693 rfc.monitor_timeout =
1694 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001695
1696 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001697
1698 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1699 sizeof(rfc), (unsigned long) &rfc);
1700
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001701 break;
1702
1703 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001704 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1705 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001706
1707 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001708
1709 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001710
1711 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1712 sizeof(rfc), (unsigned long) &rfc);
1713
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001714 break;
1715
1716 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001717 result = L2CAP_CONF_UNACCEPT;
1718
1719 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001720 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001721 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001722
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001723 if (result == L2CAP_CONF_SUCCESS)
1724 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1725 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001726 rsp->scid = cpu_to_le16(pi->dcid);
1727 rsp->result = cpu_to_le16(result);
1728 rsp->flags = cpu_to_le16(0x0000);
1729
1730 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731}
1732
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001733static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1734{
1735 struct l2cap_pinfo *pi = l2cap_pi(sk);
1736 struct l2cap_conf_req *req = data;
1737 void *ptr = req->data;
1738 int type, olen;
1739 unsigned long val;
1740 struct l2cap_conf_rfc rfc;
1741
1742 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1743
1744 while (len >= L2CAP_CONF_OPT_SIZE) {
1745 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1746
1747 switch (type) {
1748 case L2CAP_CONF_MTU:
1749 if (val < L2CAP_DEFAULT_MIN_MTU) {
1750 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001751 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001752 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001753 pi->imtu = val;
1754 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001755 break;
1756
1757 case L2CAP_CONF_FLUSH_TO:
1758 pi->flush_to = val;
1759 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1760 2, pi->flush_to);
1761 break;
1762
1763 case L2CAP_CONF_RFC:
1764 if (olen == sizeof(rfc))
1765 memcpy(&rfc, (void *)val, olen);
1766
1767 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1768 rfc.mode != pi->mode)
1769 return -ECONNREFUSED;
1770
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001771 pi->fcs = 0;
1772
1773 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1774 sizeof(rfc), (unsigned long) &rfc);
1775 break;
1776 }
1777 }
1778
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001779 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1780 return -ECONNREFUSED;
1781
1782 pi->mode = rfc.mode;
1783
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001784 if (*result == L2CAP_CONF_SUCCESS) {
1785 switch (rfc.mode) {
1786 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001787 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1788 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001789 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001790 break;
1791 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001792 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001793 }
1794 }
1795
1796 req->dcid = cpu_to_le16(pi->dcid);
1797 req->flags = cpu_to_le16(0x0000);
1798
1799 return ptr - data;
1800}
1801
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001802static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803{
1804 struct l2cap_conf_rsp *rsp = data;
1805 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001807 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001809 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001810 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001811 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812
1813 return ptr - data;
1814}
1815
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001816static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1817{
1818 struct l2cap_pinfo *pi = l2cap_pi(sk);
1819 int type, olen;
1820 unsigned long val;
1821 struct l2cap_conf_rfc rfc;
1822
1823 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1824
1825 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1826 return;
1827
1828 while (len >= L2CAP_CONF_OPT_SIZE) {
1829 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1830
1831 switch (type) {
1832 case L2CAP_CONF_RFC:
1833 if (olen == sizeof(rfc))
1834 memcpy(&rfc, (void *)val, olen);
1835 goto done;
1836 }
1837 }
1838
1839done:
1840 switch (rfc.mode) {
1841 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001842 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1843 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001844 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1845 break;
1846 case L2CAP_MODE_STREAMING:
1847 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1848 }
1849}
1850
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001851static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1852{
1853 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
1854
1855 if (rej->reason != 0x0000)
1856 return 0;
1857
1858 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
1859 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001860 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01001861
1862 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01001863 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01001864
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001865 l2cap_conn_start(conn);
1866 }
1867
1868 return 0;
1869}
1870
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1872{
1873 struct l2cap_chan_list *list = &conn->chan_list;
1874 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
1875 struct l2cap_conn_rsp rsp;
Nathan Holsteind793fe82010-10-15 11:54:02 -04001876 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001877 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878
1879 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001880 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881
1882 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
1883
1884 /* Check if we have socket listening on psm */
1885 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
1886 if (!parent) {
1887 result = L2CAP_CR_BAD_PSM;
1888 goto sendresp;
1889 }
1890
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001891 bh_lock_sock(parent);
1892
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001893 /* Check if the ACL is secure enough (if not SDP) */
1894 if (psm != cpu_to_le16(0x0001) &&
1895 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01001896 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001897 result = L2CAP_CR_SEC_BLOCK;
1898 goto response;
1899 }
1900
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 result = L2CAP_CR_NO_MEM;
1902
1903 /* Check for backlog size */
1904 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001905 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 goto response;
1907 }
1908
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001909 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910 if (!sk)
1911 goto response;
1912
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02001913 write_lock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914
1915 /* Check if we already have channel with that dcid */
1916 if (__l2cap_get_chan_by_dcid(list, scid)) {
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02001917 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918 sock_set_flag(sk, SOCK_ZAPPED);
1919 l2cap_sock_kill(sk);
1920 goto response;
1921 }
1922
1923 hci_conn_hold(conn->hcon);
1924
1925 l2cap_sock_init(sk, parent);
1926 bacpy(&bt_sk(sk)->src, conn->src);
1927 bacpy(&bt_sk(sk)->dst, conn->dst);
1928 l2cap_pi(sk)->psm = psm;
1929 l2cap_pi(sk)->dcid = scid;
1930
1931 __l2cap_chan_add(conn, sk, parent);
1932 dcid = l2cap_pi(sk)->scid;
1933
1934 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
1935
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 l2cap_pi(sk)->ident = cmd->ident;
1937
Marcel Holtmann984947d2009-02-06 23:35:19 +01001938 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001939 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001940 if (bt_sk(sk)->defer_setup) {
1941 sk->sk_state = BT_CONNECT2;
1942 result = L2CAP_CR_PEND;
1943 status = L2CAP_CS_AUTHOR_PEND;
1944 parent->sk_data_ready(parent, 0);
1945 } else {
1946 sk->sk_state = BT_CONFIG;
1947 result = L2CAP_CR_SUCCESS;
1948 status = L2CAP_CS_NO_INFO;
1949 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001950 } else {
1951 sk->sk_state = BT_CONNECT2;
1952 result = L2CAP_CR_PEND;
1953 status = L2CAP_CS_AUTHEN_PEND;
1954 }
1955 } else {
1956 sk->sk_state = BT_CONNECT2;
1957 result = L2CAP_CR_PEND;
1958 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959 }
1960
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02001961 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962
1963response:
1964 bh_unlock_sock(parent);
1965
1966sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001967 rsp.scid = cpu_to_le16(scid);
1968 rsp.dcid = cpu_to_le16(dcid);
1969 rsp.result = cpu_to_le16(result);
1970 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001972
1973 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
1974 struct l2cap_info_req info;
1975 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
1976
1977 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
1978 conn->info_ident = l2cap_get_ident(conn);
1979
1980 mod_timer(&conn->info_timer, jiffies +
1981 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
1982
1983 l2cap_send_cmd(conn, conn->info_ident,
1984 L2CAP_INFO_REQ, sizeof(info), &info);
1985 }
1986
Nathan Holsteind793fe82010-10-15 11:54:02 -04001987 if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001988 result == L2CAP_CR_SUCCESS) {
1989 u8 buf[128];
1990 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
1991 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1992 l2cap_build_conf_req(sk, buf), buf);
1993 l2cap_pi(sk)->num_conf_req++;
1994 }
1995
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996 return 0;
1997}
1998
1999static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2000{
2001 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2002 u16 scid, dcid, result, status;
2003 struct sock *sk;
2004 u8 req[128];
2005
2006 scid = __le16_to_cpu(rsp->scid);
2007 dcid = __le16_to_cpu(rsp->dcid);
2008 result = __le16_to_cpu(rsp->result);
2009 status = __le16_to_cpu(rsp->status);
2010
2011 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2012
2013 if (scid) {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002014 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2015 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002016 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 } else {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002018 sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
2019 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002020 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021 }
2022
2023 switch (result) {
2024 case L2CAP_CR_SUCCESS:
2025 sk->sk_state = BT_CONFIG;
2026 l2cap_pi(sk)->ident = 0;
2027 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002028 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2029
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002030 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2031 break;
2032
2033 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2034
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2036 l2cap_build_conf_req(sk, req), req);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002037 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 break;
2039
2040 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002041 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042 break;
2043
2044 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002045 /* don't delete l2cap channel if sk is owned by user */
2046 if (sock_owned_by_user(sk)) {
2047 sk->sk_state = BT_DISCONN;
2048 l2cap_sock_clear_timer(sk);
2049 l2cap_sock_set_timer(sk, HZ / 5);
2050 break;
2051 }
2052
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 l2cap_chan_del(sk, ECONNREFUSED);
2054 break;
2055 }
2056
2057 bh_unlock_sock(sk);
2058 return 0;
2059}
2060
Mat Martineau8c462b62010-08-24 15:35:42 -07002061static inline void set_default_fcs(struct l2cap_pinfo *pi)
2062{
2063 /* FCS is enabled only in ERTM or streaming mode, if one or both
2064 * sides request it.
2065 */
2066 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2067 pi->fcs = L2CAP_FCS_NONE;
2068 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2069 pi->fcs = L2CAP_FCS_CRC16;
2070}
2071
Al Viro88219a02007-07-29 00:17:25 -07002072static 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 -07002073{
2074 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2075 u16 dcid, flags;
2076 u8 rsp[64];
2077 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002078 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079
2080 dcid = __le16_to_cpu(req->dcid);
2081 flags = __le16_to_cpu(req->flags);
2082
2083 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2084
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002085 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2086 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 return -ENOENT;
2088
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002089 if (sk->sk_state != BT_CONFIG) {
2090 struct l2cap_cmd_rej rej;
2091
2092 rej.reason = cpu_to_le16(0x0002);
2093 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2094 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002095 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002096 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002097
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002098 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002099 len = cmd_len - sizeof(*req);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002100 if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
2101 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2102 l2cap_build_conf_rsp(sk, rsp,
2103 L2CAP_CONF_REJECT, flags), rsp);
2104 goto unlock;
2105 }
2106
2107 /* Store config. */
2108 memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
2109 l2cap_pi(sk)->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110
2111 if (flags & 0x0001) {
2112 /* Incomplete config. Send empty response. */
2113 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002114 l2cap_build_conf_rsp(sk, rsp,
2115 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 goto unlock;
2117 }
2118
2119 /* Complete config. */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002120 len = l2cap_parse_conf_req(sk, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002121 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002122 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002124 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002126 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002127 l2cap_pi(sk)->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002128
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002129 /* Reset config buffer. */
2130 l2cap_pi(sk)->conf_len = 0;
2131
Marcel Holtmann876d9482007-10-20 13:35:42 +02002132 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2133 goto unlock;
2134
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002136 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002137
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002139
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002140 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002141 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002142 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002143 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2144 l2cap_ertm_init(sk);
2145
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002147 goto unlock;
2148 }
2149
2150 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002151 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002152 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002154 l2cap_build_conf_req(sk, buf), buf);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002155 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156 }
2157
2158unlock:
2159 bh_unlock_sock(sk);
2160 return 0;
2161}
2162
2163static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2164{
2165 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2166 u16 scid, flags, result;
2167 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002168 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169
2170 scid = __le16_to_cpu(rsp->scid);
2171 flags = __le16_to_cpu(rsp->flags);
2172 result = __le16_to_cpu(rsp->result);
2173
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002174 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2175 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002177 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2178 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 return 0;
2180
2181 switch (result) {
2182 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002183 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 break;
2185
2186 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002187 if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002188 char req[64];
2189
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002190 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002191 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002192 goto done;
2193 }
2194
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002195 /* throw out any old stored conf requests */
2196 result = L2CAP_CONF_SUCCESS;
2197 len = l2cap_parse_conf_rsp(sk, rsp->data,
2198 len, req, &result);
2199 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002200 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002201 goto done;
2202 }
2203
2204 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2205 L2CAP_CONF_REQ, len, req);
2206 l2cap_pi(sk)->num_conf_req++;
2207 if (result != L2CAP_CONF_SUCCESS)
2208 goto done;
2209 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 }
2211
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002212 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002213 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002215 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 goto done;
2217 }
2218
2219 if (flags & 0x01)
2220 goto done;
2221
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2223
2224 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002225 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002226
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002228 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002229 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002230 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002231 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2232 l2cap_ertm_init(sk);
2233
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234 l2cap_chan_ready(sk);
2235 }
2236
2237done:
2238 bh_unlock_sock(sk);
2239 return 0;
2240}
2241
2242static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2243{
2244 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2245 struct l2cap_disconn_rsp rsp;
2246 u16 dcid, scid;
2247 struct sock *sk;
2248
2249 scid = __le16_to_cpu(req->scid);
2250 dcid = __le16_to_cpu(req->dcid);
2251
2252 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2253
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002254 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2255 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 return 0;
2257
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002258 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2259 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2261
2262 sk->sk_shutdown = SHUTDOWN_MASK;
2263
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002264 /* don't delete l2cap channel if sk is owned by user */
2265 if (sock_owned_by_user(sk)) {
2266 sk->sk_state = BT_DISCONN;
2267 l2cap_sock_clear_timer(sk);
2268 l2cap_sock_set_timer(sk, HZ / 5);
2269 bh_unlock_sock(sk);
2270 return 0;
2271 }
2272
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 l2cap_chan_del(sk, ECONNRESET);
2274 bh_unlock_sock(sk);
2275
2276 l2cap_sock_kill(sk);
2277 return 0;
2278}
2279
2280static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2281{
2282 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2283 u16 dcid, scid;
2284 struct sock *sk;
2285
2286 scid = __le16_to_cpu(rsp->scid);
2287 dcid = __le16_to_cpu(rsp->dcid);
2288
2289 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2290
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002291 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2292 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293 return 0;
2294
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002295 /* don't delete l2cap channel if sk is owned by user */
2296 if (sock_owned_by_user(sk)) {
2297 sk->sk_state = BT_DISCONN;
2298 l2cap_sock_clear_timer(sk);
2299 l2cap_sock_set_timer(sk, HZ / 5);
2300 bh_unlock_sock(sk);
2301 return 0;
2302 }
2303
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 l2cap_chan_del(sk, 0);
2305 bh_unlock_sock(sk);
2306
2307 l2cap_sock_kill(sk);
2308 return 0;
2309}
2310
2311static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2312{
2313 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 u16 type;
2315
2316 type = __le16_to_cpu(req->type);
2317
2318 BT_DBG("type 0x%4.4x", type);
2319
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002320 if (type == L2CAP_IT_FEAT_MASK) {
2321 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002322 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002323 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2324 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2325 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002326 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002327 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2328 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002329 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002330 l2cap_send_cmd(conn, cmd->ident,
2331 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002332 } else if (type == L2CAP_IT_FIXED_CHAN) {
2333 u8 buf[12];
2334 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2335 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2336 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2337 memcpy(buf + 4, l2cap_fixed_chan, 8);
2338 l2cap_send_cmd(conn, cmd->ident,
2339 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002340 } else {
2341 struct l2cap_info_rsp rsp;
2342 rsp.type = cpu_to_le16(type);
2343 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2344 l2cap_send_cmd(conn, cmd->ident,
2345 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2346 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347
2348 return 0;
2349}
2350
2351static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2352{
2353 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2354 u16 type, result;
2355
2356 type = __le16_to_cpu(rsp->type);
2357 result = __le16_to_cpu(rsp->result);
2358
2359 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2360
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002361 del_timer(&conn->info_timer);
2362
Ville Tervoadb08ed2010-08-04 09:43:33 +03002363 if (result != L2CAP_IR_SUCCESS) {
2364 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2365 conn->info_ident = 0;
2366
2367 l2cap_conn_start(conn);
2368
2369 return 0;
2370 }
2371
Marcel Holtmann984947d2009-02-06 23:35:19 +01002372 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002373 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002374
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002375 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002376 struct l2cap_info_req req;
2377 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2378
2379 conn->info_ident = l2cap_get_ident(conn);
2380
2381 l2cap_send_cmd(conn, conn->info_ident,
2382 L2CAP_INFO_REQ, sizeof(req), &req);
2383 } else {
2384 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2385 conn->info_ident = 0;
2386
2387 l2cap_conn_start(conn);
2388 }
2389 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002390 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002391 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002392
2393 l2cap_conn_start(conn);
2394 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002395
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396 return 0;
2397}
2398
2399static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
2400{
2401 u8 *data = skb->data;
2402 int len = skb->len;
2403 struct l2cap_cmd_hdr cmd;
2404 int err = 0;
2405
2406 l2cap_raw_recv(conn, skb);
2407
2408 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002409 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2411 data += L2CAP_CMD_HDR_SIZE;
2412 len -= L2CAP_CMD_HDR_SIZE;
2413
Al Viro88219a02007-07-29 00:17:25 -07002414 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415
Al Viro88219a02007-07-29 00:17:25 -07002416 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 -07002417
Al Viro88219a02007-07-29 00:17:25 -07002418 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419 BT_DBG("corrupted command");
2420 break;
2421 }
2422
2423 switch (cmd.code) {
2424 case L2CAP_COMMAND_REJ:
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002425 l2cap_command_rej(conn, &cmd, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426 break;
2427
2428 case L2CAP_CONN_REQ:
2429 err = l2cap_connect_req(conn, &cmd, data);
2430 break;
2431
2432 case L2CAP_CONN_RSP:
2433 err = l2cap_connect_rsp(conn, &cmd, data);
2434 break;
2435
2436 case L2CAP_CONF_REQ:
Al Viro88219a02007-07-29 00:17:25 -07002437 err = l2cap_config_req(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438 break;
2439
2440 case L2CAP_CONF_RSP:
2441 err = l2cap_config_rsp(conn, &cmd, data);
2442 break;
2443
2444 case L2CAP_DISCONN_REQ:
2445 err = l2cap_disconnect_req(conn, &cmd, data);
2446 break;
2447
2448 case L2CAP_DISCONN_RSP:
2449 err = l2cap_disconnect_rsp(conn, &cmd, data);
2450 break;
2451
2452 case L2CAP_ECHO_REQ:
Al Viro88219a02007-07-29 00:17:25 -07002453 l2cap_send_cmd(conn, cmd.ident, L2CAP_ECHO_RSP, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 break;
2455
2456 case L2CAP_ECHO_RSP:
2457 break;
2458
2459 case L2CAP_INFO_REQ:
2460 err = l2cap_information_req(conn, &cmd, data);
2461 break;
2462
2463 case L2CAP_INFO_RSP:
2464 err = l2cap_information_rsp(conn, &cmd, data);
2465 break;
2466
2467 default:
2468 BT_ERR("Unknown signaling command 0x%2.2x", cmd.code);
2469 err = -EINVAL;
2470 break;
2471 }
2472
2473 if (err) {
2474 struct l2cap_cmd_rej rej;
2475 BT_DBG("error %d", err);
2476
2477 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002478 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2480 }
2481
Al Viro88219a02007-07-29 00:17:25 -07002482 data += cmd_len;
2483 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484 }
2485
2486 kfree_skb(skb);
2487}
2488
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002489static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2490{
2491 u16 our_fcs, rcv_fcs;
2492 int hdr_size = L2CAP_HDR_SIZE + 2;
2493
2494 if (pi->fcs == L2CAP_FCS_CRC16) {
2495 skb_trim(skb, skb->len - 2);
2496 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2497 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2498
2499 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002500 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002501 }
2502 return 0;
2503}
2504
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002505static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
2506{
2507 struct l2cap_pinfo *pi = l2cap_pi(sk);
2508 u16 control = 0;
2509
2510 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002511
2512 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2513
2514 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002515 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002516 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002517 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002518 }
2519
Gustavo F. Padovan4ea727e2010-06-03 16:34:20 -03002520 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
2521 l2cap_retransmit_frames(sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002522
2523 l2cap_ertm_send(sk);
2524
2525 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
2526 pi->frames_sent == 0) {
2527 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002528 l2cap_send_sframe(pi, control);
2529 }
2530}
2531
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002532static 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 -03002533{
2534 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002535 struct l2cap_pinfo *pi = l2cap_pi(sk);
2536 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002537
2538 bt_cb(skb)->tx_seq = tx_seq;
2539 bt_cb(skb)->sar = sar;
2540
2541 next_skb = skb_peek(SREJ_QUEUE(sk));
2542 if (!next_skb) {
2543 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002544 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002545 }
2546
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002547 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
2548 if (tx_seq_offset < 0)
2549 tx_seq_offset += 64;
2550
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002551 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002552 if (bt_cb(next_skb)->tx_seq == tx_seq)
2553 return -EINVAL;
2554
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002555 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
2556 pi->buffer_seq) % 64;
2557 if (next_tx_seq_offset < 0)
2558 next_tx_seq_offset += 64;
2559
2560 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002561 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002562 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002563 }
2564
2565 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
2566 break;
2567
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002568 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002569
2570 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002571
2572 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002573}
2574
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002575static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
2576{
2577 struct l2cap_pinfo *pi = l2cap_pi(sk);
2578 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002579 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002580
2581 switch (control & L2CAP_CTRL_SAR) {
2582 case L2CAP_SDU_UNSEGMENTED:
2583 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2584 goto drop;
2585
2586 err = sock_queue_rcv_skb(sk, skb);
2587 if (!err)
2588 return err;
2589
2590 break;
2591
2592 case L2CAP_SDU_START:
2593 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2594 goto drop;
2595
2596 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002597
2598 if (pi->sdu_len > pi->imtu)
2599 goto disconnect;
2600
2601 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002602 if (!pi->sdu)
2603 return -ENOMEM;
2604
2605 /* pull sdu_len bytes only after alloc, because of Local Busy
2606 * condition we have to be sure that this will be executed
2607 * only once, i.e., when alloc does not fail */
2608 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002609
2610 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2611
2612 pi->conn_state |= L2CAP_CONN_SAR_SDU;
2613 pi->partial_sdu_len = skb->len;
2614 break;
2615
2616 case L2CAP_SDU_CONTINUE:
2617 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2618 goto disconnect;
2619
2620 if (!pi->sdu)
2621 goto disconnect;
2622
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002623 pi->partial_sdu_len += skb->len;
2624 if (pi->partial_sdu_len > pi->sdu_len)
2625 goto drop;
2626
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002627 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2628
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002629 break;
2630
2631 case L2CAP_SDU_END:
2632 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2633 goto disconnect;
2634
2635 if (!pi->sdu)
2636 goto disconnect;
2637
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002638 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002639 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002640
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002641 if (pi->partial_sdu_len > pi->imtu)
2642 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002643
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002644 if (pi->partial_sdu_len != pi->sdu_len)
2645 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002646
2647 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002648 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002649
2650 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002651 if (!_skb) {
2652 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2653 return -ENOMEM;
2654 }
2655
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002656 err = sock_queue_rcv_skb(sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002657 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002658 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002659 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2660 return err;
2661 }
2662
2663 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2664 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002665
2666 kfree_skb(pi->sdu);
2667 break;
2668 }
2669
2670 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002671 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002672
2673drop:
2674 kfree_skb(pi->sdu);
2675 pi->sdu = NULL;
2676
2677disconnect:
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002678 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002679 kfree_skb(skb);
2680 return 0;
2681}
2682
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002683static int l2cap_try_push_rx_skb(struct sock *sk)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002684{
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002685 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002686 struct sk_buff *skb;
2687 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002688 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002689
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002690 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
2691 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
2692 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
2693 if (err < 0) {
2694 skb_queue_head(BUSY_QUEUE(sk), skb);
2695 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002696 }
2697
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002698 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002699 }
2700
2701 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
2702 goto done;
2703
2704 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2705 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
2706 l2cap_send_sframe(pi, control);
2707 l2cap_pi(sk)->retry_count = 1;
2708
2709 del_timer(&pi->retrans_timer);
2710 __mod_monitor_timer();
2711
2712 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
2713
2714done:
2715 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2716 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
2717
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002718 BT_DBG("sk %p, Exit local busy", sk);
2719
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002720 return 0;
2721}
2722
2723static void l2cap_busy_work(struct work_struct *work)
2724{
2725 DECLARE_WAITQUEUE(wait, current);
2726 struct l2cap_pinfo *pi =
2727 container_of(work, struct l2cap_pinfo, busy_work);
2728 struct sock *sk = (struct sock *)pi;
2729 int n_tries = 0, timeo = HZ/5, err;
2730 struct sk_buff *skb;
2731
2732 lock_sock(sk);
2733
2734 add_wait_queue(sk_sleep(sk), &wait);
2735 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
2736 set_current_state(TASK_INTERRUPTIBLE);
2737
2738 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
2739 err = -EBUSY;
2740 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
2741 break;
2742 }
2743
2744 if (!timeo)
2745 timeo = HZ/5;
2746
2747 if (signal_pending(current)) {
2748 err = sock_intr_errno(timeo);
2749 break;
2750 }
2751
2752 release_sock(sk);
2753 timeo = schedule_timeout(timeo);
2754 lock_sock(sk);
2755
2756 err = sock_error(sk);
2757 if (err)
2758 break;
2759
2760 if (l2cap_try_push_rx_skb(sk) == 0)
2761 break;
2762 }
2763
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002764 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02002765 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002766
2767 release_sock(sk);
2768}
2769
2770static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
2771{
2772 struct l2cap_pinfo *pi = l2cap_pi(sk);
2773 int sctrl, err;
2774
2775 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
2776 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
2777 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002778 return l2cap_try_push_rx_skb(sk);
2779
2780
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002781 }
2782
2783 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
2784 if (err >= 0) {
2785 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
2786 return err;
2787 }
2788
2789 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002790 BT_DBG("sk %p, Enter local busy", sk);
2791
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002792 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
2793 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
2794 __skb_queue_tail(BUSY_QUEUE(sk), skb);
2795
2796 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2797 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
2798 l2cap_send_sframe(pi, sctrl);
2799
2800 pi->conn_state |= L2CAP_CONN_RNR_SENT;
2801
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03002802 del_timer(&pi->ack_timer);
2803
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002804 queue_work(_busy_wq, &pi->busy_work);
2805
2806 return err;
2807}
2808
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002809static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002810{
2811 struct l2cap_pinfo *pi = l2cap_pi(sk);
2812 struct sk_buff *_skb;
2813 int err = -EINVAL;
2814
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002815 /*
2816 * TODO: We have to notify the userland if some data is lost with the
2817 * Streaming Mode.
2818 */
2819
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002820 switch (control & L2CAP_CTRL_SAR) {
2821 case L2CAP_SDU_UNSEGMENTED:
2822 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
2823 kfree_skb(pi->sdu);
2824 break;
2825 }
2826
2827 err = sock_queue_rcv_skb(sk, skb);
2828 if (!err)
2829 return 0;
2830
2831 break;
2832
2833 case L2CAP_SDU_START:
2834 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
2835 kfree_skb(pi->sdu);
2836 break;
2837 }
2838
2839 pi->sdu_len = get_unaligned_le16(skb->data);
2840 skb_pull(skb, 2);
2841
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03002842 if (pi->sdu_len > pi->imtu) {
2843 err = -EMSGSIZE;
2844 break;
2845 }
2846
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002847 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
2848 if (!pi->sdu) {
2849 err = -ENOMEM;
2850 break;
2851 }
2852
2853 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2854
2855 pi->conn_state |= L2CAP_CONN_SAR_SDU;
2856 pi->partial_sdu_len = skb->len;
2857 err = 0;
2858 break;
2859
2860 case L2CAP_SDU_CONTINUE:
2861 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2862 break;
2863
2864 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2865
2866 pi->partial_sdu_len += skb->len;
2867 if (pi->partial_sdu_len > pi->sdu_len)
2868 kfree_skb(pi->sdu);
2869 else
2870 err = 0;
2871
2872 break;
2873
2874 case L2CAP_SDU_END:
2875 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2876 break;
2877
2878 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2879
2880 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
2881 pi->partial_sdu_len += skb->len;
2882
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03002883 if (pi->partial_sdu_len > pi->imtu)
2884 goto drop;
2885
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002886 if (pi->partial_sdu_len == pi->sdu_len) {
2887 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
2888 err = sock_queue_rcv_skb(sk, _skb);
2889 if (err < 0)
2890 kfree_skb(_skb);
2891 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002892 err = 0;
2893
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03002894drop:
2895 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002896 break;
2897 }
2898
2899 kfree_skb(skb);
2900 return err;
2901}
2902
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002903static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
2904{
2905 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03002906 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002907
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002908 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002909 if (bt_cb(skb)->tx_seq != tx_seq)
2910 break;
2911
2912 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03002913 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002914 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002915 l2cap_pi(sk)->buffer_seq_srej =
2916 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03002917 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002918 }
2919}
2920
2921static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
2922{
2923 struct l2cap_pinfo *pi = l2cap_pi(sk);
2924 struct srej_list *l, *tmp;
2925 u16 control;
2926
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002927 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002928 if (l->tx_seq == tx_seq) {
2929 list_del(&l->list);
2930 kfree(l);
2931 return;
2932 }
2933 control = L2CAP_SUPER_SELECT_REJECT;
2934 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2935 l2cap_send_sframe(pi, control);
2936 list_del(&l->list);
2937 list_add_tail(&l->list, SREJ_LIST(sk));
2938 }
2939}
2940
2941static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
2942{
2943 struct l2cap_pinfo *pi = l2cap_pi(sk);
2944 struct srej_list *new;
2945 u16 control;
2946
2947 while (tx_seq != pi->expected_tx_seq) {
2948 control = L2CAP_SUPER_SELECT_REJECT;
2949 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2950 l2cap_send_sframe(pi, control);
2951
2952 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03002953 new->tx_seq = pi->expected_tx_seq;
2954 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002955 list_add_tail(&new->list, SREJ_LIST(sk));
2956 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03002957 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002958}
2959
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002960static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
2961{
2962 struct l2cap_pinfo *pi = l2cap_pi(sk);
2963 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03002964 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002965 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03002966 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03002967 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002968 int err = 0;
2969
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002970 BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
2971 rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002972
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03002973 if (L2CAP_CTRL_FINAL & rx_control &&
2974 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03002975 del_timer(&pi->monitor_timer);
2976 if (pi->unacked_frames > 0)
2977 __mod_retrans_timer();
2978 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
2979 }
2980
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03002981 pi->expected_ack_seq = req_seq;
2982 l2cap_drop_acked_frames(sk);
2983
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002984 if (tx_seq == pi->expected_tx_seq)
2985 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002986
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002987 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
2988 if (tx_seq_offset < 0)
2989 tx_seq_offset += 64;
2990
2991 /* invalid tx_seq */
2992 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002993 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002994 goto drop;
2995 }
2996
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002997 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
2998 goto drop;
2999
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003000 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3001 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003002
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003003 first = list_first_entry(SREJ_LIST(sk),
3004 struct srej_list, list);
3005 if (tx_seq == first->tx_seq) {
3006 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3007 l2cap_check_srej_gap(sk, tx_seq);
3008
3009 list_del(&first->list);
3010 kfree(first);
3011
3012 if (list_empty(SREJ_LIST(sk))) {
3013 pi->buffer_seq = pi->buffer_seq_srej;
3014 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666cc2010-05-01 16:15:40 -03003015 l2cap_send_ack(pi);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003016 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003017 }
3018 } else {
3019 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003020
3021 /* duplicated tx_seq */
3022 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
3023 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003024
3025 list_for_each_entry(l, SREJ_LIST(sk), list) {
3026 if (l->tx_seq == tx_seq) {
3027 l2cap_resend_srejframe(sk, tx_seq);
3028 return 0;
3029 }
3030 }
3031 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003032 }
3033 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003034 expected_tx_seq_offset =
3035 (pi->expected_tx_seq - pi->buffer_seq) % 64;
3036 if (expected_tx_seq_offset < 0)
3037 expected_tx_seq_offset += 64;
3038
3039 /* duplicated tx_seq */
3040 if (tx_seq_offset < expected_tx_seq_offset)
3041 goto drop;
3042
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003043 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003044
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003045 BT_DBG("sk %p, Enter SREJ", sk);
3046
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003047 INIT_LIST_HEAD(SREJ_LIST(sk));
3048 pi->buffer_seq_srej = pi->buffer_seq;
3049
3050 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003051 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003052 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3053
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003054 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
3055
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003056 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003057
3058 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003059 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003060 return 0;
3061
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003062expected:
3063 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3064
3065 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003066 bt_cb(skb)->tx_seq = tx_seq;
3067 bt_cb(skb)->sar = sar;
3068 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003069 return 0;
3070 }
3071
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003072 err = l2cap_push_rx_skb(sk, skb, rx_control);
3073 if (err < 0)
3074 return 0;
3075
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003076 if (rx_control & L2CAP_CTRL_FINAL) {
3077 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3078 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003079 else
3080 l2cap_retransmit_frames(sk);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003081 }
3082
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003083 __mod_ack_timer();
3084
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003085 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
3086 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003087 l2cap_send_ack(pi);
3088
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003089 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003090
3091drop:
3092 kfree_skb(skb);
3093 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003094}
3095
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003096static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003097{
3098 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003099
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003100 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3101 rx_control);
3102
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003103 pi->expected_ack_seq = __get_reqseq(rx_control);
3104 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003105
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003106 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003107 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003108 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3109 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3110 (pi->unacked_frames > 0))
3111 __mod_retrans_timer();
3112
3113 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3114 l2cap_send_srejtail(sk);
3115 } else {
3116 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003117 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003118
3119 } else if (rx_control & L2CAP_CTRL_FINAL) {
3120 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003121
3122 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3123 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003124 else
3125 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003126
3127 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003128 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3129 (pi->unacked_frames > 0))
3130 __mod_retrans_timer();
3131
3132 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003133 if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003134 l2cap_send_ack(pi);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003135 else
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003136 l2cap_ertm_send(sk);
3137 }
3138}
3139
3140static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
3141{
3142 struct l2cap_pinfo *pi = l2cap_pi(sk);
3143 u8 tx_seq = __get_reqseq(rx_control);
3144
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003145 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3146
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003147 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3148
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03003149 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003150 l2cap_drop_acked_frames(sk);
3151
3152 if (rx_control & L2CAP_CTRL_FINAL) {
3153 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3154 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003155 else
3156 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003157 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003158 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003159
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03003160 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003161 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003162 }
3163}
3164static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
3165{
3166 struct l2cap_pinfo *pi = l2cap_pi(sk);
3167 u8 tx_seq = __get_reqseq(rx_control);
3168
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003169 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3170
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003171 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3172
3173 if (rx_control & L2CAP_CTRL_POLL) {
3174 pi->expected_ack_seq = tx_seq;
3175 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003176
3177 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003178 l2cap_retransmit_one_frame(sk, tx_seq);
3179
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003180 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003181
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003182 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3183 pi->srej_save_reqseq = tx_seq;
3184 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3185 }
3186 } else if (rx_control & L2CAP_CTRL_FINAL) {
3187 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
3188 pi->srej_save_reqseq == tx_seq)
3189 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
3190 else
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003191 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003192 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003193 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003194 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3195 pi->srej_save_reqseq = tx_seq;
3196 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3197 }
3198 }
3199}
3200
3201static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
3202{
3203 struct l2cap_pinfo *pi = l2cap_pi(sk);
3204 u8 tx_seq = __get_reqseq(rx_control);
3205
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003206 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3207
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003208 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
3209 pi->expected_ack_seq = tx_seq;
3210 l2cap_drop_acked_frames(sk);
3211
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003212 if (rx_control & L2CAP_CTRL_POLL)
3213 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
3214
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003215 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
3216 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003217 if (rx_control & L2CAP_CTRL_POLL)
3218 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003219 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003220 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003221
3222 if (rx_control & L2CAP_CTRL_POLL)
3223 l2cap_send_srejtail(sk);
3224 else
3225 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003226}
3227
3228static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3229{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003230 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3231
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003232 if (L2CAP_CTRL_FINAL & rx_control &&
3233 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003234 del_timer(&l2cap_pi(sk)->monitor_timer);
3235 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003236 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003237 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003238 }
3239
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003240 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3241 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003242 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003243 break;
3244
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003245 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003246 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003247 break;
3248
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003249 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003250 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003251 break;
3252
3253 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003254 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003255 break;
3256 }
3257
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003258 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003259 return 0;
3260}
3261
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003262static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3263{
3264 struct l2cap_pinfo *pi = l2cap_pi(sk);
3265 u16 control;
3266 u8 req_seq;
3267 int len, next_tx_seq_offset, req_seq_offset;
3268
3269 control = get_unaligned_le16(skb->data);
3270 skb_pull(skb, 2);
3271 len = skb->len;
3272
3273 /*
3274 * We can just drop the corrupted I-frame here.
3275 * Receiver will miss it and start proper recovery
3276 * procedures and ask retransmission.
3277 */
3278 if (l2cap_check_fcs(pi, skb))
3279 goto drop;
3280
3281 if (__is_sar_start(control) && __is_iframe(control))
3282 len -= 2;
3283
3284 if (pi->fcs == L2CAP_FCS_CRC16)
3285 len -= 2;
3286
3287 if (len > pi->mps) {
3288 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3289 goto drop;
3290 }
3291
3292 req_seq = __get_reqseq(control);
3293 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
3294 if (req_seq_offset < 0)
3295 req_seq_offset += 64;
3296
3297 next_tx_seq_offset =
3298 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
3299 if (next_tx_seq_offset < 0)
3300 next_tx_seq_offset += 64;
3301
3302 /* check for invalid req-seq */
3303 if (req_seq_offset > next_tx_seq_offset) {
3304 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3305 goto drop;
3306 }
3307
3308 if (__is_iframe(control)) {
3309 if (len < 0) {
3310 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3311 goto drop;
3312 }
3313
3314 l2cap_data_channel_iframe(sk, control, skb);
3315 } else {
3316 if (len != 0) {
3317 BT_ERR("%d", len);
3318 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3319 goto drop;
3320 }
3321
3322 l2cap_data_channel_sframe(sk, control, skb);
3323 }
3324
3325 return 0;
3326
3327drop:
3328 kfree_skb(skb);
3329 return 0;
3330}
3331
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3333{
3334 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003335 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003336 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003337 u8 tx_seq;
3338 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339
3340 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
3341 if (!sk) {
3342 BT_DBG("unknown cid 0x%4.4x", cid);
3343 goto drop;
3344 }
3345
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003346 pi = l2cap_pi(sk);
3347
Linus Torvalds1da177e2005-04-16 15:20:36 -07003348 BT_DBG("sk %p, len %d", sk, skb->len);
3349
3350 if (sk->sk_state != BT_CONNECTED)
3351 goto drop;
3352
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003353 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003354 case L2CAP_MODE_BASIC:
3355 /* If socket recv buffers overflows we drop data here
3356 * which is *bad* because L2CAP has to be reliable.
3357 * But we don't have any other choice. L2CAP doesn't
3358 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003360 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003361 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003363 if (!sock_queue_rcv_skb(sk, skb))
3364 goto done;
3365 break;
3366
3367 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003368 if (!sock_owned_by_user(sk)) {
3369 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003370 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003371 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003372 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003373 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003374
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003375 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003376
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003377 case L2CAP_MODE_STREAMING:
3378 control = get_unaligned_le16(skb->data);
3379 skb_pull(skb, 2);
3380 len = skb->len;
3381
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003382 if (l2cap_check_fcs(pi, skb))
3383 goto drop;
3384
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003385 if (__is_sar_start(control))
3386 len -= 2;
3387
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003388 if (pi->fcs == L2CAP_FCS_CRC16)
3389 len -= 2;
3390
Nathan Holstein51893f82010-06-09 15:46:25 -04003391 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003392 goto drop;
3393
3394 tx_seq = __get_txseq(control);
3395
3396 if (pi->expected_tx_seq == tx_seq)
3397 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3398 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03003399 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003400
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003401 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003402
3403 goto done;
3404
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003405 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003406 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003407 break;
3408 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409
3410drop:
3411 kfree_skb(skb);
3412
3413done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003414 if (sk)
3415 bh_unlock_sock(sk);
3416
Linus Torvalds1da177e2005-04-16 15:20:36 -07003417 return 0;
3418}
3419
Al Viro8e036fc2007-07-29 00:16:36 -07003420static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421{
3422 struct sock *sk;
3423
3424 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3425 if (!sk)
3426 goto drop;
3427
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003428 bh_lock_sock(sk);
3429
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430 BT_DBG("sk %p, len %d", sk, skb->len);
3431
3432 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3433 goto drop;
3434
3435 if (l2cap_pi(sk)->imtu < skb->len)
3436 goto drop;
3437
3438 if (!sock_queue_rcv_skb(sk, skb))
3439 goto done;
3440
3441drop:
3442 kfree_skb(skb);
3443
3444done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003445 if (sk)
3446 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003447 return 0;
3448}
3449
3450static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3451{
3452 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003453 u16 cid, len;
3454 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455
3456 skb_pull(skb, L2CAP_HDR_SIZE);
3457 cid = __le16_to_cpu(lh->cid);
3458 len = __le16_to_cpu(lh->len);
3459
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003460 if (len != skb->len) {
3461 kfree_skb(skb);
3462 return;
3463 }
3464
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3466
3467 switch (cid) {
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003468 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469 l2cap_sig_channel(conn, skb);
3470 break;
3471
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003472 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003473 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003474 skb_pull(skb, 2);
3475 l2cap_conless_channel(conn, psm, skb);
3476 break;
3477
3478 default:
3479 l2cap_data_channel(conn, cid, skb);
3480 break;
3481 }
3482}
3483
3484/* ---- L2CAP interface with lower layer (HCI) ---- */
3485
3486static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3487{
3488 int exact = 0, lm1 = 0, lm2 = 0;
3489 register struct sock *sk;
3490 struct hlist_node *node;
3491
3492 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003493 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494
3495 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3496
3497 /* Find listening sockets and check their link_mode */
3498 read_lock(&l2cap_sk_list.lock);
3499 sk_for_each(sk, node, &l2cap_sk_list.head) {
3500 if (sk->sk_state != BT_LISTEN)
3501 continue;
3502
3503 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003504 lm1 |= HCI_LM_ACCEPT;
3505 if (l2cap_pi(sk)->role_switch)
3506 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003508 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3509 lm2 |= HCI_LM_ACCEPT;
3510 if (l2cap_pi(sk)->role_switch)
3511 lm2 |= HCI_LM_MASTER;
3512 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513 }
3514 read_unlock(&l2cap_sk_list.lock);
3515
3516 return exact ? lm1 : lm2;
3517}
3518
3519static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3520{
Marcel Holtmann01394182006-07-03 10:02:46 +02003521 struct l2cap_conn *conn;
3522
Linus Torvalds1da177e2005-04-16 15:20:36 -07003523 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3524
3525 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003526 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527
3528 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003529 conn = l2cap_conn_add(hcon, status);
3530 if (conn)
3531 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003532 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533 l2cap_conn_del(hcon, bt_err(status));
3534
3535 return 0;
3536}
3537
Marcel Holtmann2950f212009-02-12 14:02:50 +01003538static int l2cap_disconn_ind(struct hci_conn *hcon)
3539{
3540 struct l2cap_conn *conn = hcon->l2cap_data;
3541
3542 BT_DBG("hcon %p", hcon);
3543
3544 if (hcon->type != ACL_LINK || !conn)
3545 return 0x13;
3546
3547 return conn->disc_reason;
3548}
3549
3550static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551{
3552 BT_DBG("hcon %p reason %d", hcon, reason);
3553
3554 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003555 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003556
3557 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003558
Linus Torvalds1da177e2005-04-16 15:20:36 -07003559 return 0;
3560}
3561
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003562static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3563{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003564 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003565 return;
3566
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003567 if (encrypt == 0x00) {
3568 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3569 l2cap_sock_clear_timer(sk);
3570 l2cap_sock_set_timer(sk, HZ * 5);
3571 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3572 __l2cap_sock_close(sk, ECONNREFUSED);
3573 } else {
3574 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3575 l2cap_sock_clear_timer(sk);
3576 }
3577}
3578
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003579static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003580{
3581 struct l2cap_chan_list *l;
Marcel Holtmann40be4922008-07-14 20:13:50 +02003582 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003583 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584
Marcel Holtmann01394182006-07-03 10:02:46 +02003585 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003586 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003587
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588 l = &conn->chan_list;
3589
3590 BT_DBG("conn %p", conn);
3591
3592 read_lock(&l->lock);
3593
3594 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
3595 bh_lock_sock(sk);
3596
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003597 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3598 bh_unlock_sock(sk);
3599 continue;
3600 }
3601
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003602 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003603 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003604 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003605 bh_unlock_sock(sk);
3606 continue;
3607 }
3608
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003609 if (sk->sk_state == BT_CONNECT) {
3610 if (!status) {
3611 struct l2cap_conn_req req;
3612 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3613 req.psm = l2cap_pi(sk)->psm;
3614
3615 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003616 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003617
3618 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3619 L2CAP_CONN_REQ, sizeof(req), &req);
3620 } else {
3621 l2cap_sock_clear_timer(sk);
3622 l2cap_sock_set_timer(sk, HZ / 10);
3623 }
3624 } else if (sk->sk_state == BT_CONNECT2) {
3625 struct l2cap_conn_rsp rsp;
3626 __u16 result;
3627
3628 if (!status) {
3629 sk->sk_state = BT_CONFIG;
3630 result = L2CAP_CR_SUCCESS;
3631 } else {
3632 sk->sk_state = BT_DISCONN;
3633 l2cap_sock_set_timer(sk, HZ / 10);
3634 result = L2CAP_CR_SEC_BLOCK;
3635 }
3636
3637 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3638 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3639 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003640 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003641 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3642 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643 }
3644
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645 bh_unlock_sock(sk);
3646 }
3647
3648 read_unlock(&l->lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003649
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650 return 0;
3651}
3652
3653static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3654{
3655 struct l2cap_conn *conn = hcon->l2cap_data;
3656
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003657 if (!conn)
3658 conn = l2cap_conn_add(hcon, 0);
3659
3660 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661 goto drop;
3662
3663 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3664
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003665 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003666 struct l2cap_hdr *hdr;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003667 struct sock *sk;
3668 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669 int len;
3670
3671 if (conn->rx_len) {
3672 BT_ERR("Unexpected start frame (len %d)", skb->len);
3673 kfree_skb(conn->rx_skb);
3674 conn->rx_skb = NULL;
3675 conn->rx_len = 0;
3676 l2cap_conn_unreliable(conn, ECOMM);
3677 }
3678
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003679 /* Start fragment always begin with Basic L2CAP header */
3680 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681 BT_ERR("Frame is too short (len %d)", skb->len);
3682 l2cap_conn_unreliable(conn, ECOMM);
3683 goto drop;
3684 }
3685
3686 hdr = (struct l2cap_hdr *) skb->data;
3687 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003688 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689
3690 if (len == skb->len) {
3691 /* Complete frame received */
3692 l2cap_recv_frame(conn, skb);
3693 return 0;
3694 }
3695
3696 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3697
3698 if (skb->len > len) {
3699 BT_ERR("Frame is too long (len %d, expected len %d)",
3700 skb->len, len);
3701 l2cap_conn_unreliable(conn, ECOMM);
3702 goto drop;
3703 }
3704
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003705 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
3706
3707 if (sk && l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
3708 BT_ERR("Frame exceeding recv MTU (len %d, MTU %d)",
3709 len, l2cap_pi(sk)->imtu);
3710 bh_unlock_sock(sk);
3711 l2cap_conn_unreliable(conn, ECOMM);
3712 goto drop;
3713 }
3714
3715 if (sk)
3716 bh_unlock_sock(sk);
3717
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003719 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
3720 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721 goto drop;
3722
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003723 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003724 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725 conn->rx_len = len - skb->len;
3726 } else {
3727 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
3728
3729 if (!conn->rx_len) {
3730 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
3731 l2cap_conn_unreliable(conn, ECOMM);
3732 goto drop;
3733 }
3734
3735 if (skb->len > conn->rx_len) {
3736 BT_ERR("Fragment is too long (len %d, expected %d)",
3737 skb->len, conn->rx_len);
3738 kfree_skb(conn->rx_skb);
3739 conn->rx_skb = NULL;
3740 conn->rx_len = 0;
3741 l2cap_conn_unreliable(conn, ECOMM);
3742 goto drop;
3743 }
3744
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003745 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003746 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747 conn->rx_len -= skb->len;
3748
3749 if (!conn->rx_len) {
3750 /* Complete frame received */
3751 l2cap_recv_frame(conn, conn->rx_skb);
3752 conn->rx_skb = NULL;
3753 }
3754 }
3755
3756drop:
3757 kfree_skb(skb);
3758 return 0;
3759}
3760
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003761static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003762{
3763 struct sock *sk;
3764 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765
3766 read_lock_bh(&l2cap_sk_list.lock);
3767
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003768 sk_for_each(sk, node, &l2cap_sk_list.head) {
3769 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003771 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
3772 batostr(&bt_sk(sk)->src),
3773 batostr(&bt_sk(sk)->dst),
3774 sk->sk_state, __le16_to_cpu(pi->psm),
3775 pi->scid, pi->dcid,
3776 pi->imtu, pi->omtu, pi->sec_level);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003777 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003780
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003781 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003782}
3783
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003784static int l2cap_debugfs_open(struct inode *inode, struct file *file)
3785{
3786 return single_open(file, l2cap_debugfs_show, inode->i_private);
3787}
3788
3789static const struct file_operations l2cap_debugfs_fops = {
3790 .open = l2cap_debugfs_open,
3791 .read = seq_read,
3792 .llseek = seq_lseek,
3793 .release = single_release,
3794};
3795
3796static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798static struct hci_proto l2cap_hci_proto = {
3799 .name = "L2CAP",
3800 .id = HCI_PROTO_L2CAP,
3801 .connect_ind = l2cap_connect_ind,
3802 .connect_cfm = l2cap_connect_cfm,
3803 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01003804 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003805 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806 .recv_acldata = l2cap_recv_acldata
3807};
3808
3809static int __init l2cap_init(void)
3810{
3811 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003812
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02003813 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814 if (err < 0)
3815 return err;
3816
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003817 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04003818 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02003819 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003820 goto error;
3821 }
3822
3823 err = hci_register_proto(&l2cap_hci_proto);
3824 if (err < 0) {
3825 BT_ERR("L2CAP protocol registration failed");
3826 bt_sock_unregister(BTPROTO_L2CAP);
3827 goto error;
3828 }
3829
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003830 if (bt_debugfs) {
3831 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
3832 bt_debugfs, NULL, &l2cap_debugfs_fops);
3833 if (!l2cap_debugfs)
3834 BT_ERR("Failed to create L2CAP debug file");
3835 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836
3837 BT_INFO("L2CAP ver %s", VERSION);
3838 BT_INFO("L2CAP socket layer initialized");
3839
3840 return 0;
3841
3842error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04003843 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02003844 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845 return err;
3846}
3847
3848static void __exit l2cap_exit(void)
3849{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003850 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003852 flush_workqueue(_busy_wq);
3853 destroy_workqueue(_busy_wq);
3854
Linus Torvalds1da177e2005-04-16 15:20:36 -07003855 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
3856 BT_ERR("L2CAP protocol unregistration failed");
3857
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02003858 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859}
3860
3861void l2cap_load(void)
3862{
3863 /* Dummy function to trigger automatic L2CAP module loading by
3864 * other modules that use L2CAP sockets but don't use any other
3865 * symbols from it. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003866}
3867EXPORT_SYMBOL(l2cap_load);
3868
3869module_init(l2cap_init);
3870module_exit(l2cap_exit);
3871
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003872module_param(disable_ertm, bool, 0644);
3873MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07003874
Marcel Holtmann63fbd242008-08-18 13:23:53 +02003875MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION);
3877MODULE_VERSION(VERSION);
3878MODULE_LICENSE("GPL");
3879MODULE_ALIAS("bt-proto-0");