blob: a72d6e4eab4f9dae97f9c4e006e51fd14d77141d [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2000-2001 Qualcomm Incorporated
Gustavo F. Padovance5706b2010-07-13 11:57:11 -03004 Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Gustavo F. Padovan5d8868f2010-07-16 16:18:39 -03005 Copyright (C) 2010 Google Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
7 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation;
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
16 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090017 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
18 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090022 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
23 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 SOFTWARE IS DISCLAIMED.
25*/
26
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020027/* Bluetooth L2CAP core. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30
31#include <linux/types.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080032#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/errno.h>
34#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/poll.h>
38#include <linux/fcntl.h>
39#include <linux/init.h>
40#include <linux/interrupt.h>
41#include <linux/socket.h>
42#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/list.h>
Marcel Holtmannbe9d1222005-11-08 09:57:38 -080044#include <linux/device.h>
Marcel Holtmannaef7d972010-03-21 05:27:45 +010045#include <linux/debugfs.h>
46#include <linux/seq_file.h>
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -030047#include <linux/uaccess.h>
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -030048#include <linux/crc16.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/sock.h>
50
51#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <asm/unaligned.h>
53
54#include <net/bluetooth/bluetooth.h>
55#include <net/bluetooth/hci_core.h>
56#include <net/bluetooth/l2cap.h>
57
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020058int disable_ertm;
Marcel Holtmannf0709e02007-10-20 13:38:51 +020059
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -070060static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
Marcel Holtmanne1027a72009-02-09 09:18:02 +010061static u8 l2cap_fixed_chan[8] = { 0x02, };
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030063static struct workqueue_struct *_busy_wq;
64
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -020065struct bt_sock_list l2cap_sk_list = {
Robert P. J. Dayd5fb2962008-03-28 16:17:38 -070066 .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070067};
68
Gustavo F. Padovan1890d362010-05-01 16:15:44 -030069static void l2cap_busy_work(struct work_struct *work);
70
Linus Torvalds1da177e2005-04-16 15:20:36 -070071static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
72 u8 code, u8 ident, u16 dlen, void *data);
73
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -030074static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
75
Marcel Holtmann01394182006-07-03 10:02:46 +020076/* ---- L2CAP channels ---- */
77static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
78{
79 struct sock *s;
80 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
81 if (l2cap_pi(s)->dcid == cid)
82 break;
83 }
84 return s;
85}
86
87static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
88{
89 struct sock *s;
90 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
91 if (l2cap_pi(s)->scid == cid)
92 break;
93 }
94 return s;
95}
96
97/* Find channel with given SCID.
98 * Returns locked socket */
99static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
100{
101 struct sock *s;
102 read_lock(&l->lock);
103 s = __l2cap_get_chan_by_scid(l, cid);
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300104 if (s)
105 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200106 read_unlock(&l->lock);
107 return s;
108}
109
110static struct sock *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
111{
112 struct sock *s;
113 for (s = l->head; s; s = l2cap_pi(s)->next_c) {
114 if (l2cap_pi(s)->ident == ident)
115 break;
116 }
117 return s;
118}
119
120static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
121{
122 struct sock *s;
123 read_lock(&l->lock);
124 s = __l2cap_get_chan_by_ident(l, ident);
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300125 if (s)
126 bh_lock_sock(s);
Marcel Holtmann01394182006-07-03 10:02:46 +0200127 read_unlock(&l->lock);
128 return s;
129}
130
131static u16 l2cap_alloc_cid(struct l2cap_chan_list *l)
132{
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300133 u16 cid = L2CAP_CID_DYN_START;
Marcel Holtmann01394182006-07-03 10:02:46 +0200134
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300135 for (; cid < L2CAP_CID_DYN_END; cid++) {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300136 if (!__l2cap_get_chan_by_scid(l, cid))
Marcel Holtmann01394182006-07-03 10:02:46 +0200137 return cid;
138 }
139
140 return 0;
141}
142
143static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct sock *sk)
144{
145 sock_hold(sk);
146
147 if (l->head)
148 l2cap_pi(l->head)->prev_c = sk;
149
150 l2cap_pi(sk)->next_c = l->head;
151 l2cap_pi(sk)->prev_c = NULL;
152 l->head = sk;
153}
154
155static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk)
156{
157 struct sock *next = l2cap_pi(sk)->next_c, *prev = l2cap_pi(sk)->prev_c;
158
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200159 write_lock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200160 if (sk == l->head)
161 l->head = next;
162
163 if (next)
164 l2cap_pi(next)->prev_c = prev;
165 if (prev)
166 l2cap_pi(prev)->next_c = next;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200167 write_unlock_bh(&l->lock);
Marcel Holtmann01394182006-07-03 10:02:46 +0200168
169 __sock_put(sk);
170}
171
172static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
173{
174 struct l2cap_chan_list *l = &conn->chan_list;
175
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300176 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
177 l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
Marcel Holtmann01394182006-07-03 10:02:46 +0200178
Marcel Holtmann2950f212009-02-12 14:02:50 +0100179 conn->disc_reason = 0x13;
180
Marcel Holtmann01394182006-07-03 10:02:46 +0200181 l2cap_pi(sk)->conn = conn;
182
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300183 if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200184 /* Alloc CID for connection-oriented socket */
185 l2cap_pi(sk)->scid = l2cap_alloc_cid(l);
186 } else if (sk->sk_type == SOCK_DGRAM) {
187 /* Connectionless socket */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300188 l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
189 l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
Marcel Holtmann01394182006-07-03 10:02:46 +0200190 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
191 } else {
192 /* Raw socket can send/recv signalling messages only */
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -0300193 l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
194 l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
Marcel Holtmann01394182006-07-03 10:02:46 +0200195 l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
196 }
197
198 __l2cap_chan_link(l, sk);
199
200 if (parent)
201 bt_accept_enqueue(parent, sk);
202}
203
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900204/* Delete channel.
Marcel Holtmann01394182006-07-03 10:02:46 +0200205 * Must be called on the locked socket. */
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200206void l2cap_chan_del(struct sock *sk, int err)
Marcel Holtmann01394182006-07-03 10:02:46 +0200207{
208 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
209 struct sock *parent = bt_sk(sk)->parent;
210
211 l2cap_sock_clear_timer(sk);
212
213 BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
214
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900215 if (conn) {
Marcel Holtmann01394182006-07-03 10:02:46 +0200216 /* Unlink from channel list */
217 l2cap_chan_unlink(&conn->chan_list, sk);
218 l2cap_pi(sk)->conn = NULL;
219 hci_conn_put(conn->hcon);
220 }
221
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200222 sk->sk_state = BT_CLOSED;
Marcel Holtmann01394182006-07-03 10:02:46 +0200223 sock_set_flag(sk, SOCK_ZAPPED);
224
225 if (err)
226 sk->sk_err = err;
227
228 if (parent) {
229 bt_accept_unlink(sk);
230 parent->sk_data_ready(parent, 0);
231 } else
232 sk->sk_state_change(sk);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300233
234 skb_queue_purge(TX_QUEUE(sk));
235
236 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
237 struct srej_list *l, *tmp;
238
239 del_timer(&l2cap_pi(sk)->retrans_timer);
240 del_timer(&l2cap_pi(sk)->monitor_timer);
241 del_timer(&l2cap_pi(sk)->ack_timer);
242
243 skb_queue_purge(SREJ_QUEUE(sk));
244 skb_queue_purge(BUSY_QUEUE(sk));
245
246 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
247 list_del(&l->list);
248 kfree(l);
249 }
250 }
Marcel Holtmann01394182006-07-03 10:02:46 +0200251}
252
Johan Hedberg8556edd32011-01-19 12:06:50 +0530253static inline u8 l2cap_get_auth_type(struct sock *sk)
254{
255 if (sk->sk_type == SOCK_RAW) {
256 switch (l2cap_pi(sk)->sec_level) {
257 case BT_SECURITY_HIGH:
258 return HCI_AT_DEDICATED_BONDING_MITM;
259 case BT_SECURITY_MEDIUM:
260 return HCI_AT_DEDICATED_BONDING;
261 default:
262 return HCI_AT_NO_BONDING;
263 }
264 } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
265 if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
266 l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
267
268 if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
269 return HCI_AT_NO_BONDING_MITM;
270 else
271 return HCI_AT_NO_BONDING;
272 } else {
273 switch (l2cap_pi(sk)->sec_level) {
274 case BT_SECURITY_HIGH:
275 return HCI_AT_GENERAL_BONDING_MITM;
276 case BT_SECURITY_MEDIUM:
277 return HCI_AT_GENERAL_BONDING;
278 default:
279 return HCI_AT_NO_BONDING;
280 }
281 }
282}
283
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200284/* Service level security */
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100285static inline int l2cap_check_security(struct sock *sk)
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200286{
287 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100288 __u8 auth_type;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200289
Johan Hedberg8556edd32011-01-19 12:06:50 +0530290 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100291
292 return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
293 auth_type);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200294}
295
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200296u8 l2cap_get_ident(struct l2cap_conn *conn)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200297{
298 u8 id;
299
300 /* Get next available identificator.
301 * 1 - 128 are used by kernel.
302 * 129 - 199 are reserved.
303 * 200 - 254 are used by utilities like l2ping, etc.
304 */
305
306 spin_lock_bh(&conn->lock);
307
308 if (++conn->tx_ident > 128)
309 conn->tx_ident = 1;
310
311 id = conn->tx_ident;
312
313 spin_unlock_bh(&conn->lock);
314
315 return id;
316}
317
Gustavo F. Padovan68983252011-02-04 03:02:31 -0200318void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200319{
320 struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200321 u8 flags;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200322
323 BT_DBG("code 0x%2.2x", code);
324
325 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300326 return;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200327
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200328 if (lmp_no_flush_capable(conn->hcon->hdev))
329 flags = ACL_START_NO_FLUSH;
330 else
331 flags = ACL_START;
332
333 hci_send_acl(conn->hcon, skb, flags);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200334}
335
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300336static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300337{
338 struct sk_buff *skb;
339 struct l2cap_hdr *lh;
340 struct l2cap_conn *conn = pi->conn;
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300341 struct sock *sk = (struct sock *)pi;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300342 int count, hlen = L2CAP_HDR_SIZE + 2;
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200343 u8 flags;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300344
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300345 if (sk->sk_state != BT_CONNECTED)
346 return;
347
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300348 if (pi->fcs == L2CAP_FCS_CRC16)
349 hlen += 2;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300350
351 BT_DBG("pi %p, control 0x%2.2x", pi, control);
352
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300353 count = min_t(unsigned int, conn->mtu, hlen);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300354 control |= L2CAP_CTRL_FRAME_TYPE;
355
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -0300356 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
357 control |= L2CAP_CTRL_FINAL;
358 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
359 }
360
Gustavo F. Padovanf0946cc2010-05-01 16:15:37 -0300361 if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
362 control |= L2CAP_CTRL_POLL;
363 pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
364 }
365
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300366 skb = bt_skb_alloc(count, GFP_ATOMIC);
367 if (!skb)
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300368 return;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300369
370 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300371 lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300372 lh->cid = cpu_to_le16(pi->dcid);
373 put_unaligned_le16(control, skb_put(skb, 2));
374
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300375 if (pi->fcs == L2CAP_FCS_CRC16) {
376 u16 fcs = crc16(0, (u8 *)lh, count - 2);
377 put_unaligned_le16(fcs, skb_put(skb, 2));
378 }
379
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200380 if (lmp_no_flush_capable(conn->hcon->hdev))
381 flags = ACL_START_NO_FLUSH;
382 else
383 flags = ACL_START;
384
385 hci_send_acl(pi->conn->hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300386}
387
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300388static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300389{
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300390 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300391 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -0300392 pi->conn_state |= L2CAP_CONN_RNR_SENT;
393 } else
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300394 control |= L2CAP_SUPER_RCV_READY;
395
Gustavo F. Padovan2ab25cd2009-10-03 02:34:40 -0300396 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
397
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300398 l2cap_send_sframe(pi, control);
Gustavo F. Padovan7e743092009-08-26 04:04:03 -0300399}
400
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300401static inline int __l2cap_no_conn_pending(struct sock *sk)
402{
403 return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
404}
405
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200406static void l2cap_do_start(struct sock *sk)
407{
408 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
409
410 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
Marcel Holtmann984947d2009-02-06 23:35:19 +0100411 if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
412 return;
413
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300414 if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200415 struct l2cap_conn_req req;
416 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
417 req.psm = l2cap_pi(sk)->psm;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200418
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200419 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +0300420 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200421
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200422 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200423 L2CAP_CONN_REQ, sizeof(req), &req);
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200424 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200425 } else {
426 struct l2cap_info_req req;
427 req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
428
429 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
430 conn->info_ident = l2cap_get_ident(conn);
431
432 mod_timer(&conn->info_timer, jiffies +
433 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
434
435 l2cap_send_cmd(conn, conn->info_ident,
436 L2CAP_INFO_REQ, sizeof(req), &req);
437 }
438}
439
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300440static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
441{
442 u32 local_feat_mask = l2cap_feat_mask;
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -0300443 if (!disable_ertm)
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300444 local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
445
446 switch (mode) {
447 case L2CAP_MODE_ERTM:
448 return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
449 case L2CAP_MODE_STREAMING:
450 return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
451 default:
452 return 0x00;
453 }
454}
455
Gustavo F. Padovan6de07022011-02-04 03:35:20 -0200456void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300457{
458 struct l2cap_disconn_req req;
459
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300460 if (!conn)
461 return;
462
463 skb_queue_purge(TX_QUEUE(sk));
464
465 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
466 del_timer(&l2cap_pi(sk)->retrans_timer);
467 del_timer(&l2cap_pi(sk)->monitor_timer);
468 del_timer(&l2cap_pi(sk)->ack_timer);
469 }
470
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300471 req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
472 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
473 l2cap_send_cmd(conn, l2cap_get_ident(conn),
474 L2CAP_DISCONN_REQ, sizeof(req), &req);
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300475
476 sk->sk_state = BT_DISCONN;
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300477 sk->sk_err = err;
Gustavo F. Padovan22121fc2009-07-23 10:27:23 -0300478}
479
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480/* ---- L2CAP connections ---- */
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200481static void l2cap_conn_start(struct l2cap_conn *conn)
482{
483 struct l2cap_chan_list *l = &conn->chan_list;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300484 struct sock_del_list del, *tmp1, *tmp2;
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200485 struct sock *sk;
486
487 BT_DBG("conn %p", conn);
488
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300489 INIT_LIST_HEAD(&del.list);
490
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200491 read_lock(&l->lock);
492
493 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
494 bh_lock_sock(sk);
495
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300496 if (sk->sk_type != SOCK_SEQPACKET &&
497 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200498 bh_unlock_sock(sk);
499 continue;
500 }
501
502 if (sk->sk_state == BT_CONNECT) {
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300503 struct l2cap_conn_req req;
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300504
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300505 if (!l2cap_check_security(sk) ||
506 !__l2cap_no_conn_pending(sk)) {
507 bh_unlock_sock(sk);
508 continue;
Marcel Holtmannb1235d72008-07-14 20:13:54 +0200509 }
Gustavo F. Padovan47731de2010-07-09 16:38:35 -0300510
511 if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
512 conn->feat_mask)
513 && l2cap_pi(sk)->conf_state &
514 L2CAP_CONF_STATE2_DEVICE) {
515 tmp1 = kzalloc(sizeof(struct sock_del_list),
516 GFP_ATOMIC);
517 tmp1->sk = sk;
518 list_add_tail(&tmp1->list, &del.list);
519 bh_unlock_sock(sk);
520 continue;
521 }
522
523 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
524 req.psm = l2cap_pi(sk)->psm;
525
526 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
527 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
528
529 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
530 L2CAP_CONN_REQ, sizeof(req), &req);
531
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200532 } else if (sk->sk_state == BT_CONNECT2) {
533 struct l2cap_conn_rsp rsp;
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300534 char buf[128];
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200535 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
536 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
537
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100538 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +0100539 if (bt_sk(sk)->defer_setup) {
540 struct sock *parent = bt_sk(sk)->parent;
541 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
542 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
543 parent->sk_data_ready(parent, 0);
544
545 } else {
546 sk->sk_state = BT_CONFIG;
547 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
548 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
549 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200550 } else {
551 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
552 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
553 }
554
555 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
556 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -0300557
558 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
559 rsp.result != L2CAP_CR_SUCCESS) {
560 bh_unlock_sock(sk);
561 continue;
562 }
563
564 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
565 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
566 l2cap_build_conf_req(sk, buf), buf);
567 l2cap_pi(sk)->num_conf_req++;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200568 }
569
570 bh_unlock_sock(sk);
571 }
572
573 read_unlock(&l->lock);
Gustavo F. Padovancf6c2c02010-06-07 20:54:45 -0300574
575 list_for_each_entry_safe(tmp1, tmp2, &del.list, list) {
576 bh_lock_sock(tmp1->sk);
577 __l2cap_sock_close(tmp1->sk, ECONNRESET);
578 bh_unlock_sock(tmp1->sk);
579 list_del(&tmp1->list);
580 kfree(tmp1);
581 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200582}
583
584static void l2cap_conn_ready(struct l2cap_conn *conn)
585{
586 struct l2cap_chan_list *l = &conn->chan_list;
587 struct sock *sk;
588
589 BT_DBG("conn %p", conn);
590
591 read_lock(&l->lock);
592
593 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
594 bh_lock_sock(sk);
595
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300596 if (sk->sk_type != SOCK_SEQPACKET &&
597 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200598 l2cap_sock_clear_timer(sk);
599 sk->sk_state = BT_CONNECTED;
600 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200601 } else if (sk->sk_state == BT_CONNECT)
602 l2cap_do_start(sk);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200603
604 bh_unlock_sock(sk);
605 }
606
607 read_unlock(&l->lock);
608}
609
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200610/* Notify sockets that we cannot guaranty reliability anymore */
611static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
612{
613 struct l2cap_chan_list *l = &conn->chan_list;
614 struct sock *sk;
615
616 BT_DBG("conn %p", conn);
617
618 read_lock(&l->lock);
619
620 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100621 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200622 sk->sk_err = err;
623 }
624
625 read_unlock(&l->lock);
626}
627
628static void l2cap_info_timeout(unsigned long arg)
629{
630 struct l2cap_conn *conn = (void *) arg;
631
Marcel Holtmann984947d2009-02-06 23:35:19 +0100632 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100633 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100634
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200635 l2cap_conn_start(conn);
636}
637
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
639{
Marcel Holtmann01394182006-07-03 10:02:46 +0200640 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641
Marcel Holtmann01394182006-07-03 10:02:46 +0200642 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 return conn;
644
Marcel Holtmann01394182006-07-03 10:02:46 +0200645 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
646 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648
649 hcon->l2cap_data = conn;
650 conn->hcon = hcon;
651
Marcel Holtmann01394182006-07-03 10:02:46 +0200652 BT_DBG("hcon %p conn %p", hcon, conn);
653
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 conn->mtu = hcon->hdev->acl_mtu;
655 conn->src = &hcon->hdev->bdaddr;
656 conn->dst = &hcon->dst;
657
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200658 conn->feat_mask = 0;
659
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 spin_lock_init(&conn->lock);
661 rwlock_init(&conn->chan_list.lock);
662
Dave Young45054dc2009-10-18 20:28:30 +0000663 setup_timer(&conn->info_timer, l2cap_info_timeout,
664 (unsigned long) conn);
665
Marcel Holtmann2950f212009-02-12 14:02:50 +0100666 conn->disc_reason = 0x13;
667
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 return conn;
669}
670
Marcel Holtmann01394182006-07-03 10:02:46 +0200671static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672{
Marcel Holtmann01394182006-07-03 10:02:46 +0200673 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 struct sock *sk;
675
Marcel Holtmann01394182006-07-03 10:02:46 +0200676 if (!conn)
677 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678
679 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
680
Wei Yongjun7585b972009-02-25 18:29:52 +0800681 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682
683 /* Kill channels */
684 while ((sk = conn->chan_list.head)) {
685 bh_lock_sock(sk);
686 l2cap_chan_del(sk, err);
687 bh_unlock_sock(sk);
688 l2cap_sock_kill(sk);
689 }
690
Dave Young8e8440f2008-03-03 12:18:55 -0800691 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
692 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800693
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 hcon->l2cap_data = NULL;
695 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696}
697
698static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
699{
700 struct l2cap_chan_list *l = &conn->chan_list;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200701 write_lock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 __l2cap_chan_add(conn, sk, parent);
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200703 write_unlock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704}
705
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707
708/* Find socket with psm and source bdaddr.
709 * Returns closest match.
710 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000711static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712{
713 struct sock *sk = NULL, *sk1 = NULL;
714 struct hlist_node *node;
715
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000716 read_lock(&l2cap_sk_list.lock);
717
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 sk_for_each(sk, node, &l2cap_sk_list.head) {
719 if (state && sk->sk_state != state)
720 continue;
721
722 if (l2cap_pi(sk)->psm == psm) {
723 /* Exact match. */
724 if (!bacmp(&bt_sk(sk)->src, src))
725 break;
726
727 /* Closest match */
728 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
729 sk1 = sk;
730 }
731 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000734
735 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736}
737
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200738int l2cap_do_connect(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739{
740 bdaddr_t *src = &bt_sk(sk)->src;
741 bdaddr_t *dst = &bt_sk(sk)->dst;
742 struct l2cap_conn *conn;
743 struct hci_conn *hcon;
744 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200745 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200746 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100748 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
749 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300751 hdev = hci_get_route(dst, src);
752 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 return -EHOSTUNREACH;
754
755 hci_dev_lock_bh(hdev);
756
757 err = -ENOMEM;
758
Johan Hedberg8556edd32011-01-19 12:06:50 +0530759 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200760
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100761 hcon = hci_connect(hdev, ACL_LINK, dst,
762 l2cap_pi(sk)->sec_level, auth_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 if (!hcon)
764 goto done;
765
766 conn = l2cap_conn_add(hcon, 0);
767 if (!conn) {
768 hci_conn_put(hcon);
769 goto done;
770 }
771
772 err = 0;
773
774 /* Update source addr of the socket */
775 bacpy(src, conn->src);
776
777 l2cap_chan_add(conn, sk, NULL);
778
779 sk->sk_state = BT_CONNECT;
780 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
781
782 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300783 if (sk->sk_type != SOCK_SEQPACKET &&
784 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530786 if (l2cap_check_security(sk))
787 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200788 } else
789 l2cap_do_start(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 }
791
792done:
793 hci_dev_unlock_bh(hdev);
794 hci_dev_put(hdev);
795 return err;
796}
797
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200798int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300799{
800 DECLARE_WAITQUEUE(wait, current);
801 int err = 0;
802 int timeo = HZ/5;
803
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200804 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300805 while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
806 set_current_state(TASK_INTERRUPTIBLE);
807
808 if (!timeo)
809 timeo = HZ/5;
810
811 if (signal_pending(current)) {
812 err = sock_intr_errno(timeo);
813 break;
814 }
815
816 release_sock(sk);
817 timeo = schedule_timeout(timeo);
818 lock_sock(sk);
819
820 err = sock_error(sk);
821 if (err)
822 break;
823 }
824 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200825 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300826 return err;
827}
828
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300829static void l2cap_monitor_timeout(unsigned long arg)
830{
831 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300832
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300833 BT_DBG("sk %p", sk);
834
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300835 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300836 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300837 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200838 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300839 return;
840 }
841
842 l2cap_pi(sk)->retry_count++;
843 __mod_monitor_timer();
844
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -0300845 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300846 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300847}
848
849static void l2cap_retrans_timeout(unsigned long arg)
850{
851 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300852
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300853 BT_DBG("sk %p", sk);
854
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300855 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300856 l2cap_pi(sk)->retry_count = 1;
857 __mod_monitor_timer();
858
859 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
860
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -0300861 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300862 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300863}
864
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300865static void l2cap_drop_acked_frames(struct sock *sk)
866{
867 struct sk_buff *skb;
868
Gustavo F. Padovan812e7372010-05-01 16:15:42 -0300869 while ((skb = skb_peek(TX_QUEUE(sk))) &&
870 l2cap_pi(sk)->unacked_frames) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300871 if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
872 break;
873
874 skb = skb_dequeue(TX_QUEUE(sk));
875 kfree_skb(skb);
876
877 l2cap_pi(sk)->unacked_frames--;
878 }
879
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300880 if (!l2cap_pi(sk)->unacked_frames)
881 del_timer(&l2cap_pi(sk)->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300882}
883
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200884void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300885{
886 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200887 struct hci_conn *hcon = pi->conn->hcon;
888 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300889
890 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
891
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200892 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
893 flags = ACL_START_NO_FLUSH;
894 else
895 flags = ACL_START;
896
897 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300898}
899
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200900void l2cap_streaming_send(struct sock *sk)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300901{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -0300902 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300903 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300904 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300905
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -0300906 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
907 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300908 control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -0300909 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300910
Gustavo F. Padovane8235c62010-05-01 16:15:36 -0300911 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -0300912 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
913 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300914 }
915
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -0300916 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300917
918 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300919 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300920}
921
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -0300922static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300923{
924 struct l2cap_pinfo *pi = l2cap_pi(sk);
925 struct sk_buff *skb, *tx_skb;
926 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300927
928 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300929 if (!skb)
930 return;
931
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300932 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300933 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300934 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300935
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300936 if (skb_queue_is_last(TX_QUEUE(sk), skb))
937 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300938
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300939 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300940
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300941 if (pi->remote_max_tx &&
942 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300943 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300944 return;
945 }
946
947 tx_skb = skb_clone(skb, GFP_ATOMIC);
948 bt_cb(skb)->retries++;
949 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -0300950
951 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
952 control |= L2CAP_CTRL_FINAL;
953 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
954 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -0300955
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300956 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
957 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -0300958
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300959 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
960
961 if (pi->fcs == L2CAP_FCS_CRC16) {
962 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
963 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
964 }
965
966 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300967}
968
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200969int l2cap_ertm_send(struct sock *sk)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300970{
971 struct sk_buff *skb, *tx_skb;
972 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300973 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300974 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300975
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300976 if (sk->sk_state != BT_CONNECTED)
977 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300978
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -0300979 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300980
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300981 if (pi->remote_max_tx &&
982 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300983 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300984 break;
985 }
986
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +0200987 tx_skb = skb_clone(skb, GFP_ATOMIC);
988
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300989 bt_cb(skb)->retries++;
990
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300991 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -0300992 control &= L2CAP_CTRL_SAR;
993
Gustavo F. Padovand5392c82010-05-01 16:15:36 -0300994 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
995 control |= L2CAP_CTRL_FINAL;
996 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
997 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -0300998 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300999 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1000 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1001
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001002
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001003 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001004 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1005 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1006 }
1007
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001008 l2cap_do_send(sk, tx_skb);
1009
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001010 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001011
1012 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1013 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1014
1015 pi->unacked_frames++;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001016 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001017
1018 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1019 sk->sk_send_head = NULL;
1020 else
1021 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001022
1023 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001024 }
1025
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001026 return nsent;
1027}
1028
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001029static int l2cap_retransmit_frames(struct sock *sk)
1030{
1031 struct l2cap_pinfo *pi = l2cap_pi(sk);
1032 int ret;
1033
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001034 if (!skb_queue_empty(TX_QUEUE(sk)))
1035 sk->sk_send_head = TX_QUEUE(sk)->next;
1036
1037 pi->next_tx_seq = pi->expected_ack_seq;
1038 ret = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001039 return ret;
1040}
1041
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001042static void l2cap_send_ack(struct l2cap_pinfo *pi)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001043{
1044 struct sock *sk = (struct sock *)pi;
1045 u16 control = 0;
1046
1047 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1048
1049 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1050 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001051 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001052 l2cap_send_sframe(pi, control);
1053 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001054 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001055
Gustavo F. Padovane0f66212010-06-21 18:50:49 -03001056 if (l2cap_ertm_send(sk) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001057 return;
1058
1059 control |= L2CAP_SUPER_RCV_READY;
1060 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001061}
1062
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001063static void l2cap_send_srejtail(struct sock *sk)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001064{
1065 struct srej_list *tail;
1066 u16 control;
1067
1068 control = L2CAP_SUPER_SELECT_REJECT;
1069 control |= L2CAP_CTRL_FINAL;
1070
1071 tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
1072 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1073
1074 l2cap_send_sframe(l2cap_pi(sk), control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001075}
1076
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001077static 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 -07001078{
1079 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001080 struct sk_buff **frag;
1081 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001083 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001084 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085
1086 sent += count;
1087 len -= count;
1088
1089 /* Continuation fragments (no L2CAP header) */
1090 frag = &skb_shinfo(skb)->frag_list;
1091 while (len) {
1092 count = min_t(unsigned int, conn->mtu, len);
1093
1094 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1095 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001096 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001097 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1098 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
1100 sent += count;
1101 len -= count;
1102
1103 frag = &(*frag)->next;
1104 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105
1106 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001107}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001109struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001110{
1111 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1112 struct sk_buff *skb;
1113 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1114 struct l2cap_hdr *lh;
1115
1116 BT_DBG("sk %p len %d", sk, (int)len);
1117
1118 count = min_t(unsigned int, (conn->mtu - hlen), len);
1119 skb = bt_skb_send_alloc(sk, count + hlen,
1120 msg->msg_flags & MSG_DONTWAIT, &err);
1121 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001122 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001123
1124 /* Create L2CAP header */
1125 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1126 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1127 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1128 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1129
1130 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1131 if (unlikely(err < 0)) {
1132 kfree_skb(skb);
1133 return ERR_PTR(err);
1134 }
1135 return skb;
1136}
1137
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001138struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001139{
1140 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1141 struct sk_buff *skb;
1142 int err, count, hlen = L2CAP_HDR_SIZE;
1143 struct l2cap_hdr *lh;
1144
1145 BT_DBG("sk %p len %d", sk, (int)len);
1146
1147 count = min_t(unsigned int, (conn->mtu - hlen), len);
1148 skb = bt_skb_send_alloc(sk, count + hlen,
1149 msg->msg_flags & MSG_DONTWAIT, &err);
1150 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001151 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001152
1153 /* Create L2CAP header */
1154 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1155 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1156 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1157
1158 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1159 if (unlikely(err < 0)) {
1160 kfree_skb(skb);
1161 return ERR_PTR(err);
1162 }
1163 return skb;
1164}
1165
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001166struct 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 -03001167{
1168 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1169 struct sk_buff *skb;
1170 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1171 struct l2cap_hdr *lh;
1172
1173 BT_DBG("sk %p len %d", sk, (int)len);
1174
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001175 if (!conn)
1176 return ERR_PTR(-ENOTCONN);
1177
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001178 if (sdulen)
1179 hlen += 2;
1180
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001181 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1182 hlen += 2;
1183
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001184 count = min_t(unsigned int, (conn->mtu - hlen), len);
1185 skb = bt_skb_send_alloc(sk, count + hlen,
1186 msg->msg_flags & MSG_DONTWAIT, &err);
1187 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001188 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001189
1190 /* Create L2CAP header */
1191 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1192 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1193 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1194 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001195 if (sdulen)
1196 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001197
1198 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1199 if (unlikely(err < 0)) {
1200 kfree_skb(skb);
1201 return ERR_PTR(err);
1202 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001203
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001204 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1205 put_unaligned_le16(0, skb_put(skb, 2));
1206
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001207 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001208 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209}
1210
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001211int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001212{
1213 struct l2cap_pinfo *pi = l2cap_pi(sk);
1214 struct sk_buff *skb;
1215 struct sk_buff_head sar_queue;
1216 u16 control;
1217 size_t size = 0;
1218
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001219 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001220 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001221 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001222 if (IS_ERR(skb))
1223 return PTR_ERR(skb);
1224
1225 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001226 len -= pi->remote_mps;
1227 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001228
1229 while (len > 0) {
1230 size_t buflen;
1231
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001232 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001233 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001234 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001235 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001236 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001237 buflen = len;
1238 }
1239
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001240 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001241 if (IS_ERR(skb)) {
1242 skb_queue_purge(&sar_queue);
1243 return PTR_ERR(skb);
1244 }
1245
1246 __skb_queue_tail(&sar_queue, skb);
1247 len -= buflen;
1248 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001249 }
1250 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1251 if (sk->sk_send_head == NULL)
1252 sk->sk_send_head = sar_queue.next;
1253
1254 return size;
1255}
1256
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257static void l2cap_chan_ready(struct sock *sk)
1258{
1259 struct sock *parent = bt_sk(sk)->parent;
1260
1261 BT_DBG("sk %p, parent %p", sk, parent);
1262
1263 l2cap_pi(sk)->conf_state = 0;
1264 l2cap_sock_clear_timer(sk);
1265
1266 if (!parent) {
1267 /* Outgoing channel.
1268 * Wake up socket sleeping on connect.
1269 */
1270 sk->sk_state = BT_CONNECTED;
1271 sk->sk_state_change(sk);
1272 } else {
1273 /* Incoming channel.
1274 * Wake up socket sleeping on accept.
1275 */
1276 parent->sk_data_ready(parent, 0);
1277 }
1278}
1279
1280/* Copy frame to all raw sockets on that connection */
1281static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1282{
1283 struct l2cap_chan_list *l = &conn->chan_list;
1284 struct sk_buff *nskb;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001285 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286
1287 BT_DBG("conn %p", conn);
1288
1289 read_lock(&l->lock);
1290 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
1291 if (sk->sk_type != SOCK_RAW)
1292 continue;
1293
1294 /* Don't send frame to the socket it came from */
1295 if (skb->sk == sk)
1296 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001297 nskb = skb_clone(skb, GFP_ATOMIC);
1298 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 continue;
1300
1301 if (sock_queue_rcv_skb(sk, nskb))
1302 kfree_skb(nskb);
1303 }
1304 read_unlock(&l->lock);
1305}
1306
1307/* ---- L2CAP signalling commands ---- */
1308static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1309 u8 code, u8 ident, u16 dlen, void *data)
1310{
1311 struct sk_buff *skb, **frag;
1312 struct l2cap_cmd_hdr *cmd;
1313 struct l2cap_hdr *lh;
1314 int len, count;
1315
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001316 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1317 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318
1319 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1320 count = min_t(unsigned int, conn->mtu, len);
1321
1322 skb = bt_skb_alloc(count, GFP_ATOMIC);
1323 if (!skb)
1324 return NULL;
1325
1326 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001327 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03001328 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329
1330 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1331 cmd->code = code;
1332 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001333 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
1335 if (dlen) {
1336 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1337 memcpy(skb_put(skb, count), data, count);
1338 data += count;
1339 }
1340
1341 len -= skb->len;
1342
1343 /* Continuation fragments (no L2CAP header) */
1344 frag = &skb_shinfo(skb)->frag_list;
1345 while (len) {
1346 count = min_t(unsigned int, conn->mtu, len);
1347
1348 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1349 if (!*frag)
1350 goto fail;
1351
1352 memcpy(skb_put(*frag, count), data, count);
1353
1354 len -= count;
1355 data += count;
1356
1357 frag = &(*frag)->next;
1358 }
1359
1360 return skb;
1361
1362fail:
1363 kfree_skb(skb);
1364 return NULL;
1365}
1366
1367static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1368{
1369 struct l2cap_conf_opt *opt = *ptr;
1370 int len;
1371
1372 len = L2CAP_CONF_OPT_SIZE + opt->len;
1373 *ptr += len;
1374
1375 *type = opt->type;
1376 *olen = opt->len;
1377
1378 switch (opt->len) {
1379 case 1:
1380 *val = *((u8 *) opt->val);
1381 break;
1382
1383 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001384 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 break;
1386
1387 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001388 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 break;
1390
1391 default:
1392 *val = (unsigned long) opt->val;
1393 break;
1394 }
1395
1396 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1397 return len;
1398}
1399
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1401{
1402 struct l2cap_conf_opt *opt = *ptr;
1403
1404 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1405
1406 opt->type = type;
1407 opt->len = len;
1408
1409 switch (len) {
1410 case 1:
1411 *((u8 *) opt->val) = val;
1412 break;
1413
1414 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001415 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 break;
1417
1418 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001419 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 break;
1421
1422 default:
1423 memcpy(opt->val, (void *) val, len);
1424 break;
1425 }
1426
1427 *ptr += L2CAP_CONF_OPT_SIZE + len;
1428}
1429
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001430static void l2cap_ack_timeout(unsigned long arg)
1431{
1432 struct sock *sk = (void *) arg;
1433
1434 bh_lock_sock(sk);
1435 l2cap_send_ack(l2cap_pi(sk));
1436 bh_unlock_sock(sk);
1437}
1438
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001439static inline void l2cap_ertm_init(struct sock *sk)
1440{
1441 l2cap_pi(sk)->expected_ack_seq = 0;
1442 l2cap_pi(sk)->unacked_frames = 0;
1443 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03001444 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001445 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001446
1447 setup_timer(&l2cap_pi(sk)->retrans_timer,
1448 l2cap_retrans_timeout, (unsigned long) sk);
1449 setup_timer(&l2cap_pi(sk)->monitor_timer,
1450 l2cap_monitor_timeout, (unsigned long) sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001451 setup_timer(&l2cap_pi(sk)->ack_timer,
1452 l2cap_ack_timeout, (unsigned long) sk);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001453
1454 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001455 __skb_queue_head_init(BUSY_QUEUE(sk));
1456
1457 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001458
1459 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001460}
1461
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001462static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1463{
1464 switch (mode) {
1465 case L2CAP_MODE_STREAMING:
1466 case L2CAP_MODE_ERTM:
1467 if (l2cap_mode_supported(mode, remote_feat_mask))
1468 return mode;
1469 /* fall through */
1470 default:
1471 return L2CAP_MODE_BASIC;
1472 }
1473}
1474
Gustavo F. Padovan68983252011-02-04 03:02:31 -02001475int l2cap_build_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476{
1477 struct l2cap_pinfo *pi = l2cap_pi(sk);
1478 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001479 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 void *ptr = req->data;
1481
1482 BT_DBG("sk %p", sk);
1483
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001484 if (pi->num_conf_req || pi->num_conf_rsp)
1485 goto done;
1486
1487 switch (pi->mode) {
1488 case L2CAP_MODE_STREAMING:
1489 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001490 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001491 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001492
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001493 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001494 default:
1495 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1496 break;
1497 }
1498
1499done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001500 if (pi->imtu != L2CAP_DEFAULT_MTU)
1501 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1502
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001503 switch (pi->mode) {
1504 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001505 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1506 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1507 break;
1508
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001509 rfc.mode = L2CAP_MODE_BASIC;
1510 rfc.txwin_size = 0;
1511 rfc.max_transmit = 0;
1512 rfc.retrans_timeout = 0;
1513 rfc.monitor_timeout = 0;
1514 rfc.max_pdu_size = 0;
1515
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001516 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1517 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001518 break;
1519
1520 case L2CAP_MODE_ERTM:
1521 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001522 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001523 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001524 rfc.retrans_timeout = 0;
1525 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001526 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001527 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001528 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001529
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001530 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1531 (unsigned long) &rfc);
1532
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001533 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1534 break;
1535
1536 if (pi->fcs == L2CAP_FCS_NONE ||
1537 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1538 pi->fcs = L2CAP_FCS_NONE;
1539 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1540 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001541 break;
1542
1543 case L2CAP_MODE_STREAMING:
1544 rfc.mode = L2CAP_MODE_STREAMING;
1545 rfc.txwin_size = 0;
1546 rfc.max_transmit = 0;
1547 rfc.retrans_timeout = 0;
1548 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001549 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001550 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001551 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001552
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001553 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1554 (unsigned long) &rfc);
1555
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001556 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1557 break;
1558
1559 if (pi->fcs == L2CAP_FCS_NONE ||
1560 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1561 pi->fcs = L2CAP_FCS_NONE;
1562 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1563 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001564 break;
1565 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566
1567 /* FIXME: Need actual value of the flush timeout */
1568 //if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
1569 // l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to);
1570
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001571 req->dcid = cpu_to_le16(pi->dcid);
1572 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573
1574 return ptr - data;
1575}
1576
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001577static int l2cap_parse_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578{
1579 struct l2cap_pinfo *pi = l2cap_pi(sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001580 struct l2cap_conf_rsp *rsp = data;
1581 void *ptr = rsp->data;
1582 void *req = pi->conf_req;
1583 int len = pi->conf_len;
1584 int type, hint, olen;
1585 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001586 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001587 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001588 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001590 BT_DBG("sk %p", sk);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001591
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001592 while (len >= L2CAP_CONF_OPT_SIZE) {
1593 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001595 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001596 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001597
1598 switch (type) {
1599 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001600 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001601 break;
1602
1603 case L2CAP_CONF_FLUSH_TO:
1604 pi->flush_to = val;
1605 break;
1606
1607 case L2CAP_CONF_QOS:
1608 break;
1609
Marcel Holtmann6464f352007-10-20 13:39:51 +02001610 case L2CAP_CONF_RFC:
1611 if (olen == sizeof(rfc))
1612 memcpy(&rfc, (void *) val, olen);
1613 break;
1614
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001615 case L2CAP_CONF_FCS:
1616 if (val == L2CAP_FCS_NONE)
1617 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1618
1619 break;
1620
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001621 default:
1622 if (hint)
1623 break;
1624
1625 result = L2CAP_CONF_UNKNOWN;
1626 *((u8 *) ptr++) = type;
1627 break;
1628 }
1629 }
1630
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001631 if (pi->num_conf_rsp || pi->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001632 goto done;
1633
1634 switch (pi->mode) {
1635 case L2CAP_MODE_STREAMING:
1636 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001637 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1638 pi->mode = l2cap_select_mode(rfc.mode,
1639 pi->conn->feat_mask);
1640 break;
1641 }
1642
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001643 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001644 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001645
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001646 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001647 }
1648
1649done:
1650 if (pi->mode != rfc.mode) {
1651 result = L2CAP_CONF_UNACCEPT;
1652 rfc.mode = pi->mode;
1653
1654 if (pi->num_conf_rsp == 1)
1655 return -ECONNREFUSED;
1656
1657 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1658 sizeof(rfc), (unsigned long) &rfc);
1659 }
1660
1661
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001662 if (result == L2CAP_CONF_SUCCESS) {
1663 /* Configure output options and let the other side know
1664 * which ones we don't like. */
1665
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001666 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1667 result = L2CAP_CONF_UNACCEPT;
1668 else {
1669 pi->omtu = mtu;
1670 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1671 }
1672 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001673
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001674 switch (rfc.mode) {
1675 case L2CAP_MODE_BASIC:
1676 pi->fcs = L2CAP_FCS_NONE;
1677 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1678 break;
1679
1680 case L2CAP_MODE_ERTM:
1681 pi->remote_tx_win = rfc.txwin_size;
1682 pi->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001683
1684 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1685 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001686
1687 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001688
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001689 rfc.retrans_timeout =
1690 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1691 rfc.monitor_timeout =
1692 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001693
1694 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001695
1696 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1697 sizeof(rfc), (unsigned long) &rfc);
1698
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001699 break;
1700
1701 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001702 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1703 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001704
1705 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001706
1707 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001708
1709 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1710 sizeof(rfc), (unsigned long) &rfc);
1711
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001712 break;
1713
1714 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001715 result = L2CAP_CONF_UNACCEPT;
1716
1717 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001718 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001719 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001720
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001721 if (result == L2CAP_CONF_SUCCESS)
1722 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1723 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001724 rsp->scid = cpu_to_le16(pi->dcid);
1725 rsp->result = cpu_to_le16(result);
1726 rsp->flags = cpu_to_le16(0x0000);
1727
1728 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729}
1730
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001731static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1732{
1733 struct l2cap_pinfo *pi = l2cap_pi(sk);
1734 struct l2cap_conf_req *req = data;
1735 void *ptr = req->data;
1736 int type, olen;
1737 unsigned long val;
1738 struct l2cap_conf_rfc rfc;
1739
1740 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1741
1742 while (len >= L2CAP_CONF_OPT_SIZE) {
1743 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1744
1745 switch (type) {
1746 case L2CAP_CONF_MTU:
1747 if (val < L2CAP_DEFAULT_MIN_MTU) {
1748 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001749 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001750 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001751 pi->imtu = val;
1752 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001753 break;
1754
1755 case L2CAP_CONF_FLUSH_TO:
1756 pi->flush_to = val;
1757 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1758 2, pi->flush_to);
1759 break;
1760
1761 case L2CAP_CONF_RFC:
1762 if (olen == sizeof(rfc))
1763 memcpy(&rfc, (void *)val, olen);
1764
1765 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1766 rfc.mode != pi->mode)
1767 return -ECONNREFUSED;
1768
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001769 pi->fcs = 0;
1770
1771 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1772 sizeof(rfc), (unsigned long) &rfc);
1773 break;
1774 }
1775 }
1776
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001777 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1778 return -ECONNREFUSED;
1779
1780 pi->mode = rfc.mode;
1781
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001782 if (*result == L2CAP_CONF_SUCCESS) {
1783 switch (rfc.mode) {
1784 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001785 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1786 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001787 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001788 break;
1789 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001790 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001791 }
1792 }
1793
1794 req->dcid = cpu_to_le16(pi->dcid);
1795 req->flags = cpu_to_le16(0x0000);
1796
1797 return ptr - data;
1798}
1799
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001800static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801{
1802 struct l2cap_conf_rsp *rsp = data;
1803 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001805 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001807 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001808 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001809 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810
1811 return ptr - data;
1812}
1813
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001814static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1815{
1816 struct l2cap_pinfo *pi = l2cap_pi(sk);
1817 int type, olen;
1818 unsigned long val;
1819 struct l2cap_conf_rfc rfc;
1820
1821 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1822
1823 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1824 return;
1825
1826 while (len >= L2CAP_CONF_OPT_SIZE) {
1827 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1828
1829 switch (type) {
1830 case L2CAP_CONF_RFC:
1831 if (olen == sizeof(rfc))
1832 memcpy(&rfc, (void *)val, olen);
1833 goto done;
1834 }
1835 }
1836
1837done:
1838 switch (rfc.mode) {
1839 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001840 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1841 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001842 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1843 break;
1844 case L2CAP_MODE_STREAMING:
1845 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1846 }
1847}
1848
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001849static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1850{
1851 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
1852
1853 if (rej->reason != 0x0000)
1854 return 0;
1855
1856 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
1857 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001858 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01001859
1860 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01001861 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01001862
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001863 l2cap_conn_start(conn);
1864 }
1865
1866 return 0;
1867}
1868
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1870{
1871 struct l2cap_chan_list *list = &conn->chan_list;
1872 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
1873 struct l2cap_conn_rsp rsp;
Nathan Holsteind793fe82010-10-15 11:54:02 -04001874 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001875 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876
1877 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001878 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879
1880 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
1881
1882 /* Check if we have socket listening on psm */
1883 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
1884 if (!parent) {
1885 result = L2CAP_CR_BAD_PSM;
1886 goto sendresp;
1887 }
1888
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001889 bh_lock_sock(parent);
1890
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001891 /* Check if the ACL is secure enough (if not SDP) */
1892 if (psm != cpu_to_le16(0x0001) &&
1893 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01001894 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001895 result = L2CAP_CR_SEC_BLOCK;
1896 goto response;
1897 }
1898
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 result = L2CAP_CR_NO_MEM;
1900
1901 /* Check for backlog size */
1902 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001903 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 goto response;
1905 }
1906
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001907 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908 if (!sk)
1909 goto response;
1910
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02001911 write_lock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912
1913 /* Check if we already have channel with that dcid */
1914 if (__l2cap_get_chan_by_dcid(list, scid)) {
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02001915 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 sock_set_flag(sk, SOCK_ZAPPED);
1917 l2cap_sock_kill(sk);
1918 goto response;
1919 }
1920
1921 hci_conn_hold(conn->hcon);
1922
1923 l2cap_sock_init(sk, parent);
1924 bacpy(&bt_sk(sk)->src, conn->src);
1925 bacpy(&bt_sk(sk)->dst, conn->dst);
1926 l2cap_pi(sk)->psm = psm;
1927 l2cap_pi(sk)->dcid = scid;
1928
1929 __l2cap_chan_add(conn, sk, parent);
1930 dcid = l2cap_pi(sk)->scid;
1931
1932 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
1933
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 l2cap_pi(sk)->ident = cmd->ident;
1935
Marcel Holtmann984947d2009-02-06 23:35:19 +01001936 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001937 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001938 if (bt_sk(sk)->defer_setup) {
1939 sk->sk_state = BT_CONNECT2;
1940 result = L2CAP_CR_PEND;
1941 status = L2CAP_CS_AUTHOR_PEND;
1942 parent->sk_data_ready(parent, 0);
1943 } else {
1944 sk->sk_state = BT_CONFIG;
1945 result = L2CAP_CR_SUCCESS;
1946 status = L2CAP_CS_NO_INFO;
1947 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001948 } else {
1949 sk->sk_state = BT_CONNECT2;
1950 result = L2CAP_CR_PEND;
1951 status = L2CAP_CS_AUTHEN_PEND;
1952 }
1953 } else {
1954 sk->sk_state = BT_CONNECT2;
1955 result = L2CAP_CR_PEND;
1956 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957 }
1958
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02001959 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960
1961response:
1962 bh_unlock_sock(parent);
1963
1964sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001965 rsp.scid = cpu_to_le16(scid);
1966 rsp.dcid = cpu_to_le16(dcid);
1967 rsp.result = cpu_to_le16(result);
1968 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001970
1971 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
1972 struct l2cap_info_req info;
1973 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
1974
1975 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
1976 conn->info_ident = l2cap_get_ident(conn);
1977
1978 mod_timer(&conn->info_timer, jiffies +
1979 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
1980
1981 l2cap_send_cmd(conn, conn->info_ident,
1982 L2CAP_INFO_REQ, sizeof(info), &info);
1983 }
1984
Nathan Holsteind793fe82010-10-15 11:54:02 -04001985 if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001986 result == L2CAP_CR_SUCCESS) {
1987 u8 buf[128];
1988 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
1989 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1990 l2cap_build_conf_req(sk, buf), buf);
1991 l2cap_pi(sk)->num_conf_req++;
1992 }
1993
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 return 0;
1995}
1996
1997static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1998{
1999 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2000 u16 scid, dcid, result, status;
2001 struct sock *sk;
2002 u8 req[128];
2003
2004 scid = __le16_to_cpu(rsp->scid);
2005 dcid = __le16_to_cpu(rsp->dcid);
2006 result = __le16_to_cpu(rsp->result);
2007 status = __le16_to_cpu(rsp->status);
2008
2009 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2010
2011 if (scid) {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002012 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2013 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002014 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 } else {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002016 sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
2017 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002018 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 }
2020
2021 switch (result) {
2022 case L2CAP_CR_SUCCESS:
2023 sk->sk_state = BT_CONFIG;
2024 l2cap_pi(sk)->ident = 0;
2025 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002026 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2027
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002028 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2029 break;
2030
2031 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2032
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2034 l2cap_build_conf_req(sk, req), req);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002035 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 break;
2037
2038 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002039 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 break;
2041
2042 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002043 /* don't delete l2cap channel if sk is owned by user */
2044 if (sock_owned_by_user(sk)) {
2045 sk->sk_state = BT_DISCONN;
2046 l2cap_sock_clear_timer(sk);
2047 l2cap_sock_set_timer(sk, HZ / 5);
2048 break;
2049 }
2050
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 l2cap_chan_del(sk, ECONNREFUSED);
2052 break;
2053 }
2054
2055 bh_unlock_sock(sk);
2056 return 0;
2057}
2058
Mat Martineau8c462b62010-08-24 15:35:42 -07002059static inline void set_default_fcs(struct l2cap_pinfo *pi)
2060{
2061 /* FCS is enabled only in ERTM or streaming mode, if one or both
2062 * sides request it.
2063 */
2064 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2065 pi->fcs = L2CAP_FCS_NONE;
2066 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2067 pi->fcs = L2CAP_FCS_CRC16;
2068}
2069
Al Viro88219a02007-07-29 00:17:25 -07002070static 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 -07002071{
2072 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2073 u16 dcid, flags;
2074 u8 rsp[64];
2075 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002076 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077
2078 dcid = __le16_to_cpu(req->dcid);
2079 flags = __le16_to_cpu(req->flags);
2080
2081 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2082
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002083 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2084 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085 return -ENOENT;
2086
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002087 if (sk->sk_state != BT_CONFIG) {
2088 struct l2cap_cmd_rej rej;
2089
2090 rej.reason = cpu_to_le16(0x0002);
2091 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2092 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002093 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002094 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002095
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002096 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002097 len = cmd_len - sizeof(*req);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002098 if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
2099 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2100 l2cap_build_conf_rsp(sk, rsp,
2101 L2CAP_CONF_REJECT, flags), rsp);
2102 goto unlock;
2103 }
2104
2105 /* Store config. */
2106 memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
2107 l2cap_pi(sk)->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108
2109 if (flags & 0x0001) {
2110 /* Incomplete config. Send empty response. */
2111 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002112 l2cap_build_conf_rsp(sk, rsp,
2113 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 goto unlock;
2115 }
2116
2117 /* Complete config. */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002118 len = l2cap_parse_conf_req(sk, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002119 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002120 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002122 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002124 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002125 l2cap_pi(sk)->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002126
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002127 /* Reset config buffer. */
2128 l2cap_pi(sk)->conf_len = 0;
2129
Marcel Holtmann876d9482007-10-20 13:35:42 +02002130 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2131 goto unlock;
2132
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002134 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002135
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002137
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002138 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002139 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002140 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002141 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2142 l2cap_ertm_init(sk);
2143
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002145 goto unlock;
2146 }
2147
2148 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002149 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002150 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002152 l2cap_build_conf_req(sk, buf), buf);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002153 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 }
2155
2156unlock:
2157 bh_unlock_sock(sk);
2158 return 0;
2159}
2160
2161static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2162{
2163 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2164 u16 scid, flags, result;
2165 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002166 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167
2168 scid = __le16_to_cpu(rsp->scid);
2169 flags = __le16_to_cpu(rsp->flags);
2170 result = __le16_to_cpu(rsp->result);
2171
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002172 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2173 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002175 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2176 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 return 0;
2178
2179 switch (result) {
2180 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002181 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182 break;
2183
2184 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002185 if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002186 char req[64];
2187
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002188 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002189 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002190 goto done;
2191 }
2192
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002193 /* throw out any old stored conf requests */
2194 result = L2CAP_CONF_SUCCESS;
2195 len = l2cap_parse_conf_rsp(sk, rsp->data,
2196 len, req, &result);
2197 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002198 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002199 goto done;
2200 }
2201
2202 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2203 L2CAP_CONF_REQ, len, req);
2204 l2cap_pi(sk)->num_conf_req++;
2205 if (result != L2CAP_CONF_SUCCESS)
2206 goto done;
2207 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 }
2209
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002210 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002211 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002213 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 goto done;
2215 }
2216
2217 if (flags & 0x01)
2218 goto done;
2219
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2221
2222 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002223 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002224
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002226 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002227 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002228 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002229 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2230 l2cap_ertm_init(sk);
2231
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232 l2cap_chan_ready(sk);
2233 }
2234
2235done:
2236 bh_unlock_sock(sk);
2237 return 0;
2238}
2239
2240static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2241{
2242 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2243 struct l2cap_disconn_rsp rsp;
2244 u16 dcid, scid;
2245 struct sock *sk;
2246
2247 scid = __le16_to_cpu(req->scid);
2248 dcid = __le16_to_cpu(req->dcid);
2249
2250 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2251
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002252 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2253 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 return 0;
2255
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002256 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2257 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2259
2260 sk->sk_shutdown = SHUTDOWN_MASK;
2261
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002262 /* don't delete l2cap channel if sk is owned by user */
2263 if (sock_owned_by_user(sk)) {
2264 sk->sk_state = BT_DISCONN;
2265 l2cap_sock_clear_timer(sk);
2266 l2cap_sock_set_timer(sk, HZ / 5);
2267 bh_unlock_sock(sk);
2268 return 0;
2269 }
2270
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271 l2cap_chan_del(sk, ECONNRESET);
2272 bh_unlock_sock(sk);
2273
2274 l2cap_sock_kill(sk);
2275 return 0;
2276}
2277
2278static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2279{
2280 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2281 u16 dcid, scid;
2282 struct sock *sk;
2283
2284 scid = __le16_to_cpu(rsp->scid);
2285 dcid = __le16_to_cpu(rsp->dcid);
2286
2287 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2288
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002289 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2290 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 return 0;
2292
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002293 /* don't delete l2cap channel if sk is owned by user */
2294 if (sock_owned_by_user(sk)) {
2295 sk->sk_state = BT_DISCONN;
2296 l2cap_sock_clear_timer(sk);
2297 l2cap_sock_set_timer(sk, HZ / 5);
2298 bh_unlock_sock(sk);
2299 return 0;
2300 }
2301
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 l2cap_chan_del(sk, 0);
2303 bh_unlock_sock(sk);
2304
2305 l2cap_sock_kill(sk);
2306 return 0;
2307}
2308
2309static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2310{
2311 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 u16 type;
2313
2314 type = __le16_to_cpu(req->type);
2315
2316 BT_DBG("type 0x%4.4x", type);
2317
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002318 if (type == L2CAP_IT_FEAT_MASK) {
2319 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002320 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002321 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2322 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2323 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002324 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002325 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2326 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002327 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002328 l2cap_send_cmd(conn, cmd->ident,
2329 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002330 } else if (type == L2CAP_IT_FIXED_CHAN) {
2331 u8 buf[12];
2332 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2333 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2334 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2335 memcpy(buf + 4, l2cap_fixed_chan, 8);
2336 l2cap_send_cmd(conn, cmd->ident,
2337 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002338 } else {
2339 struct l2cap_info_rsp rsp;
2340 rsp.type = cpu_to_le16(type);
2341 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2342 l2cap_send_cmd(conn, cmd->ident,
2343 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2344 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345
2346 return 0;
2347}
2348
2349static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2350{
2351 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2352 u16 type, result;
2353
2354 type = __le16_to_cpu(rsp->type);
2355 result = __le16_to_cpu(rsp->result);
2356
2357 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2358
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002359 del_timer(&conn->info_timer);
2360
Ville Tervoadb08ed2010-08-04 09:43:33 +03002361 if (result != L2CAP_IR_SUCCESS) {
2362 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2363 conn->info_ident = 0;
2364
2365 l2cap_conn_start(conn);
2366
2367 return 0;
2368 }
2369
Marcel Holtmann984947d2009-02-06 23:35:19 +01002370 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002371 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002372
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002373 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002374 struct l2cap_info_req req;
2375 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2376
2377 conn->info_ident = l2cap_get_ident(conn);
2378
2379 l2cap_send_cmd(conn, conn->info_ident,
2380 L2CAP_INFO_REQ, sizeof(req), &req);
2381 } else {
2382 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2383 conn->info_ident = 0;
2384
2385 l2cap_conn_start(conn);
2386 }
2387 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002388 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002389 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002390
2391 l2cap_conn_start(conn);
2392 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002393
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394 return 0;
2395}
2396
2397static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
2398{
2399 u8 *data = skb->data;
2400 int len = skb->len;
2401 struct l2cap_cmd_hdr cmd;
2402 int err = 0;
2403
2404 l2cap_raw_recv(conn, skb);
2405
2406 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002407 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2409 data += L2CAP_CMD_HDR_SIZE;
2410 len -= L2CAP_CMD_HDR_SIZE;
2411
Al Viro88219a02007-07-29 00:17:25 -07002412 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413
Al Viro88219a02007-07-29 00:17:25 -07002414 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 -07002415
Al Viro88219a02007-07-29 00:17:25 -07002416 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 BT_DBG("corrupted command");
2418 break;
2419 }
2420
2421 switch (cmd.code) {
2422 case L2CAP_COMMAND_REJ:
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002423 l2cap_command_rej(conn, &cmd, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 break;
2425
2426 case L2CAP_CONN_REQ:
2427 err = l2cap_connect_req(conn, &cmd, data);
2428 break;
2429
2430 case L2CAP_CONN_RSP:
2431 err = l2cap_connect_rsp(conn, &cmd, data);
2432 break;
2433
2434 case L2CAP_CONF_REQ:
Al Viro88219a02007-07-29 00:17:25 -07002435 err = l2cap_config_req(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 break;
2437
2438 case L2CAP_CONF_RSP:
2439 err = l2cap_config_rsp(conn, &cmd, data);
2440 break;
2441
2442 case L2CAP_DISCONN_REQ:
2443 err = l2cap_disconnect_req(conn, &cmd, data);
2444 break;
2445
2446 case L2CAP_DISCONN_RSP:
2447 err = l2cap_disconnect_rsp(conn, &cmd, data);
2448 break;
2449
2450 case L2CAP_ECHO_REQ:
Al Viro88219a02007-07-29 00:17:25 -07002451 l2cap_send_cmd(conn, cmd.ident, L2CAP_ECHO_RSP, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 break;
2453
2454 case L2CAP_ECHO_RSP:
2455 break;
2456
2457 case L2CAP_INFO_REQ:
2458 err = l2cap_information_req(conn, &cmd, data);
2459 break;
2460
2461 case L2CAP_INFO_RSP:
2462 err = l2cap_information_rsp(conn, &cmd, data);
2463 break;
2464
2465 default:
2466 BT_ERR("Unknown signaling command 0x%2.2x", cmd.code);
2467 err = -EINVAL;
2468 break;
2469 }
2470
2471 if (err) {
2472 struct l2cap_cmd_rej rej;
2473 BT_DBG("error %d", err);
2474
2475 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002476 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2478 }
2479
Al Viro88219a02007-07-29 00:17:25 -07002480 data += cmd_len;
2481 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482 }
2483
2484 kfree_skb(skb);
2485}
2486
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002487static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2488{
2489 u16 our_fcs, rcv_fcs;
2490 int hdr_size = L2CAP_HDR_SIZE + 2;
2491
2492 if (pi->fcs == L2CAP_FCS_CRC16) {
2493 skb_trim(skb, skb->len - 2);
2494 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2495 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2496
2497 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002498 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002499 }
2500 return 0;
2501}
2502
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002503static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
2504{
2505 struct l2cap_pinfo *pi = l2cap_pi(sk);
2506 u16 control = 0;
2507
2508 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002509
2510 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2511
2512 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002513 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002514 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002515 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002516 }
2517
Gustavo F. Padovan4ea727e2010-06-03 16:34:20 -03002518 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
2519 l2cap_retransmit_frames(sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002520
2521 l2cap_ertm_send(sk);
2522
2523 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
2524 pi->frames_sent == 0) {
2525 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002526 l2cap_send_sframe(pi, control);
2527 }
2528}
2529
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002530static 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 -03002531{
2532 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002533 struct l2cap_pinfo *pi = l2cap_pi(sk);
2534 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002535
2536 bt_cb(skb)->tx_seq = tx_seq;
2537 bt_cb(skb)->sar = sar;
2538
2539 next_skb = skb_peek(SREJ_QUEUE(sk));
2540 if (!next_skb) {
2541 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002542 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002543 }
2544
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002545 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
2546 if (tx_seq_offset < 0)
2547 tx_seq_offset += 64;
2548
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002549 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002550 if (bt_cb(next_skb)->tx_seq == tx_seq)
2551 return -EINVAL;
2552
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002553 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
2554 pi->buffer_seq) % 64;
2555 if (next_tx_seq_offset < 0)
2556 next_tx_seq_offset += 64;
2557
2558 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002559 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002560 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002561 }
2562
2563 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
2564 break;
2565
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002566 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002567
2568 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002569
2570 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002571}
2572
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002573static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
2574{
2575 struct l2cap_pinfo *pi = l2cap_pi(sk);
2576 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002577 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002578
2579 switch (control & L2CAP_CTRL_SAR) {
2580 case L2CAP_SDU_UNSEGMENTED:
2581 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2582 goto drop;
2583
2584 err = sock_queue_rcv_skb(sk, skb);
2585 if (!err)
2586 return err;
2587
2588 break;
2589
2590 case L2CAP_SDU_START:
2591 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2592 goto drop;
2593
2594 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002595
2596 if (pi->sdu_len > pi->imtu)
2597 goto disconnect;
2598
2599 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002600 if (!pi->sdu)
2601 return -ENOMEM;
2602
2603 /* pull sdu_len bytes only after alloc, because of Local Busy
2604 * condition we have to be sure that this will be executed
2605 * only once, i.e., when alloc does not fail */
2606 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002607
2608 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2609
2610 pi->conn_state |= L2CAP_CONN_SAR_SDU;
2611 pi->partial_sdu_len = skb->len;
2612 break;
2613
2614 case L2CAP_SDU_CONTINUE:
2615 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2616 goto disconnect;
2617
2618 if (!pi->sdu)
2619 goto disconnect;
2620
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002621 pi->partial_sdu_len += skb->len;
2622 if (pi->partial_sdu_len > pi->sdu_len)
2623 goto drop;
2624
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002625 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2626
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002627 break;
2628
2629 case L2CAP_SDU_END:
2630 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2631 goto disconnect;
2632
2633 if (!pi->sdu)
2634 goto disconnect;
2635
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002636 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002637 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002638
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002639 if (pi->partial_sdu_len > pi->imtu)
2640 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002641
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002642 if (pi->partial_sdu_len != pi->sdu_len)
2643 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002644
2645 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002646 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002647
2648 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002649 if (!_skb) {
2650 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2651 return -ENOMEM;
2652 }
2653
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002654 err = sock_queue_rcv_skb(sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002655 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002656 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002657 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2658 return err;
2659 }
2660
2661 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2662 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002663
2664 kfree_skb(pi->sdu);
2665 break;
2666 }
2667
2668 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002669 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002670
2671drop:
2672 kfree_skb(pi->sdu);
2673 pi->sdu = NULL;
2674
2675disconnect:
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002676 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002677 kfree_skb(skb);
2678 return 0;
2679}
2680
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002681static int l2cap_try_push_rx_skb(struct sock *sk)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002682{
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002683 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002684 struct sk_buff *skb;
2685 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002686 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002687
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002688 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
2689 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
2690 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
2691 if (err < 0) {
2692 skb_queue_head(BUSY_QUEUE(sk), skb);
2693 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002694 }
2695
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002696 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002697 }
2698
2699 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
2700 goto done;
2701
2702 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2703 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
2704 l2cap_send_sframe(pi, control);
2705 l2cap_pi(sk)->retry_count = 1;
2706
2707 del_timer(&pi->retrans_timer);
2708 __mod_monitor_timer();
2709
2710 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
2711
2712done:
2713 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2714 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
2715
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002716 BT_DBG("sk %p, Exit local busy", sk);
2717
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002718 return 0;
2719}
2720
2721static void l2cap_busy_work(struct work_struct *work)
2722{
2723 DECLARE_WAITQUEUE(wait, current);
2724 struct l2cap_pinfo *pi =
2725 container_of(work, struct l2cap_pinfo, busy_work);
2726 struct sock *sk = (struct sock *)pi;
2727 int n_tries = 0, timeo = HZ/5, err;
2728 struct sk_buff *skb;
2729
2730 lock_sock(sk);
2731
2732 add_wait_queue(sk_sleep(sk), &wait);
2733 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
2734 set_current_state(TASK_INTERRUPTIBLE);
2735
2736 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
2737 err = -EBUSY;
2738 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
2739 break;
2740 }
2741
2742 if (!timeo)
2743 timeo = HZ/5;
2744
2745 if (signal_pending(current)) {
2746 err = sock_intr_errno(timeo);
2747 break;
2748 }
2749
2750 release_sock(sk);
2751 timeo = schedule_timeout(timeo);
2752 lock_sock(sk);
2753
2754 err = sock_error(sk);
2755 if (err)
2756 break;
2757
2758 if (l2cap_try_push_rx_skb(sk) == 0)
2759 break;
2760 }
2761
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002762 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02002763 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002764
2765 release_sock(sk);
2766}
2767
2768static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
2769{
2770 struct l2cap_pinfo *pi = l2cap_pi(sk);
2771 int sctrl, err;
2772
2773 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
2774 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
2775 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002776 return l2cap_try_push_rx_skb(sk);
2777
2778
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002779 }
2780
2781 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
2782 if (err >= 0) {
2783 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
2784 return err;
2785 }
2786
2787 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002788 BT_DBG("sk %p, Enter local busy", sk);
2789
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002790 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
2791 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
2792 __skb_queue_tail(BUSY_QUEUE(sk), skb);
2793
2794 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2795 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
2796 l2cap_send_sframe(pi, sctrl);
2797
2798 pi->conn_state |= L2CAP_CONN_RNR_SENT;
2799
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03002800 del_timer(&pi->ack_timer);
2801
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002802 queue_work(_busy_wq, &pi->busy_work);
2803
2804 return err;
2805}
2806
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002807static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002808{
2809 struct l2cap_pinfo *pi = l2cap_pi(sk);
2810 struct sk_buff *_skb;
2811 int err = -EINVAL;
2812
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002813 /*
2814 * TODO: We have to notify the userland if some data is lost with the
2815 * Streaming Mode.
2816 */
2817
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002818 switch (control & L2CAP_CTRL_SAR) {
2819 case L2CAP_SDU_UNSEGMENTED:
2820 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
2821 kfree_skb(pi->sdu);
2822 break;
2823 }
2824
2825 err = sock_queue_rcv_skb(sk, skb);
2826 if (!err)
2827 return 0;
2828
2829 break;
2830
2831 case L2CAP_SDU_START:
2832 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
2833 kfree_skb(pi->sdu);
2834 break;
2835 }
2836
2837 pi->sdu_len = get_unaligned_le16(skb->data);
2838 skb_pull(skb, 2);
2839
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03002840 if (pi->sdu_len > pi->imtu) {
2841 err = -EMSGSIZE;
2842 break;
2843 }
2844
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002845 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
2846 if (!pi->sdu) {
2847 err = -ENOMEM;
2848 break;
2849 }
2850
2851 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2852
2853 pi->conn_state |= L2CAP_CONN_SAR_SDU;
2854 pi->partial_sdu_len = skb->len;
2855 err = 0;
2856 break;
2857
2858 case L2CAP_SDU_CONTINUE:
2859 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2860 break;
2861
2862 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2863
2864 pi->partial_sdu_len += skb->len;
2865 if (pi->partial_sdu_len > pi->sdu_len)
2866 kfree_skb(pi->sdu);
2867 else
2868 err = 0;
2869
2870 break;
2871
2872 case L2CAP_SDU_END:
2873 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2874 break;
2875
2876 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2877
2878 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
2879 pi->partial_sdu_len += skb->len;
2880
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03002881 if (pi->partial_sdu_len > pi->imtu)
2882 goto drop;
2883
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002884 if (pi->partial_sdu_len == pi->sdu_len) {
2885 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
2886 err = sock_queue_rcv_skb(sk, _skb);
2887 if (err < 0)
2888 kfree_skb(_skb);
2889 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002890 err = 0;
2891
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03002892drop:
2893 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002894 break;
2895 }
2896
2897 kfree_skb(skb);
2898 return err;
2899}
2900
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002901static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
2902{
2903 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03002904 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002905
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002906 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002907 if (bt_cb(skb)->tx_seq != tx_seq)
2908 break;
2909
2910 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03002911 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002912 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002913 l2cap_pi(sk)->buffer_seq_srej =
2914 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03002915 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002916 }
2917}
2918
2919static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
2920{
2921 struct l2cap_pinfo *pi = l2cap_pi(sk);
2922 struct srej_list *l, *tmp;
2923 u16 control;
2924
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002925 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002926 if (l->tx_seq == tx_seq) {
2927 list_del(&l->list);
2928 kfree(l);
2929 return;
2930 }
2931 control = L2CAP_SUPER_SELECT_REJECT;
2932 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2933 l2cap_send_sframe(pi, control);
2934 list_del(&l->list);
2935 list_add_tail(&l->list, SREJ_LIST(sk));
2936 }
2937}
2938
2939static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
2940{
2941 struct l2cap_pinfo *pi = l2cap_pi(sk);
2942 struct srej_list *new;
2943 u16 control;
2944
2945 while (tx_seq != pi->expected_tx_seq) {
2946 control = L2CAP_SUPER_SELECT_REJECT;
2947 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2948 l2cap_send_sframe(pi, control);
2949
2950 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03002951 new->tx_seq = pi->expected_tx_seq;
2952 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002953 list_add_tail(&new->list, SREJ_LIST(sk));
2954 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03002955 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002956}
2957
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002958static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
2959{
2960 struct l2cap_pinfo *pi = l2cap_pi(sk);
2961 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03002962 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002963 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03002964 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03002965 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002966 int err = 0;
2967
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002968 BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
2969 rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002970
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03002971 if (L2CAP_CTRL_FINAL & rx_control &&
2972 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03002973 del_timer(&pi->monitor_timer);
2974 if (pi->unacked_frames > 0)
2975 __mod_retrans_timer();
2976 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
2977 }
2978
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03002979 pi->expected_ack_seq = req_seq;
2980 l2cap_drop_acked_frames(sk);
2981
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002982 if (tx_seq == pi->expected_tx_seq)
2983 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002984
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002985 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
2986 if (tx_seq_offset < 0)
2987 tx_seq_offset += 64;
2988
2989 /* invalid tx_seq */
2990 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002991 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002992 goto drop;
2993 }
2994
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002995 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
2996 goto drop;
2997
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002998 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
2999 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003000
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003001 first = list_first_entry(SREJ_LIST(sk),
3002 struct srej_list, list);
3003 if (tx_seq == first->tx_seq) {
3004 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3005 l2cap_check_srej_gap(sk, tx_seq);
3006
3007 list_del(&first->list);
3008 kfree(first);
3009
3010 if (list_empty(SREJ_LIST(sk))) {
3011 pi->buffer_seq = pi->buffer_seq_srej;
3012 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666cc2010-05-01 16:15:40 -03003013 l2cap_send_ack(pi);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003014 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003015 }
3016 } else {
3017 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003018
3019 /* duplicated tx_seq */
3020 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
3021 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003022
3023 list_for_each_entry(l, SREJ_LIST(sk), list) {
3024 if (l->tx_seq == tx_seq) {
3025 l2cap_resend_srejframe(sk, tx_seq);
3026 return 0;
3027 }
3028 }
3029 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003030 }
3031 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003032 expected_tx_seq_offset =
3033 (pi->expected_tx_seq - pi->buffer_seq) % 64;
3034 if (expected_tx_seq_offset < 0)
3035 expected_tx_seq_offset += 64;
3036
3037 /* duplicated tx_seq */
3038 if (tx_seq_offset < expected_tx_seq_offset)
3039 goto drop;
3040
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003041 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003042
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003043 BT_DBG("sk %p, Enter SREJ", sk);
3044
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003045 INIT_LIST_HEAD(SREJ_LIST(sk));
3046 pi->buffer_seq_srej = pi->buffer_seq;
3047
3048 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003049 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003050 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3051
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003052 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
3053
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003054 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003055
3056 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003057 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003058 return 0;
3059
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003060expected:
3061 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3062
3063 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003064 bt_cb(skb)->tx_seq = tx_seq;
3065 bt_cb(skb)->sar = sar;
3066 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003067 return 0;
3068 }
3069
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003070 err = l2cap_push_rx_skb(sk, skb, rx_control);
3071 if (err < 0)
3072 return 0;
3073
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003074 if (rx_control & L2CAP_CTRL_FINAL) {
3075 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3076 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003077 else
3078 l2cap_retransmit_frames(sk);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003079 }
3080
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003081 __mod_ack_timer();
3082
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003083 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
3084 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003085 l2cap_send_ack(pi);
3086
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003087 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003088
3089drop:
3090 kfree_skb(skb);
3091 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003092}
3093
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003094static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003095{
3096 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003097
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003098 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3099 rx_control);
3100
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003101 pi->expected_ack_seq = __get_reqseq(rx_control);
3102 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003103
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003104 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003105 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003106 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3107 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3108 (pi->unacked_frames > 0))
3109 __mod_retrans_timer();
3110
3111 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3112 l2cap_send_srejtail(sk);
3113 } else {
3114 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003115 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003116
3117 } else if (rx_control & L2CAP_CTRL_FINAL) {
3118 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003119
3120 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3121 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003122 else
3123 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003124
3125 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003126 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3127 (pi->unacked_frames > 0))
3128 __mod_retrans_timer();
3129
3130 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003131 if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003132 l2cap_send_ack(pi);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003133 else
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003134 l2cap_ertm_send(sk);
3135 }
3136}
3137
3138static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
3139{
3140 struct l2cap_pinfo *pi = l2cap_pi(sk);
3141 u8 tx_seq = __get_reqseq(rx_control);
3142
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003143 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3144
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003145 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3146
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03003147 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003148 l2cap_drop_acked_frames(sk);
3149
3150 if (rx_control & L2CAP_CTRL_FINAL) {
3151 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3152 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003153 else
3154 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003155 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003156 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003157
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03003158 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003159 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003160 }
3161}
3162static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
3163{
3164 struct l2cap_pinfo *pi = l2cap_pi(sk);
3165 u8 tx_seq = __get_reqseq(rx_control);
3166
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003167 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3168
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003169 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3170
3171 if (rx_control & L2CAP_CTRL_POLL) {
3172 pi->expected_ack_seq = tx_seq;
3173 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003174
3175 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003176 l2cap_retransmit_one_frame(sk, tx_seq);
3177
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003178 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003179
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003180 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3181 pi->srej_save_reqseq = tx_seq;
3182 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3183 }
3184 } else if (rx_control & L2CAP_CTRL_FINAL) {
3185 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
3186 pi->srej_save_reqseq == tx_seq)
3187 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
3188 else
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003189 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003190 } 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 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3193 pi->srej_save_reqseq = tx_seq;
3194 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3195 }
3196 }
3197}
3198
3199static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
3200{
3201 struct l2cap_pinfo *pi = l2cap_pi(sk);
3202 u8 tx_seq = __get_reqseq(rx_control);
3203
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003204 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3205
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003206 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
3207 pi->expected_ack_seq = tx_seq;
3208 l2cap_drop_acked_frames(sk);
3209
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003210 if (rx_control & L2CAP_CTRL_POLL)
3211 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
3212
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003213 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
3214 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003215 if (rx_control & L2CAP_CTRL_POLL)
3216 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003217 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003218 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003219
3220 if (rx_control & L2CAP_CTRL_POLL)
3221 l2cap_send_srejtail(sk);
3222 else
3223 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003224}
3225
3226static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3227{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003228 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3229
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003230 if (L2CAP_CTRL_FINAL & rx_control &&
3231 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003232 del_timer(&l2cap_pi(sk)->monitor_timer);
3233 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003234 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003235 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003236 }
3237
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003238 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3239 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003240 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003241 break;
3242
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003243 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003244 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003245 break;
3246
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003247 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003248 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003249 break;
3250
3251 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003252 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003253 break;
3254 }
3255
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003256 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003257 return 0;
3258}
3259
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003260static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3261{
3262 struct l2cap_pinfo *pi = l2cap_pi(sk);
3263 u16 control;
3264 u8 req_seq;
3265 int len, next_tx_seq_offset, req_seq_offset;
3266
3267 control = get_unaligned_le16(skb->data);
3268 skb_pull(skb, 2);
3269 len = skb->len;
3270
3271 /*
3272 * We can just drop the corrupted I-frame here.
3273 * Receiver will miss it and start proper recovery
3274 * procedures and ask retransmission.
3275 */
3276 if (l2cap_check_fcs(pi, skb))
3277 goto drop;
3278
3279 if (__is_sar_start(control) && __is_iframe(control))
3280 len -= 2;
3281
3282 if (pi->fcs == L2CAP_FCS_CRC16)
3283 len -= 2;
3284
3285 if (len > pi->mps) {
3286 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3287 goto drop;
3288 }
3289
3290 req_seq = __get_reqseq(control);
3291 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
3292 if (req_seq_offset < 0)
3293 req_seq_offset += 64;
3294
3295 next_tx_seq_offset =
3296 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
3297 if (next_tx_seq_offset < 0)
3298 next_tx_seq_offset += 64;
3299
3300 /* check for invalid req-seq */
3301 if (req_seq_offset > next_tx_seq_offset) {
3302 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3303 goto drop;
3304 }
3305
3306 if (__is_iframe(control)) {
3307 if (len < 0) {
3308 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3309 goto drop;
3310 }
3311
3312 l2cap_data_channel_iframe(sk, control, skb);
3313 } else {
3314 if (len != 0) {
3315 BT_ERR("%d", len);
3316 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3317 goto drop;
3318 }
3319
3320 l2cap_data_channel_sframe(sk, control, skb);
3321 }
3322
3323 return 0;
3324
3325drop:
3326 kfree_skb(skb);
3327 return 0;
3328}
3329
Linus Torvalds1da177e2005-04-16 15:20:36 -07003330static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3331{
3332 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003333 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003334 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003335 u8 tx_seq;
3336 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337
3338 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
3339 if (!sk) {
3340 BT_DBG("unknown cid 0x%4.4x", cid);
3341 goto drop;
3342 }
3343
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003344 pi = l2cap_pi(sk);
3345
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346 BT_DBG("sk %p, len %d", sk, skb->len);
3347
3348 if (sk->sk_state != BT_CONNECTED)
3349 goto drop;
3350
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003351 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003352 case L2CAP_MODE_BASIC:
3353 /* If socket recv buffers overflows we drop data here
3354 * which is *bad* because L2CAP has to be reliable.
3355 * But we don't have any other choice. L2CAP doesn't
3356 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003357
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003358 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003359 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003360
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003361 if (!sock_queue_rcv_skb(sk, skb))
3362 goto done;
3363 break;
3364
3365 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003366 if (!sock_owned_by_user(sk)) {
3367 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003368 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003369 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003370 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003371 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003372
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003373 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003374
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003375 case L2CAP_MODE_STREAMING:
3376 control = get_unaligned_le16(skb->data);
3377 skb_pull(skb, 2);
3378 len = skb->len;
3379
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003380 if (l2cap_check_fcs(pi, skb))
3381 goto drop;
3382
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003383 if (__is_sar_start(control))
3384 len -= 2;
3385
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003386 if (pi->fcs == L2CAP_FCS_CRC16)
3387 len -= 2;
3388
Nathan Holstein51893f82010-06-09 15:46:25 -04003389 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003390 goto drop;
3391
3392 tx_seq = __get_txseq(control);
3393
3394 if (pi->expected_tx_seq == tx_seq)
3395 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3396 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03003397 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003398
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003399 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003400
3401 goto done;
3402
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003403 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003404 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003405 break;
3406 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407
3408drop:
3409 kfree_skb(skb);
3410
3411done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003412 if (sk)
3413 bh_unlock_sock(sk);
3414
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415 return 0;
3416}
3417
Al Viro8e036fc2007-07-29 00:16:36 -07003418static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003419{
3420 struct sock *sk;
3421
3422 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3423 if (!sk)
3424 goto drop;
3425
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003426 bh_lock_sock(sk);
3427
Linus Torvalds1da177e2005-04-16 15:20:36 -07003428 BT_DBG("sk %p, len %d", sk, skb->len);
3429
3430 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3431 goto drop;
3432
3433 if (l2cap_pi(sk)->imtu < skb->len)
3434 goto drop;
3435
3436 if (!sock_queue_rcv_skb(sk, skb))
3437 goto done;
3438
3439drop:
3440 kfree_skb(skb);
3441
3442done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003443 if (sk)
3444 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003445 return 0;
3446}
3447
3448static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3449{
3450 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003451 u16 cid, len;
3452 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453
3454 skb_pull(skb, L2CAP_HDR_SIZE);
3455 cid = __le16_to_cpu(lh->cid);
3456 len = __le16_to_cpu(lh->len);
3457
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003458 if (len != skb->len) {
3459 kfree_skb(skb);
3460 return;
3461 }
3462
Linus Torvalds1da177e2005-04-16 15:20:36 -07003463 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3464
3465 switch (cid) {
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003466 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467 l2cap_sig_channel(conn, skb);
3468 break;
3469
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003470 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003471 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003472 skb_pull(skb, 2);
3473 l2cap_conless_channel(conn, psm, skb);
3474 break;
3475
3476 default:
3477 l2cap_data_channel(conn, cid, skb);
3478 break;
3479 }
3480}
3481
3482/* ---- L2CAP interface with lower layer (HCI) ---- */
3483
3484static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3485{
3486 int exact = 0, lm1 = 0, lm2 = 0;
3487 register struct sock *sk;
3488 struct hlist_node *node;
3489
3490 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003491 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003492
3493 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3494
3495 /* Find listening sockets and check their link_mode */
3496 read_lock(&l2cap_sk_list.lock);
3497 sk_for_each(sk, node, &l2cap_sk_list.head) {
3498 if (sk->sk_state != BT_LISTEN)
3499 continue;
3500
3501 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003502 lm1 |= HCI_LM_ACCEPT;
3503 if (l2cap_pi(sk)->role_switch)
3504 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003505 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003506 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3507 lm2 |= HCI_LM_ACCEPT;
3508 if (l2cap_pi(sk)->role_switch)
3509 lm2 |= HCI_LM_MASTER;
3510 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003511 }
3512 read_unlock(&l2cap_sk_list.lock);
3513
3514 return exact ? lm1 : lm2;
3515}
3516
3517static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3518{
Marcel Holtmann01394182006-07-03 10:02:46 +02003519 struct l2cap_conn *conn;
3520
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3522
3523 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003524 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003525
3526 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527 conn = l2cap_conn_add(hcon, status);
3528 if (conn)
3529 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003530 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003531 l2cap_conn_del(hcon, bt_err(status));
3532
3533 return 0;
3534}
3535
Marcel Holtmann2950f212009-02-12 14:02:50 +01003536static int l2cap_disconn_ind(struct hci_conn *hcon)
3537{
3538 struct l2cap_conn *conn = hcon->l2cap_data;
3539
3540 BT_DBG("hcon %p", hcon);
3541
3542 if (hcon->type != ACL_LINK || !conn)
3543 return 0x13;
3544
3545 return conn->disc_reason;
3546}
3547
3548static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549{
3550 BT_DBG("hcon %p reason %d", hcon, reason);
3551
3552 if (hcon->type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003553 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003554
3555 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003556
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557 return 0;
3558}
3559
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003560static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3561{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003562 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003563 return;
3564
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003565 if (encrypt == 0x00) {
3566 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3567 l2cap_sock_clear_timer(sk);
3568 l2cap_sock_set_timer(sk, HZ * 5);
3569 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3570 __l2cap_sock_close(sk, ECONNREFUSED);
3571 } else {
3572 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3573 l2cap_sock_clear_timer(sk);
3574 }
3575}
3576
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003577static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003578{
3579 struct l2cap_chan_list *l;
Marcel Holtmann40be4922008-07-14 20:13:50 +02003580 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582
Marcel Holtmann01394182006-07-03 10:02:46 +02003583 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003585
Linus Torvalds1da177e2005-04-16 15:20:36 -07003586 l = &conn->chan_list;
3587
3588 BT_DBG("conn %p", conn);
3589
3590 read_lock(&l->lock);
3591
3592 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
3593 bh_lock_sock(sk);
3594
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003595 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3596 bh_unlock_sock(sk);
3597 continue;
3598 }
3599
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003600 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003601 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003602 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003603 bh_unlock_sock(sk);
3604 continue;
3605 }
3606
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003607 if (sk->sk_state == BT_CONNECT) {
3608 if (!status) {
3609 struct l2cap_conn_req req;
3610 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3611 req.psm = l2cap_pi(sk)->psm;
3612
3613 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003614 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003615
3616 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3617 L2CAP_CONN_REQ, sizeof(req), &req);
3618 } else {
3619 l2cap_sock_clear_timer(sk);
3620 l2cap_sock_set_timer(sk, HZ / 10);
3621 }
3622 } else if (sk->sk_state == BT_CONNECT2) {
3623 struct l2cap_conn_rsp rsp;
3624 __u16 result;
3625
3626 if (!status) {
3627 sk->sk_state = BT_CONFIG;
3628 result = L2CAP_CR_SUCCESS;
3629 } else {
3630 sk->sk_state = BT_DISCONN;
3631 l2cap_sock_set_timer(sk, HZ / 10);
3632 result = L2CAP_CR_SEC_BLOCK;
3633 }
3634
3635 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3636 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3637 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003638 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003639 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3640 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003641 }
3642
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643 bh_unlock_sock(sk);
3644 }
3645
3646 read_unlock(&l->lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003647
Linus Torvalds1da177e2005-04-16 15:20:36 -07003648 return 0;
3649}
3650
3651static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3652{
3653 struct l2cap_conn *conn = hcon->l2cap_data;
3654
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003655 if (!conn)
3656 conn = l2cap_conn_add(hcon, 0);
3657
3658 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659 goto drop;
3660
3661 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3662
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003663 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003664 struct l2cap_hdr *hdr;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003665 struct sock *sk;
3666 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003667 int len;
3668
3669 if (conn->rx_len) {
3670 BT_ERR("Unexpected start frame (len %d)", skb->len);
3671 kfree_skb(conn->rx_skb);
3672 conn->rx_skb = NULL;
3673 conn->rx_len = 0;
3674 l2cap_conn_unreliable(conn, ECOMM);
3675 }
3676
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003677 /* Start fragment always begin with Basic L2CAP header */
3678 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679 BT_ERR("Frame is too short (len %d)", skb->len);
3680 l2cap_conn_unreliable(conn, ECOMM);
3681 goto drop;
3682 }
3683
3684 hdr = (struct l2cap_hdr *) skb->data;
3685 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003686 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687
3688 if (len == skb->len) {
3689 /* Complete frame received */
3690 l2cap_recv_frame(conn, skb);
3691 return 0;
3692 }
3693
3694 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3695
3696 if (skb->len > len) {
3697 BT_ERR("Frame is too long (len %d, expected len %d)",
3698 skb->len, len);
3699 l2cap_conn_unreliable(conn, ECOMM);
3700 goto drop;
3701 }
3702
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003703 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
3704
3705 if (sk && l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
3706 BT_ERR("Frame exceeding recv MTU (len %d, MTU %d)",
3707 len, l2cap_pi(sk)->imtu);
3708 bh_unlock_sock(sk);
3709 l2cap_conn_unreliable(conn, ECOMM);
3710 goto drop;
3711 }
3712
3713 if (sk)
3714 bh_unlock_sock(sk);
3715
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003717 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
3718 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003719 goto drop;
3720
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003721 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003722 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723 conn->rx_len = len - skb->len;
3724 } else {
3725 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
3726
3727 if (!conn->rx_len) {
3728 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
3729 l2cap_conn_unreliable(conn, ECOMM);
3730 goto drop;
3731 }
3732
3733 if (skb->len > conn->rx_len) {
3734 BT_ERR("Fragment is too long (len %d, expected %d)",
3735 skb->len, conn->rx_len);
3736 kfree_skb(conn->rx_skb);
3737 conn->rx_skb = NULL;
3738 conn->rx_len = 0;
3739 l2cap_conn_unreliable(conn, ECOMM);
3740 goto drop;
3741 }
3742
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003743 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003744 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003745 conn->rx_len -= skb->len;
3746
3747 if (!conn->rx_len) {
3748 /* Complete frame received */
3749 l2cap_recv_frame(conn, conn->rx_skb);
3750 conn->rx_skb = NULL;
3751 }
3752 }
3753
3754drop:
3755 kfree_skb(skb);
3756 return 0;
3757}
3758
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003759static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760{
3761 struct sock *sk;
3762 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763
3764 read_lock_bh(&l2cap_sk_list.lock);
3765
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003766 sk_for_each(sk, node, &l2cap_sk_list.head) {
3767 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02003769 seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003770 batostr(&bt_sk(sk)->src),
3771 batostr(&bt_sk(sk)->dst),
3772 sk->sk_state, __le16_to_cpu(pi->psm),
3773 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02003774 pi->imtu, pi->omtu, pi->sec_level,
3775 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003776 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003779
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003780 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781}
3782
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003783static int l2cap_debugfs_open(struct inode *inode, struct file *file)
3784{
3785 return single_open(file, l2cap_debugfs_show, inode->i_private);
3786}
3787
3788static const struct file_operations l2cap_debugfs_fops = {
3789 .open = l2cap_debugfs_open,
3790 .read = seq_read,
3791 .llseek = seq_lseek,
3792 .release = single_release,
3793};
3794
3795static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797static struct hci_proto l2cap_hci_proto = {
3798 .name = "L2CAP",
3799 .id = HCI_PROTO_L2CAP,
3800 .connect_ind = l2cap_connect_ind,
3801 .connect_cfm = l2cap_connect_cfm,
3802 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01003803 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003804 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003805 .recv_acldata = l2cap_recv_acldata
3806};
3807
Gustavo F. Padovan64274512011-02-07 20:08:52 -02003808int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809{
3810 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003811
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02003812 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813 if (err < 0)
3814 return err;
3815
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003816 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04003817 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02003818 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819 goto error;
3820 }
3821
3822 err = hci_register_proto(&l2cap_hci_proto);
3823 if (err < 0) {
3824 BT_ERR("L2CAP protocol registration failed");
3825 bt_sock_unregister(BTPROTO_L2CAP);
3826 goto error;
3827 }
3828
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003829 if (bt_debugfs) {
3830 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
3831 bt_debugfs, NULL, &l2cap_debugfs_fops);
3832 if (!l2cap_debugfs)
3833 BT_ERR("Failed to create L2CAP debug file");
3834 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836 BT_INFO("L2CAP socket layer initialized");
3837
3838 return 0;
3839
3840error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04003841 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02003842 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843 return err;
3844}
3845
Gustavo F. Padovan64274512011-02-07 20:08:52 -02003846void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003847{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003848 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003849
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003850 flush_workqueue(_busy_wq);
3851 destroy_workqueue(_busy_wq);
3852
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
3854 BT_ERR("L2CAP protocol unregistration failed");
3855
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02003856 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857}
3858
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003859module_param(disable_ertm, bool, 0644);
3860MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");