blob: 123c1bfa0ce612d4271ac96b48e0694c9f932523 [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
Ville Tervoacd7d372011-02-10 22:38:49 -0300596 if (conn->hcon->type == LE_LINK) {
597 l2cap_sock_clear_timer(sk);
598 sk->sk_state = BT_CONNECTED;
599 sk->sk_state_change(sk);
600 }
601
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300602 if (sk->sk_type != SOCK_SEQPACKET &&
603 sk->sk_type != SOCK_STREAM) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200604 l2cap_sock_clear_timer(sk);
605 sk->sk_state = BT_CONNECTED;
606 sk->sk_state_change(sk);
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200607 } else if (sk->sk_state == BT_CONNECT)
608 l2cap_do_start(sk);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200609
610 bh_unlock_sock(sk);
611 }
612
613 read_unlock(&l->lock);
614}
615
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200616/* Notify sockets that we cannot guaranty reliability anymore */
617static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
618{
619 struct l2cap_chan_list *l = &conn->chan_list;
620 struct sock *sk;
621
622 BT_DBG("conn %p", conn);
623
624 read_lock(&l->lock);
625
626 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100627 if (l2cap_pi(sk)->force_reliable)
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200628 sk->sk_err = err;
629 }
630
631 read_unlock(&l->lock);
632}
633
634static void l2cap_info_timeout(unsigned long arg)
635{
636 struct l2cap_conn *conn = (void *) arg;
637
Marcel Holtmann984947d2009-02-06 23:35:19 +0100638 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +0100639 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +0100640
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200641 l2cap_conn_start(conn);
642}
643
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
645{
Marcel Holtmann01394182006-07-03 10:02:46 +0200646 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647
Marcel Holtmann01394182006-07-03 10:02:46 +0200648 if (conn || status)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 return conn;
650
Marcel Holtmann01394182006-07-03 10:02:46 +0200651 conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
652 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654
655 hcon->l2cap_data = conn;
656 conn->hcon = hcon;
657
Marcel Holtmann01394182006-07-03 10:02:46 +0200658 BT_DBG("hcon %p conn %p", hcon, conn);
659
Ville Tervoacd7d372011-02-10 22:38:49 -0300660 if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
661 conn->mtu = hcon->hdev->le_mtu;
662 else
663 conn->mtu = hcon->hdev->acl_mtu;
664
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 conn->src = &hcon->hdev->bdaddr;
666 conn->dst = &hcon->dst;
667
Marcel Holtmann4e8402a2007-10-20 13:37:56 +0200668 conn->feat_mask = 0;
669
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 spin_lock_init(&conn->lock);
671 rwlock_init(&conn->chan_list.lock);
672
Dave Young45054dc2009-10-18 20:28:30 +0000673 setup_timer(&conn->info_timer, l2cap_info_timeout,
674 (unsigned long) conn);
675
Marcel Holtmann2950f212009-02-12 14:02:50 +0100676 conn->disc_reason = 0x13;
677
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 return conn;
679}
680
Marcel Holtmann01394182006-07-03 10:02:46 +0200681static void l2cap_conn_del(struct hci_conn *hcon, int err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682{
Marcel Holtmann01394182006-07-03 10:02:46 +0200683 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 struct sock *sk;
685
Marcel Holtmann01394182006-07-03 10:02:46 +0200686 if (!conn)
687 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688
689 BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
690
Wei Yongjun7585b972009-02-25 18:29:52 +0800691 kfree_skb(conn->rx_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692
693 /* Kill channels */
694 while ((sk = conn->chan_list.head)) {
695 bh_lock_sock(sk);
696 l2cap_chan_del(sk, err);
697 bh_unlock_sock(sk);
698 l2cap_sock_kill(sk);
699 }
700
Dave Young8e8440f2008-03-03 12:18:55 -0800701 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
702 del_timer_sync(&conn->info_timer);
Thomas Gleixner3ab22732008-02-26 17:42:56 -0800703
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 hcon->l2cap_data = NULL;
705 kfree(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706}
707
708static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
709{
710 struct l2cap_chan_list *l = &conn->chan_list;
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200711 write_lock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 __l2cap_chan_add(conn, sk, parent);
Marcel Holtmannfd1278d2006-07-12 23:00:07 +0200713 write_unlock_bh(&l->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714}
715
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716/* ---- Socket interface ---- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717
718/* Find socket with psm and source bdaddr.
719 * Returns closest match.
720 */
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000721static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722{
723 struct sock *sk = NULL, *sk1 = NULL;
724 struct hlist_node *node;
725
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000726 read_lock(&l2cap_sk_list.lock);
727
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 sk_for_each(sk, node, &l2cap_sk_list.head) {
729 if (state && sk->sk_state != state)
730 continue;
731
732 if (l2cap_pi(sk)->psm == psm) {
733 /* Exact match. */
734 if (!bacmp(&bt_sk(sk)->src, src))
735 break;
736
737 /* Closest match */
738 if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
739 sk1 = sk;
740 }
741 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 read_unlock(&l2cap_sk_list.lock);
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +0000744
745 return node ? sk : sk1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746}
747
Gustavo F. Padovan4e34c502011-02-04 02:56:13 -0200748int l2cap_do_connect(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749{
750 bdaddr_t *src = &bt_sk(sk)->src;
751 bdaddr_t *dst = &bt_sk(sk)->dst;
752 struct l2cap_conn *conn;
753 struct hci_conn *hcon;
754 struct hci_dev *hdev;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200755 __u8 auth_type;
Marcel Holtmann44d0e482009-04-20 07:09:16 +0200756 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757
Marcel Holtmannf29972d2009-02-12 05:07:45 +0100758 BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
759 l2cap_pi(sk)->psm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -0300761 hdev = hci_get_route(dst, src);
762 if (!hdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 return -EHOSTUNREACH;
764
765 hci_dev_lock_bh(hdev);
766
767 err = -ENOMEM;
768
Johan Hedberg8556edd32011-01-19 12:06:50 +0530769 auth_type = l2cap_get_auth_type(sk);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200770
Ville Tervoacd7d372011-02-10 22:38:49 -0300771 if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
772 hcon = hci_connect(hdev, LE_LINK, dst,
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +0100773 l2cap_pi(sk)->sec_level, auth_type);
Ville Tervoacd7d372011-02-10 22:38:49 -0300774 else
775 hcon = hci_connect(hdev, ACL_LINK, dst,
776 l2cap_pi(sk)->sec_level, auth_type);
777
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 if (!hcon)
779 goto done;
780
781 conn = l2cap_conn_add(hcon, 0);
782 if (!conn) {
783 hci_conn_put(hcon);
784 goto done;
785 }
786
787 err = 0;
788
789 /* Update source addr of the socket */
790 bacpy(src, conn->src);
791
792 l2cap_chan_add(conn, sk, NULL);
793
794 sk->sk_state = BT_CONNECT;
795 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
796
797 if (hcon->state == BT_CONNECTED) {
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -0300798 if (sk->sk_type != SOCK_SEQPACKET &&
799 sk->sk_type != SOCK_STREAM) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 l2cap_sock_clear_timer(sk);
Johan Hedbergd00ef242011-01-19 12:06:51 +0530801 if (l2cap_check_security(sk))
802 sk->sk_state = BT_CONNECTED;
Marcel Holtmann79d554a2008-07-14 20:13:44 +0200803 } else
804 l2cap_do_start(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 }
806
807done:
808 hci_dev_unlock_bh(hdev);
809 hci_dev_put(hdev);
810 return err;
811}
812
Gustavo F. Padovandcba0db2011-02-04 03:08:36 -0200813int __l2cap_wait_ack(struct sock *sk)
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300814{
815 DECLARE_WAITQUEUE(wait, current);
816 int err = 0;
817 int timeo = HZ/5;
818
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200819 add_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300820 while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
821 set_current_state(TASK_INTERRUPTIBLE);
822
823 if (!timeo)
824 timeo = HZ/5;
825
826 if (signal_pending(current)) {
827 err = sock_intr_errno(timeo);
828 break;
829 }
830
831 release_sock(sk);
832 timeo = schedule_timeout(timeo);
833 lock_sock(sk);
834
835 err = sock_error(sk);
836 if (err)
837 break;
838 }
839 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +0200840 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan6161c032010-05-01 16:15:44 -0300841 return err;
842}
843
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300844static void l2cap_monitor_timeout(unsigned long arg)
845{
846 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300847
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300848 BT_DBG("sk %p", sk);
849
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300850 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300851 if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300852 l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
Andrei Emeltchenkob13f5862009-12-15 11:38:04 +0200853 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300854 return;
855 }
856
857 l2cap_pi(sk)->retry_count++;
858 __mod_monitor_timer();
859
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -0300860 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300861 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300862}
863
864static void l2cap_retrans_timeout(unsigned long arg)
865{
866 struct sock *sk = (void *) arg;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300867
Gustavo F. Padovan0e989582010-04-19 14:45:38 -0300868 BT_DBG("sk %p", sk);
869
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300870 bh_lock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300871 l2cap_pi(sk)->retry_count = 1;
872 __mod_monitor_timer();
873
874 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
875
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -0300876 l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
Gustavo F. Padovane6862192009-08-24 00:45:19 -0300877 bh_unlock_sock(sk);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300878}
879
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300880static void l2cap_drop_acked_frames(struct sock *sk)
881{
882 struct sk_buff *skb;
883
Gustavo F. Padovan812e7372010-05-01 16:15:42 -0300884 while ((skb = skb_peek(TX_QUEUE(sk))) &&
885 l2cap_pi(sk)->unacked_frames) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300886 if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
887 break;
888
889 skb = skb_dequeue(TX_QUEUE(sk));
890 kfree_skb(skb);
891
892 l2cap_pi(sk)->unacked_frames--;
893 }
894
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300895 if (!l2cap_pi(sk)->unacked_frames)
896 del_timer(&l2cap_pi(sk)->retrans_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300897}
898
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200899void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300900{
901 struct l2cap_pinfo *pi = l2cap_pi(sk);
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200902 struct hci_conn *hcon = pi->conn->hcon;
903 u16 flags;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300904
905 BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
906
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200907 if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
908 flags = ACL_START_NO_FLUSH;
909 else
910 flags = ACL_START;
911
912 hci_send_acl(hcon, skb, flags);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300913}
914
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200915void l2cap_streaming_send(struct sock *sk)
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300916{
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -0300917 struct sk_buff *skb;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300918 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300919 u16 control, fcs;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300920
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -0300921 while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
922 control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300923 control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -0300924 put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300925
Gustavo F. Padovane8235c62010-05-01 16:15:36 -0300926 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -0300927 fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
928 put_unaligned_le16(fcs, skb->data + skb->len - 2);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300929 }
930
Gustavo F. Padovanccbb84a2010-08-30 18:44:44 -0300931 l2cap_do_send(sk, skb);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300932
933 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300934 }
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -0300935}
936
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -0300937static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300938{
939 struct l2cap_pinfo *pi = l2cap_pi(sk);
940 struct sk_buff *skb, *tx_skb;
941 u16 control, fcs;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300942
943 skb = skb_peek(TX_QUEUE(sk));
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300944 if (!skb)
945 return;
946
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300947 do {
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300948 if (bt_cb(skb)->tx_seq == tx_seq)
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300949 break;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300950
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300951 if (skb_queue_is_last(TX_QUEUE(sk), skb))
952 return;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300953
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300954 } while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300955
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300956 if (pi->remote_max_tx &&
957 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300958 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300959 return;
960 }
961
962 tx_skb = skb_clone(skb, GFP_ATOMIC);
963 bt_cb(skb)->retries++;
964 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -0300965
966 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
967 control |= L2CAP_CTRL_FINAL;
968 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
969 }
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -0300970
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300971 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
972 | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -0300973
Gustavo F. Padovanf11d6762010-05-01 16:15:44 -0300974 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
975
976 if (pi->fcs == L2CAP_FCS_CRC16) {
977 fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
978 put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
979 }
980
981 l2cap_do_send(sk, tx_skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -0300982}
983
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -0200984int l2cap_ertm_send(struct sock *sk)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300985{
986 struct sk_buff *skb, *tx_skb;
987 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -0300988 u16 control, fcs;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300989 int nsent = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300990
Gustavo F. Padovanc13ffa62010-05-13 20:50:12 -0300991 if (sk->sk_state != BT_CONNECTED)
992 return -ENOTCONN;
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300993
Gustavo F. Padovan6e2b6722010-06-01 18:52:58 -0300994 while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -0300995
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300996 if (pi->remote_max_tx &&
997 bt_cb(skb)->retries == pi->remote_max_tx) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -0300998 l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
Gustavo F. Padovane90bac02009-08-20 22:26:00 -0300999 break;
1000 }
1001
Andrei Emeltchenkoe420aba2009-12-23 13:07:14 +02001002 tx_skb = skb_clone(skb, GFP_ATOMIC);
1003
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001004 bt_cb(skb)->retries++;
1005
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001006 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
Gustavo F. Padovan95ffa972010-06-18 20:37:33 -03001007 control &= L2CAP_CTRL_SAR;
1008
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001009 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1010 control |= L2CAP_CTRL_FINAL;
1011 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1012 }
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03001013 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001014 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1015 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
1016
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001017
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03001018 if (pi->fcs == L2CAP_FCS_CRC16) {
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001019 fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
1020 put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
1021 }
1022
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001023 l2cap_do_send(sk, tx_skb);
1024
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001025 __mod_retrans_timer();
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001026
1027 bt_cb(skb)->tx_seq = pi->next_tx_seq;
1028 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1029
1030 pi->unacked_frames++;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001031 pi->frames_sent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001032
1033 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1034 sk->sk_send_head = NULL;
1035 else
1036 sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001037
1038 nsent++;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001039 }
1040
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001041 return nsent;
1042}
1043
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001044static int l2cap_retransmit_frames(struct sock *sk)
1045{
1046 struct l2cap_pinfo *pi = l2cap_pi(sk);
1047 int ret;
1048
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001049 if (!skb_queue_empty(TX_QUEUE(sk)))
1050 sk->sk_send_head = TX_QUEUE(sk)->next;
1051
1052 pi->next_tx_seq = pi->expected_ack_seq;
1053 ret = l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001054 return ret;
1055}
1056
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001057static void l2cap_send_ack(struct l2cap_pinfo *pi)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001058{
1059 struct sock *sk = (struct sock *)pi;
1060 u16 control = 0;
1061
1062 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1063
1064 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
1065 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001066 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001067 l2cap_send_sframe(pi, control);
1068 return;
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03001069 }
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001070
Gustavo F. Padovane0f66212010-06-21 18:50:49 -03001071 if (l2cap_ertm_send(sk) > 0)
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03001072 return;
1073
1074 control |= L2CAP_SUPER_RCV_READY;
1075 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001076}
1077
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -03001078static void l2cap_send_srejtail(struct sock *sk)
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001079{
1080 struct srej_list *tail;
1081 u16 control;
1082
1083 control = L2CAP_SUPER_SELECT_REJECT;
1084 control |= L2CAP_CTRL_FINAL;
1085
1086 tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
1087 control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
1088
1089 l2cap_send_sframe(l2cap_pi(sk), control);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03001090}
1091
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001092static 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 -07001093{
1094 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001095 struct sk_buff **frag;
1096 int err, sent = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03001098 if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001099 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
1101 sent += count;
1102 len -= count;
1103
1104 /* Continuation fragments (no L2CAP header) */
1105 frag = &skb_shinfo(skb)->frag_list;
1106 while (len) {
1107 count = min_t(unsigned int, conn->mtu, len);
1108
1109 *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
1110 if (!*frag)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001111 return err;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001112 if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
1113 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114
1115 sent += count;
1116 len -= count;
1117
1118 frag = &(*frag)->next;
1119 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120
1121 return sent;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001122}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001124struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001125{
1126 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1127 struct sk_buff *skb;
1128 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1129 struct l2cap_hdr *lh;
1130
1131 BT_DBG("sk %p len %d", sk, (int)len);
1132
1133 count = min_t(unsigned int, (conn->mtu - hlen), len);
1134 skb = bt_skb_send_alloc(sk, count + hlen,
1135 msg->msg_flags & MSG_DONTWAIT, &err);
1136 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001137 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001138
1139 /* Create L2CAP header */
1140 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1141 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1142 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1143 put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
1144
1145 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1146 if (unlikely(err < 0)) {
1147 kfree_skb(skb);
1148 return ERR_PTR(err);
1149 }
1150 return skb;
1151}
1152
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001153struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001154{
1155 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1156 struct sk_buff *skb;
1157 int err, count, hlen = L2CAP_HDR_SIZE;
1158 struct l2cap_hdr *lh;
1159
1160 BT_DBG("sk %p len %d", sk, (int)len);
1161
1162 count = min_t(unsigned int, (conn->mtu - hlen), len);
1163 skb = bt_skb_send_alloc(sk, count + hlen,
1164 msg->msg_flags & MSG_DONTWAIT, &err);
1165 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001166 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001167
1168 /* Create L2CAP header */
1169 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1170 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1171 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1172
1173 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1174 if (unlikely(err < 0)) {
1175 kfree_skb(skb);
1176 return ERR_PTR(err);
1177 }
1178 return skb;
1179}
1180
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001181struct 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 -03001182{
1183 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1184 struct sk_buff *skb;
1185 int err, count, hlen = L2CAP_HDR_SIZE + 2;
1186 struct l2cap_hdr *lh;
1187
1188 BT_DBG("sk %p len %d", sk, (int)len);
1189
Gustavo F. Padovan0ee0d202010-05-01 16:15:41 -03001190 if (!conn)
1191 return ERR_PTR(-ENOTCONN);
1192
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001193 if (sdulen)
1194 hlen += 2;
1195
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001196 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1197 hlen += 2;
1198
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001199 count = min_t(unsigned int, (conn->mtu - hlen), len);
1200 skb = bt_skb_send_alloc(sk, count + hlen,
1201 msg->msg_flags & MSG_DONTWAIT, &err);
1202 if (!skb)
Gustavo F. Padovan0175d622010-09-24 20:30:57 -03001203 return ERR_PTR(err);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001204
1205 /* Create L2CAP header */
1206 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1207 lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
1208 lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1209 put_unaligned_le16(control, skb_put(skb, 2));
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001210 if (sdulen)
1211 put_unaligned_le16(sdulen, skb_put(skb, 2));
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001212
1213 err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
1214 if (unlikely(err < 0)) {
1215 kfree_skb(skb);
1216 return ERR_PTR(err);
1217 }
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001218
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001219 if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
1220 put_unaligned_le16(0, skb_put(skb, 2));
1221
Gustavo F. Padovane90bac02009-08-20 22:26:00 -03001222 bt_cb(skb)->retries = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03001223 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224}
1225
Gustavo F. Padovanfd83ccd2011-02-04 03:20:52 -02001226int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001227{
1228 struct l2cap_pinfo *pi = l2cap_pi(sk);
1229 struct sk_buff *skb;
1230 struct sk_buff_head sar_queue;
1231 u16 control;
1232 size_t size = 0;
1233
Gustavo F. Padovanff12fd62010-05-05 22:09:15 -03001234 skb_queue_head_init(&sar_queue);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001235 control = L2CAP_SDU_START;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001236 skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001237 if (IS_ERR(skb))
1238 return PTR_ERR(skb);
1239
1240 __skb_queue_tail(&sar_queue, skb);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001241 len -= pi->remote_mps;
1242 size += pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001243
1244 while (len > 0) {
1245 size_t buflen;
1246
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001247 if (len > pi->remote_mps) {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001248 control = L2CAP_SDU_CONTINUE;
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001249 buflen = pi->remote_mps;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001250 } else {
Gustavo F. Padovan44651b82010-05-01 16:15:43 -03001251 control = L2CAP_SDU_END;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001252 buflen = len;
1253 }
1254
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03001255 skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001256 if (IS_ERR(skb)) {
1257 skb_queue_purge(&sar_queue);
1258 return PTR_ERR(skb);
1259 }
1260
1261 __skb_queue_tail(&sar_queue, skb);
1262 len -= buflen;
1263 size += buflen;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001264 }
1265 skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
1266 if (sk->sk_send_head == NULL)
1267 sk->sk_send_head = sar_queue.next;
1268
1269 return size;
1270}
1271
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272static void l2cap_chan_ready(struct sock *sk)
1273{
1274 struct sock *parent = bt_sk(sk)->parent;
1275
1276 BT_DBG("sk %p, parent %p", sk, parent);
1277
1278 l2cap_pi(sk)->conf_state = 0;
1279 l2cap_sock_clear_timer(sk);
1280
1281 if (!parent) {
1282 /* Outgoing channel.
1283 * Wake up socket sleeping on connect.
1284 */
1285 sk->sk_state = BT_CONNECTED;
1286 sk->sk_state_change(sk);
1287 } else {
1288 /* Incoming channel.
1289 * Wake up socket sleeping on accept.
1290 */
1291 parent->sk_data_ready(parent, 0);
1292 }
1293}
1294
1295/* Copy frame to all raw sockets on that connection */
1296static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
1297{
1298 struct l2cap_chan_list *l = &conn->chan_list;
1299 struct sk_buff *nskb;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001300 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301
1302 BT_DBG("conn %p", conn);
1303
1304 read_lock(&l->lock);
1305 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
1306 if (sk->sk_type != SOCK_RAW)
1307 continue;
1308
1309 /* Don't send frame to the socket it came from */
1310 if (skb->sk == sk)
1311 continue;
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001312 nskb = skb_clone(skb, GFP_ATOMIC);
1313 if (!nskb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 continue;
1315
1316 if (sock_queue_rcv_skb(sk, nskb))
1317 kfree_skb(nskb);
1318 }
1319 read_unlock(&l->lock);
1320}
1321
1322/* ---- L2CAP signalling commands ---- */
1323static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
1324 u8 code, u8 ident, u16 dlen, void *data)
1325{
1326 struct sk_buff *skb, **frag;
1327 struct l2cap_cmd_hdr *cmd;
1328 struct l2cap_hdr *lh;
1329 int len, count;
1330
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03001331 BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
1332 conn, code, ident, dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333
1334 len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
1335 count = min_t(unsigned int, conn->mtu, len);
1336
1337 skb = bt_skb_alloc(count, GFP_ATOMIC);
1338 if (!skb)
1339 return NULL;
1340
1341 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001342 lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03001343 lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344
1345 cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
1346 cmd->code = code;
1347 cmd->ident = ident;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001348 cmd->len = cpu_to_le16(dlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349
1350 if (dlen) {
1351 count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
1352 memcpy(skb_put(skb, count), data, count);
1353 data += count;
1354 }
1355
1356 len -= skb->len;
1357
1358 /* Continuation fragments (no L2CAP header) */
1359 frag = &skb_shinfo(skb)->frag_list;
1360 while (len) {
1361 count = min_t(unsigned int, conn->mtu, len);
1362
1363 *frag = bt_skb_alloc(count, GFP_ATOMIC);
1364 if (!*frag)
1365 goto fail;
1366
1367 memcpy(skb_put(*frag, count), data, count);
1368
1369 len -= count;
1370 data += count;
1371
1372 frag = &(*frag)->next;
1373 }
1374
1375 return skb;
1376
1377fail:
1378 kfree_skb(skb);
1379 return NULL;
1380}
1381
1382static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
1383{
1384 struct l2cap_conf_opt *opt = *ptr;
1385 int len;
1386
1387 len = L2CAP_CONF_OPT_SIZE + opt->len;
1388 *ptr += len;
1389
1390 *type = opt->type;
1391 *olen = opt->len;
1392
1393 switch (opt->len) {
1394 case 1:
1395 *val = *((u8 *) opt->val);
1396 break;
1397
1398 case 2:
steven miaobfaaeb32010-10-16 18:29:47 -04001399 *val = get_unaligned_le16(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 break;
1401
1402 case 4:
steven miaobfaaeb32010-10-16 18:29:47 -04001403 *val = get_unaligned_le32(opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 break;
1405
1406 default:
1407 *val = (unsigned long) opt->val;
1408 break;
1409 }
1410
1411 BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
1412 return len;
1413}
1414
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
1416{
1417 struct l2cap_conf_opt *opt = *ptr;
1418
1419 BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
1420
1421 opt->type = type;
1422 opt->len = len;
1423
1424 switch (len) {
1425 case 1:
1426 *((u8 *) opt->val) = val;
1427 break;
1428
1429 case 2:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001430 put_unaligned_le16(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 break;
1432
1433 case 4:
Gustavo F. Padovan4f8b6912010-10-18 14:25:53 -02001434 put_unaligned_le32(val, opt->val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 break;
1436
1437 default:
1438 memcpy(opt->val, (void *) val, len);
1439 break;
1440 }
1441
1442 *ptr += L2CAP_CONF_OPT_SIZE + len;
1443}
1444
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001445static void l2cap_ack_timeout(unsigned long arg)
1446{
1447 struct sock *sk = (void *) arg;
1448
1449 bh_lock_sock(sk);
1450 l2cap_send_ack(l2cap_pi(sk));
1451 bh_unlock_sock(sk);
1452}
1453
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001454static inline void l2cap_ertm_init(struct sock *sk)
1455{
1456 l2cap_pi(sk)->expected_ack_seq = 0;
1457 l2cap_pi(sk)->unacked_frames = 0;
1458 l2cap_pi(sk)->buffer_seq = 0;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03001459 l2cap_pi(sk)->num_acked = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03001460 l2cap_pi(sk)->frames_sent = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001461
1462 setup_timer(&l2cap_pi(sk)->retrans_timer,
1463 l2cap_retrans_timeout, (unsigned long) sk);
1464 setup_timer(&l2cap_pi(sk)->monitor_timer,
1465 l2cap_monitor_timeout, (unsigned long) sk);
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03001466 setup_timer(&l2cap_pi(sk)->ack_timer,
1467 l2cap_ack_timeout, (unsigned long) sk);
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001468
1469 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03001470 __skb_queue_head_init(BUSY_QUEUE(sk));
1471
1472 INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03001473
1474 sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03001475}
1476
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001477static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
1478{
1479 switch (mode) {
1480 case L2CAP_MODE_STREAMING:
1481 case L2CAP_MODE_ERTM:
1482 if (l2cap_mode_supported(mode, remote_feat_mask))
1483 return mode;
1484 /* fall through */
1485 default:
1486 return L2CAP_MODE_BASIC;
1487 }
1488}
1489
Gustavo F. Padovan68983252011-02-04 03:02:31 -02001490int l2cap_build_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491{
1492 struct l2cap_pinfo *pi = l2cap_pi(sk);
1493 struct l2cap_conf_req *req = data;
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03001494 struct l2cap_conf_rfc rfc = { .mode = pi->mode };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 void *ptr = req->data;
1496
1497 BT_DBG("sk %p", sk);
1498
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001499 if (pi->num_conf_req || pi->num_conf_rsp)
1500 goto done;
1501
1502 switch (pi->mode) {
1503 case L2CAP_MODE_STREAMING:
1504 case L2CAP_MODE_ERTM:
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001505 if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001506 break;
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001507
Gustavo F. Padovan2ba13ed2010-06-09 16:39:05 -03001508 /* fall through */
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001509 default:
1510 pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
1511 break;
1512 }
1513
1514done:
Gustavo F. Padovan7990681c2011-01-24 16:01:43 -02001515 if (pi->imtu != L2CAP_DEFAULT_MTU)
1516 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
1517
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001518 switch (pi->mode) {
1519 case L2CAP_MODE_BASIC:
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001520 if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
1521 !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
1522 break;
1523
Gustavo F. Padovan62547752010-06-08 20:05:31 -03001524 rfc.mode = L2CAP_MODE_BASIC;
1525 rfc.txwin_size = 0;
1526 rfc.max_transmit = 0;
1527 rfc.retrans_timeout = 0;
1528 rfc.monitor_timeout = 0;
1529 rfc.max_pdu_size = 0;
1530
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001531 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1532 (unsigned long) &rfc);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001533 break;
1534
1535 case L2CAP_MODE_ERTM:
1536 rfc.mode = L2CAP_MODE_ERTM;
Gustavo F. Padovan14b5aa72010-05-01 16:15:40 -03001537 rfc.txwin_size = pi->tx_win;
Gustavo F. Padovan68d7f0c2010-05-01 16:15:41 -03001538 rfc.max_transmit = pi->max_tx;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001539 rfc.retrans_timeout = 0;
1540 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001541 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001542 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001543 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001544
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001545 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1546 (unsigned long) &rfc);
1547
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001548 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1549 break;
1550
1551 if (pi->fcs == L2CAP_FCS_NONE ||
1552 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1553 pi->fcs = L2CAP_FCS_NONE;
1554 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1555 }
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001556 break;
1557
1558 case L2CAP_MODE_STREAMING:
1559 rfc.mode = L2CAP_MODE_STREAMING;
1560 rfc.txwin_size = 0;
1561 rfc.max_transmit = 0;
1562 rfc.retrans_timeout = 0;
1563 rfc.monitor_timeout = 0;
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03001564 rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
Gustavo F. Padovand1daa092010-05-01 16:15:36 -03001565 if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001566 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001567
Gustavo F. Padovan63406502010-08-03 23:49:29 -03001568 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
1569 (unsigned long) &rfc);
1570
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001571 if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
1572 break;
1573
1574 if (pi->fcs == L2CAP_FCS_NONE ||
1575 pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
1576 pi->fcs = L2CAP_FCS_NONE;
1577 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
1578 }
Marcel Holtmann65c7c492009-05-02 23:07:53 -07001579 break;
1580 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581
1582 /* FIXME: Need actual value of the flush timeout */
1583 //if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
1584 // l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to);
1585
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001586 req->dcid = cpu_to_le16(pi->dcid);
1587 req->flags = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588
1589 return ptr - data;
1590}
1591
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001592static int l2cap_parse_conf_req(struct sock *sk, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593{
1594 struct l2cap_pinfo *pi = l2cap_pi(sk);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001595 struct l2cap_conf_rsp *rsp = data;
1596 void *ptr = rsp->data;
1597 void *req = pi->conf_req;
1598 int len = pi->conf_len;
1599 int type, hint, olen;
1600 unsigned long val;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001601 struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
Marcel Holtmann861d6882007-10-20 13:37:06 +02001602 u16 mtu = L2CAP_DEFAULT_MTU;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001603 u16 result = L2CAP_CONF_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001605 BT_DBG("sk %p", sk);
Marcel Holtmann820ae1b2006-11-18 22:15:00 +01001606
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001607 while (len >= L2CAP_CONF_OPT_SIZE) {
1608 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609
Gustavo F. Padovan589d2742009-04-20 01:31:07 -03001610 hint = type & L2CAP_CONF_HINT;
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07001611 type &= L2CAP_CONF_MASK;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001612
1613 switch (type) {
1614 case L2CAP_CONF_MTU:
Marcel Holtmann861d6882007-10-20 13:37:06 +02001615 mtu = val;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001616 break;
1617
1618 case L2CAP_CONF_FLUSH_TO:
1619 pi->flush_to = val;
1620 break;
1621
1622 case L2CAP_CONF_QOS:
1623 break;
1624
Marcel Holtmann6464f352007-10-20 13:39:51 +02001625 case L2CAP_CONF_RFC:
1626 if (olen == sizeof(rfc))
1627 memcpy(&rfc, (void *) val, olen);
1628 break;
1629
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03001630 case L2CAP_CONF_FCS:
1631 if (val == L2CAP_FCS_NONE)
1632 pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
1633
1634 break;
1635
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001636 default:
1637 if (hint)
1638 break;
1639
1640 result = L2CAP_CONF_UNKNOWN;
1641 *((u8 *) ptr++) = type;
1642 break;
1643 }
1644 }
1645
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03001646 if (pi->num_conf_rsp || pi->num_conf_req > 1)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001647 goto done;
1648
1649 switch (pi->mode) {
1650 case L2CAP_MODE_STREAMING:
1651 case L2CAP_MODE_ERTM:
Gustavo F. Padovan85eb53c2010-06-03 18:43:28 -03001652 if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
1653 pi->mode = l2cap_select_mode(rfc.mode,
1654 pi->conn->feat_mask);
1655 break;
1656 }
1657
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001658 if (pi->mode != rfc.mode)
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001659 return -ECONNREFUSED;
Gustavo F. Padovan742e5192010-06-08 19:09:48 -03001660
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001661 break;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001662 }
1663
1664done:
1665 if (pi->mode != rfc.mode) {
1666 result = L2CAP_CONF_UNACCEPT;
1667 rfc.mode = pi->mode;
1668
1669 if (pi->num_conf_rsp == 1)
1670 return -ECONNREFUSED;
1671
1672 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1673 sizeof(rfc), (unsigned long) &rfc);
1674 }
1675
1676
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001677 if (result == L2CAP_CONF_SUCCESS) {
1678 /* Configure output options and let the other side know
1679 * which ones we don't like. */
1680
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001681 if (mtu < L2CAP_DEFAULT_MIN_MTU)
1682 result = L2CAP_CONF_UNACCEPT;
1683 else {
1684 pi->omtu = mtu;
1685 pi->conf_state |= L2CAP_CONF_MTU_DONE;
1686 }
1687 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001688
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001689 switch (rfc.mode) {
1690 case L2CAP_MODE_BASIC:
1691 pi->fcs = L2CAP_FCS_NONE;
1692 pi->conf_state |= L2CAP_CONF_MODE_DONE;
1693 break;
1694
1695 case L2CAP_MODE_ERTM:
1696 pi->remote_tx_win = rfc.txwin_size;
1697 pi->remote_max_tx = rfc.max_transmit;
Mat Martineau86b1b262010-08-05 15:54:22 -07001698
1699 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1700 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001701
1702 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001703
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001704 rfc.retrans_timeout =
1705 le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
1706 rfc.monitor_timeout =
1707 le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001708
1709 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001710
1711 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1712 sizeof(rfc), (unsigned long) &rfc);
1713
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001714 break;
1715
1716 case L2CAP_MODE_STREAMING:
Mat Martineau86b1b262010-08-05 15:54:22 -07001717 if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
1718 rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001719
1720 pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001721
1722 pi->conf_state |= L2CAP_CONF_MODE_DONE;
Gustavo F. Padovan68ae6632009-10-17 21:41:01 -03001723
1724 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1725 sizeof(rfc), (unsigned long) &rfc);
1726
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001727 break;
1728
1729 default:
Marcel Holtmann6464f352007-10-20 13:39:51 +02001730 result = L2CAP_CONF_UNACCEPT;
1731
1732 memset(&rfc, 0, sizeof(rfc));
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001733 rfc.mode = pi->mode;
Marcel Holtmann6464f352007-10-20 13:39:51 +02001734 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001735
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001736 if (result == L2CAP_CONF_SUCCESS)
1737 pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
1738 }
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001739 rsp->scid = cpu_to_le16(pi->dcid);
1740 rsp->result = cpu_to_le16(result);
1741 rsp->flags = cpu_to_le16(0x0000);
1742
1743 return ptr - data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744}
1745
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001746static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
1747{
1748 struct l2cap_pinfo *pi = l2cap_pi(sk);
1749 struct l2cap_conf_req *req = data;
1750 void *ptr = req->data;
1751 int type, olen;
1752 unsigned long val;
1753 struct l2cap_conf_rfc rfc;
1754
1755 BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
1756
1757 while (len >= L2CAP_CONF_OPT_SIZE) {
1758 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1759
1760 switch (type) {
1761 case L2CAP_CONF_MTU:
1762 if (val < L2CAP_DEFAULT_MIN_MTU) {
1763 *result = L2CAP_CONF_UNACCEPT;
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001764 pi->imtu = L2CAP_DEFAULT_MIN_MTU;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001765 } else
Andrei Emeltchenko8183b772010-09-01 15:17:25 +03001766 pi->imtu = val;
1767 l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001768 break;
1769
1770 case L2CAP_CONF_FLUSH_TO:
1771 pi->flush_to = val;
1772 l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
1773 2, pi->flush_to);
1774 break;
1775
1776 case L2CAP_CONF_RFC:
1777 if (olen == sizeof(rfc))
1778 memcpy(&rfc, (void *)val, olen);
1779
1780 if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
1781 rfc.mode != pi->mode)
1782 return -ECONNREFUSED;
1783
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001784 pi->fcs = 0;
1785
1786 l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
1787 sizeof(rfc), (unsigned long) &rfc);
1788 break;
1789 }
1790 }
1791
Gustavo F. Padovan6c2ea7a2010-06-08 20:08:49 -03001792 if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
1793 return -ECONNREFUSED;
1794
1795 pi->mode = rfc.mode;
1796
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001797 if (*result == L2CAP_CONF_SUCCESS) {
1798 switch (rfc.mode) {
1799 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001800 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1801 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001802 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001803 break;
1804 case L2CAP_MODE_STREAMING:
Gustavo F. Padovan1c762152010-05-01 16:15:40 -03001805 pi->mps = le16_to_cpu(rfc.max_pdu_size);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03001806 }
1807 }
1808
1809 req->dcid = cpu_to_le16(pi->dcid);
1810 req->flags = cpu_to_le16(0x0000);
1811
1812 return ptr - data;
1813}
1814
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001815static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816{
1817 struct l2cap_conf_rsp *rsp = data;
1818 void *ptr = rsp->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001820 BT_DBG("sk %p", sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001822 rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02001823 rsp->result = cpu_to_le16(result);
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001824 rsp->flags = cpu_to_le16(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825
1826 return ptr - data;
1827}
1828
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001829static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
1830{
1831 struct l2cap_pinfo *pi = l2cap_pi(sk);
1832 int type, olen;
1833 unsigned long val;
1834 struct l2cap_conf_rfc rfc;
1835
1836 BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
1837
1838 if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
1839 return;
1840
1841 while (len >= L2CAP_CONF_OPT_SIZE) {
1842 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
1843
1844 switch (type) {
1845 case L2CAP_CONF_RFC:
1846 if (olen == sizeof(rfc))
1847 memcpy(&rfc, (void *)val, olen);
1848 goto done;
1849 }
1850 }
1851
1852done:
1853 switch (rfc.mode) {
1854 case L2CAP_MODE_ERTM:
Gustavo F. Padovan10467e92010-05-01 16:15:40 -03001855 pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
1856 pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03001857 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1858 break;
1859 case L2CAP_MODE_STREAMING:
1860 pi->mps = le16_to_cpu(rfc.max_pdu_size);
1861 }
1862}
1863
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001864static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1865{
1866 struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
1867
1868 if (rej->reason != 0x0000)
1869 return 0;
1870
1871 if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
1872 cmd->ident == conn->info_ident) {
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001873 del_timer(&conn->info_timer);
Marcel Holtmann984947d2009-02-06 23:35:19 +01001874
1875 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01001876 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01001877
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02001878 l2cap_conn_start(conn);
1879 }
1880
1881 return 0;
1882}
1883
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
1885{
1886 struct l2cap_chan_list *list = &conn->chan_list;
1887 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
1888 struct l2cap_conn_rsp rsp;
Nathan Holsteind793fe82010-10-15 11:54:02 -04001889 struct sock *parent, *sk = NULL;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001890 int result, status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891
1892 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001893 __le16 psm = req->psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894
1895 BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
1896
1897 /* Check if we have socket listening on psm */
1898 parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
1899 if (!parent) {
1900 result = L2CAP_CR_BAD_PSM;
1901 goto sendresp;
1902 }
1903
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00001904 bh_lock_sock(parent);
1905
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001906 /* Check if the ACL is secure enough (if not SDP) */
1907 if (psm != cpu_to_le16(0x0001) &&
1908 !hci_conn_check_link_mode(conn->hcon)) {
Marcel Holtmann2950f212009-02-12 14:02:50 +01001909 conn->disc_reason = 0x05;
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02001910 result = L2CAP_CR_SEC_BLOCK;
1911 goto response;
1912 }
1913
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914 result = L2CAP_CR_NO_MEM;
1915
1916 /* Check for backlog size */
1917 if (sk_acceptq_is_full(parent)) {
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001918 BT_DBG("backlog full %d", parent->sk_ack_backlog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 goto response;
1920 }
1921
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001922 sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 if (!sk)
1924 goto response;
1925
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02001926 write_lock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927
1928 /* Check if we already have channel with that dcid */
1929 if (__l2cap_get_chan_by_dcid(list, scid)) {
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02001930 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 sock_set_flag(sk, SOCK_ZAPPED);
1932 l2cap_sock_kill(sk);
1933 goto response;
1934 }
1935
1936 hci_conn_hold(conn->hcon);
1937
1938 l2cap_sock_init(sk, parent);
1939 bacpy(&bt_sk(sk)->src, conn->src);
1940 bacpy(&bt_sk(sk)->dst, conn->dst);
1941 l2cap_pi(sk)->psm = psm;
1942 l2cap_pi(sk)->dcid = scid;
1943
1944 __l2cap_chan_add(conn, sk, parent);
1945 dcid = l2cap_pi(sk)->scid;
1946
1947 l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
1948
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949 l2cap_pi(sk)->ident = cmd->ident;
1950
Marcel Holtmann984947d2009-02-06 23:35:19 +01001951 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01001952 if (l2cap_check_security(sk)) {
Marcel Holtmannf66dc812009-01-15 21:57:00 +01001953 if (bt_sk(sk)->defer_setup) {
1954 sk->sk_state = BT_CONNECT2;
1955 result = L2CAP_CR_PEND;
1956 status = L2CAP_CS_AUTHOR_PEND;
1957 parent->sk_data_ready(parent, 0);
1958 } else {
1959 sk->sk_state = BT_CONFIG;
1960 result = L2CAP_CR_SUCCESS;
1961 status = L2CAP_CS_NO_INFO;
1962 }
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001963 } else {
1964 sk->sk_state = BT_CONNECT2;
1965 result = L2CAP_CR_PEND;
1966 status = L2CAP_CS_AUTHEN_PEND;
1967 }
1968 } else {
1969 sk->sk_state = BT_CONNECT2;
1970 result = L2CAP_CR_PEND;
1971 status = L2CAP_CS_NO_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972 }
1973
Marcel Holtmannfd1278d2006-07-12 23:00:07 +02001974 write_unlock_bh(&list->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975
1976response:
1977 bh_unlock_sock(parent);
1978
1979sendresp:
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001980 rsp.scid = cpu_to_le16(scid);
1981 rsp.dcid = cpu_to_le16(dcid);
1982 rsp.result = cpu_to_le16(result);
1983 rsp.status = cpu_to_le16(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Marcel Holtmann79d554a2008-07-14 20:13:44 +02001985
1986 if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
1987 struct l2cap_info_req info;
1988 info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
1989
1990 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
1991 conn->info_ident = l2cap_get_ident(conn);
1992
1993 mod_timer(&conn->info_timer, jiffies +
1994 msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
1995
1996 l2cap_send_cmd(conn, conn->info_ident,
1997 L2CAP_INFO_REQ, sizeof(info), &info);
1998 }
1999
Nathan Holsteind793fe82010-10-15 11:54:02 -04002000 if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002001 result == L2CAP_CR_SUCCESS) {
2002 u8 buf[128];
2003 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2004 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2005 l2cap_build_conf_req(sk, buf), buf);
2006 l2cap_pi(sk)->num_conf_req++;
2007 }
2008
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 return 0;
2010}
2011
2012static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2013{
2014 struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
2015 u16 scid, dcid, result, status;
2016 struct sock *sk;
2017 u8 req[128];
2018
2019 scid = __le16_to_cpu(rsp->scid);
2020 dcid = __le16_to_cpu(rsp->dcid);
2021 result = __le16_to_cpu(rsp->result);
2022 status = __le16_to_cpu(rsp->status);
2023
2024 BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
2025
2026 if (scid) {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002027 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2028 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002029 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 } else {
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002031 sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
2032 if (!sk)
João Paulo Rechi Vita57d3b222010-06-22 13:56:26 -03002033 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 }
2035
2036 switch (result) {
2037 case L2CAP_CR_SUCCESS:
2038 sk->sk_state = BT_CONFIG;
2039 l2cap_pi(sk)->ident = 0;
2040 l2cap_pi(sk)->dcid = dcid;
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002041 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
2042
Gustavo F. Padovane9aeb2d2010-07-08 20:08:18 -03002043 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
2044 break;
2045
2046 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2047
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2049 l2cap_build_conf_req(sk, req), req);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002050 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 break;
2052
2053 case L2CAP_CR_PEND:
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01002054 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 break;
2056
2057 default:
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002058 /* don't delete l2cap channel if sk is owned by user */
2059 if (sock_owned_by_user(sk)) {
2060 sk->sk_state = BT_DISCONN;
2061 l2cap_sock_clear_timer(sk);
2062 l2cap_sock_set_timer(sk, HZ / 5);
2063 break;
2064 }
2065
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066 l2cap_chan_del(sk, ECONNREFUSED);
2067 break;
2068 }
2069
2070 bh_unlock_sock(sk);
2071 return 0;
2072}
2073
Mat Martineau8c462b62010-08-24 15:35:42 -07002074static inline void set_default_fcs(struct l2cap_pinfo *pi)
2075{
2076 /* FCS is enabled only in ERTM or streaming mode, if one or both
2077 * sides request it.
2078 */
2079 if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
2080 pi->fcs = L2CAP_FCS_NONE;
2081 else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
2082 pi->fcs = L2CAP_FCS_CRC16;
2083}
2084
Al Viro88219a02007-07-29 00:17:25 -07002085static 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 -07002086{
2087 struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
2088 u16 dcid, flags;
2089 u8 rsp[64];
2090 struct sock *sk;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002091 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092
2093 dcid = __le16_to_cpu(req->dcid);
2094 flags = __le16_to_cpu(req->flags);
2095
2096 BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
2097
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002098 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2099 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 return -ENOENT;
2101
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002102 if (sk->sk_state != BT_CONFIG) {
2103 struct l2cap_cmd_rej rej;
2104
2105 rej.reason = cpu_to_le16(0x0002);
2106 l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
2107 sizeof(rej), &rej);
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002108 goto unlock;
Gustavo F. Padovandf6bd742010-06-14 02:26:15 -03002109 }
Marcel Holtmann354f60a2006-11-18 22:15:20 +01002110
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002111 /* Reject if config buffer is too small. */
Al Viro88219a02007-07-29 00:17:25 -07002112 len = cmd_len - sizeof(*req);
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002113 if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
2114 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2115 l2cap_build_conf_rsp(sk, rsp,
2116 L2CAP_CONF_REJECT, flags), rsp);
2117 goto unlock;
2118 }
2119
2120 /* Store config. */
2121 memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
2122 l2cap_pi(sk)->conf_len += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123
2124 if (flags & 0x0001) {
2125 /* Incomplete config. Send empty response. */
2126 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002127 l2cap_build_conf_rsp(sk, rsp,
2128 L2CAP_CONF_SUCCESS, 0x0001), rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129 goto unlock;
2130 }
2131
2132 /* Complete config. */
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002133 len = l2cap_parse_conf_req(sk, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002134 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002135 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 goto unlock;
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002137 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002139 l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002140 l2cap_pi(sk)->num_conf_rsp++;
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002141
Marcel Holtmann5dee9e72007-05-24 14:27:19 +02002142 /* Reset config buffer. */
2143 l2cap_pi(sk)->conf_len = 0;
2144
Marcel Holtmann876d9482007-10-20 13:35:42 +02002145 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
2146 goto unlock;
2147
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002149 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002150
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002152
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002153 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002154 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002155 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002156 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2157 l2cap_ertm_init(sk);
2158
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 l2cap_chan_ready(sk);
Marcel Holtmann876d9482007-10-20 13:35:42 +02002160 goto unlock;
2161 }
2162
2163 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002164 u8 buf[64];
Haijun Liuab3e5712010-09-30 16:52:40 +08002165 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
Marcel Holtmann79d554a2008-07-14 20:13:44 +02002167 l2cap_build_conf_req(sk, buf), buf);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002168 l2cap_pi(sk)->num_conf_req++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 }
2170
2171unlock:
2172 bh_unlock_sock(sk);
2173 return 0;
2174}
2175
2176static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2177{
2178 struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
2179 u16 scid, flags, result;
2180 struct sock *sk;
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002181 int len = cmd->len - sizeof(*rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182
2183 scid = __le16_to_cpu(rsp->scid);
2184 flags = __le16_to_cpu(rsp->flags);
2185 result = __le16_to_cpu(rsp->result);
2186
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002187 BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
2188 scid, flags, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002190 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2191 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 return 0;
2193
2194 switch (result) {
2195 case L2CAP_CONF_SUCCESS:
Gustavo F. Padovan7b1c0042010-05-01 16:15:39 -03002196 l2cap_conf_rfc_get(sk, rsp->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197 break;
2198
2199 case L2CAP_CONF_UNACCEPT:
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002200 if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002201 char req[64];
2202
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002203 if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002204 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Andrei Emeltchenkoc2c77ec2010-03-19 10:26:28 +02002205 goto done;
2206 }
2207
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002208 /* throw out any old stored conf requests */
2209 result = L2CAP_CONF_SUCCESS;
2210 len = l2cap_parse_conf_rsp(sk, rsp->data,
2211 len, req, &result);
2212 if (len < 0) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002213 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Gustavo F. Padovanf2fcfcd2009-07-04 15:06:24 -03002214 goto done;
2215 }
2216
2217 l2cap_send_cmd(conn, l2cap_get_ident(conn),
2218 L2CAP_CONF_REQ, len, req);
2219 l2cap_pi(sk)->num_conf_req++;
2220 if (result != L2CAP_CONF_SUCCESS)
2221 goto done;
2222 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 }
2224
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09002225 default:
Marcel Holtmannb1235d72008-07-14 20:13:54 +02002226 sk->sk_err = ECONNRESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227 l2cap_sock_set_timer(sk, HZ * 5);
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002228 l2cap_send_disconn_req(conn, sk, ECONNRESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 goto done;
2230 }
2231
2232 if (flags & 0x01)
2233 goto done;
2234
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235 l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
2236
2237 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
Mat Martineau8c462b62010-08-24 15:35:42 -07002238 set_default_fcs(l2cap_pi(sk));
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002239
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240 sk->sk_state = BT_CONNECTED;
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002241 l2cap_pi(sk)->next_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002242 l2cap_pi(sk)->expected_tx_seq = 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002243 __skb_queue_head_init(TX_QUEUE(sk));
Gustavo F. Padovan0565c1c2009-10-03 02:34:36 -03002244 if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
2245 l2cap_ertm_init(sk);
2246
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 l2cap_chan_ready(sk);
2248 }
2249
2250done:
2251 bh_unlock_sock(sk);
2252 return 0;
2253}
2254
2255static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2256{
2257 struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
2258 struct l2cap_disconn_rsp rsp;
2259 u16 dcid, scid;
2260 struct sock *sk;
2261
2262 scid = __le16_to_cpu(req->scid);
2263 dcid = __le16_to_cpu(req->dcid);
2264
2265 BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
2266
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002267 sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
2268 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269 return 0;
2270
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002271 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
2272 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
2274
2275 sk->sk_shutdown = SHUTDOWN_MASK;
2276
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002277 /* don't delete l2cap channel if sk is owned by user */
2278 if (sock_owned_by_user(sk)) {
2279 sk->sk_state = BT_DISCONN;
2280 l2cap_sock_clear_timer(sk);
2281 l2cap_sock_set_timer(sk, HZ / 5);
2282 bh_unlock_sock(sk);
2283 return 0;
2284 }
2285
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286 l2cap_chan_del(sk, ECONNRESET);
2287 bh_unlock_sock(sk);
2288
2289 l2cap_sock_kill(sk);
2290 return 0;
2291}
2292
2293static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2294{
2295 struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
2296 u16 dcid, scid;
2297 struct sock *sk;
2298
2299 scid = __le16_to_cpu(rsp->scid);
2300 dcid = __le16_to_cpu(rsp->dcid);
2301
2302 BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
2303
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03002304 sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
2305 if (!sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 return 0;
2307
Andrei Emeltchenkoa49184c2010-11-03 12:32:44 +02002308 /* don't delete l2cap channel if sk is owned by user */
2309 if (sock_owned_by_user(sk)) {
2310 sk->sk_state = BT_DISCONN;
2311 l2cap_sock_clear_timer(sk);
2312 l2cap_sock_set_timer(sk, HZ / 5);
2313 bh_unlock_sock(sk);
2314 return 0;
2315 }
2316
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 l2cap_chan_del(sk, 0);
2318 bh_unlock_sock(sk);
2319
2320 l2cap_sock_kill(sk);
2321 return 0;
2322}
2323
2324static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2325{
2326 struct l2cap_info_req *req = (struct l2cap_info_req *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 u16 type;
2328
2329 type = __le16_to_cpu(req->type);
2330
2331 BT_DBG("type 0x%4.4x", type);
2332
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002333 if (type == L2CAP_IT_FEAT_MASK) {
2334 u8 buf[8];
Marcel Holtmann44dd46d2009-05-02 19:09:01 -07002335 u32 feat_mask = l2cap_feat_mask;
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002336 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2337 rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
2338 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03002339 if (!disable_ertm)
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002340 feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
2341 | L2CAP_FEAT_FCS;
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03002342 put_unaligned_le32(feat_mask, rsp->data);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002343 l2cap_send_cmd(conn, cmd->ident,
2344 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002345 } else if (type == L2CAP_IT_FIXED_CHAN) {
2346 u8 buf[12];
2347 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
2348 rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2349 rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
2350 memcpy(buf + 4, l2cap_fixed_chan, 8);
2351 l2cap_send_cmd(conn, cmd->ident,
2352 L2CAP_INFO_RSP, sizeof(buf), buf);
Marcel Holtmannf0709e02007-10-20 13:38:51 +02002353 } else {
2354 struct l2cap_info_rsp rsp;
2355 rsp.type = cpu_to_le16(type);
2356 rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
2357 l2cap_send_cmd(conn, cmd->ident,
2358 L2CAP_INFO_RSP, sizeof(rsp), &rsp);
2359 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360
2361 return 0;
2362}
2363
2364static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
2365{
2366 struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
2367 u16 type, result;
2368
2369 type = __le16_to_cpu(rsp->type);
2370 result = __le16_to_cpu(rsp->result);
2371
2372 BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
2373
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002374 del_timer(&conn->info_timer);
2375
Ville Tervoadb08ed2010-08-04 09:43:33 +03002376 if (result != L2CAP_IR_SUCCESS) {
2377 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2378 conn->info_ident = 0;
2379
2380 l2cap_conn_start(conn);
2381
2382 return 0;
2383 }
2384
Marcel Holtmann984947d2009-02-06 23:35:19 +01002385 if (type == L2CAP_IT_FEAT_MASK) {
Harvey Harrison83985312008-05-02 16:25:46 -07002386 conn->feat_mask = get_unaligned_le32(rsp->data);
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002387
Marcel Holtmann47ec1dcd2009-05-02 18:57:55 -07002388 if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002389 struct l2cap_info_req req;
2390 req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
2391
2392 conn->info_ident = l2cap_get_ident(conn);
2393
2394 l2cap_send_cmd(conn, conn->info_ident,
2395 L2CAP_INFO_REQ, sizeof(req), &req);
2396 } else {
2397 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
2398 conn->info_ident = 0;
2399
2400 l2cap_conn_start(conn);
2401 }
2402 } else if (type == L2CAP_IT_FIXED_CHAN) {
Marcel Holtmann984947d2009-02-06 23:35:19 +01002403 conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
Marcel Holtmanne1027a72009-02-09 09:18:02 +01002404 conn->info_ident = 0;
Marcel Holtmann984947d2009-02-06 23:35:19 +01002405
2406 l2cap_conn_start(conn);
2407 }
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002408
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409 return 0;
2410}
2411
2412static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
2413{
2414 u8 *data = skb->data;
2415 int len = skb->len;
2416 struct l2cap_cmd_hdr cmd;
2417 int err = 0;
2418
2419 l2cap_raw_recv(conn, skb);
2420
2421 while (len >= L2CAP_CMD_HDR_SIZE) {
Al Viro88219a02007-07-29 00:17:25 -07002422 u16 cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
2424 data += L2CAP_CMD_HDR_SIZE;
2425 len -= L2CAP_CMD_HDR_SIZE;
2426
Al Viro88219a02007-07-29 00:17:25 -07002427 cmd_len = le16_to_cpu(cmd.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428
Al Viro88219a02007-07-29 00:17:25 -07002429 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 -07002430
Al Viro88219a02007-07-29 00:17:25 -07002431 if (cmd_len > len || !cmd.ident) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 BT_DBG("corrupted command");
2433 break;
2434 }
2435
2436 switch (cmd.code) {
2437 case L2CAP_COMMAND_REJ:
Marcel Holtmann4e8402a2007-10-20 13:37:56 +02002438 l2cap_command_rej(conn, &cmd, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439 break;
2440
2441 case L2CAP_CONN_REQ:
2442 err = l2cap_connect_req(conn, &cmd, data);
2443 break;
2444
2445 case L2CAP_CONN_RSP:
2446 err = l2cap_connect_rsp(conn, &cmd, data);
2447 break;
2448
2449 case L2CAP_CONF_REQ:
Al Viro88219a02007-07-29 00:17:25 -07002450 err = l2cap_config_req(conn, &cmd, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 break;
2452
2453 case L2CAP_CONF_RSP:
2454 err = l2cap_config_rsp(conn, &cmd, data);
2455 break;
2456
2457 case L2CAP_DISCONN_REQ:
2458 err = l2cap_disconnect_req(conn, &cmd, data);
2459 break;
2460
2461 case L2CAP_DISCONN_RSP:
2462 err = l2cap_disconnect_rsp(conn, &cmd, data);
2463 break;
2464
2465 case L2CAP_ECHO_REQ:
Al Viro88219a02007-07-29 00:17:25 -07002466 l2cap_send_cmd(conn, cmd.ident, L2CAP_ECHO_RSP, cmd_len, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 break;
2468
2469 case L2CAP_ECHO_RSP:
2470 break;
2471
2472 case L2CAP_INFO_REQ:
2473 err = l2cap_information_req(conn, &cmd, data);
2474 break;
2475
2476 case L2CAP_INFO_RSP:
2477 err = l2cap_information_rsp(conn, &cmd, data);
2478 break;
2479
2480 default:
2481 BT_ERR("Unknown signaling command 0x%2.2x", cmd.code);
2482 err = -EINVAL;
2483 break;
2484 }
2485
2486 if (err) {
2487 struct l2cap_cmd_rej rej;
2488 BT_DBG("error %d", err);
2489
2490 /* FIXME: Map err to a valid reason */
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07002491 rej.reason = cpu_to_le16(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492 l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
2493 }
2494
Al Viro88219a02007-07-29 00:17:25 -07002495 data += cmd_len;
2496 len -= cmd_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 }
2498
2499 kfree_skb(skb);
2500}
2501
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002502static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
2503{
2504 u16 our_fcs, rcv_fcs;
2505 int hdr_size = L2CAP_HDR_SIZE + 2;
2506
2507 if (pi->fcs == L2CAP_FCS_CRC16) {
2508 skb_trim(skb, skb->len - 2);
2509 rcv_fcs = get_unaligned_le16(skb->data + skb->len);
2510 our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
2511
2512 if (our_fcs != rcv_fcs)
João Paulo Rechi Vita7a560e52010-06-22 13:56:27 -03002513 return -EBADMSG;
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03002514 }
2515 return 0;
2516}
2517
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002518static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
2519{
2520 struct l2cap_pinfo *pi = l2cap_pi(sk);
2521 u16 control = 0;
2522
2523 pi->frames_sent = 0;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002524
2525 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2526
2527 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
Gustavo F. Padovan64988862010-05-10 14:54:14 -03002528 control |= L2CAP_SUPER_RCV_NOT_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002529 l2cap_send_sframe(pi, control);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002530 pi->conn_state |= L2CAP_CONN_RNR_SENT;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002531 }
2532
Gustavo F. Padovan4ea727e2010-06-03 16:34:20 -03002533 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
2534 l2cap_retransmit_frames(sk);
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002535
2536 l2cap_ertm_send(sk);
2537
2538 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
2539 pi->frames_sent == 0) {
2540 control |= L2CAP_SUPER_RCV_READY;
Gustavo F. Padovand5392c82010-05-01 16:15:36 -03002541 l2cap_send_sframe(pi, control);
2542 }
2543}
2544
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002545static 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 -03002546{
2547 struct sk_buff *next_skb;
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002548 struct l2cap_pinfo *pi = l2cap_pi(sk);
2549 int tx_seq_offset, next_tx_seq_offset;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002550
2551 bt_cb(skb)->tx_seq = tx_seq;
2552 bt_cb(skb)->sar = sar;
2553
2554 next_skb = skb_peek(SREJ_QUEUE(sk));
2555 if (!next_skb) {
2556 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002557 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002558 }
2559
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002560 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
2561 if (tx_seq_offset < 0)
2562 tx_seq_offset += 64;
2563
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002564 do {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002565 if (bt_cb(next_skb)->tx_seq == tx_seq)
2566 return -EINVAL;
2567
João Paulo Rechi Vitabfbacc12010-05-31 18:35:44 -03002568 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
2569 pi->buffer_seq) % 64;
2570 if (next_tx_seq_offset < 0)
2571 next_tx_seq_offset += 64;
2572
2573 if (next_tx_seq_offset > tx_seq_offset) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002574 __skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002575 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002576 }
2577
2578 if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
2579 break;
2580
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002581 } while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002582
2583 __skb_queue_tail(SREJ_QUEUE(sk), skb);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03002584
2585 return 0;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002586}
2587
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002588static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
2589{
2590 struct l2cap_pinfo *pi = l2cap_pi(sk);
2591 struct sk_buff *_skb;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002592 int err;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002593
2594 switch (control & L2CAP_CTRL_SAR) {
2595 case L2CAP_SDU_UNSEGMENTED:
2596 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2597 goto drop;
2598
2599 err = sock_queue_rcv_skb(sk, skb);
2600 if (!err)
2601 return err;
2602
2603 break;
2604
2605 case L2CAP_SDU_START:
2606 if (pi->conn_state & L2CAP_CONN_SAR_SDU)
2607 goto drop;
2608
2609 pi->sdu_len = get_unaligned_le16(skb->data);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002610
2611 if (pi->sdu_len > pi->imtu)
2612 goto disconnect;
2613
2614 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002615 if (!pi->sdu)
2616 return -ENOMEM;
2617
2618 /* pull sdu_len bytes only after alloc, because of Local Busy
2619 * condition we have to be sure that this will be executed
2620 * only once, i.e., when alloc does not fail */
2621 skb_pull(skb, 2);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002622
2623 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2624
2625 pi->conn_state |= L2CAP_CONN_SAR_SDU;
2626 pi->partial_sdu_len = skb->len;
2627 break;
2628
2629 case L2CAP_SDU_CONTINUE:
2630 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2631 goto disconnect;
2632
2633 if (!pi->sdu)
2634 goto disconnect;
2635
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002636 pi->partial_sdu_len += skb->len;
2637 if (pi->partial_sdu_len > pi->sdu_len)
2638 goto drop;
2639
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002640 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2641
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002642 break;
2643
2644 case L2CAP_SDU_END:
2645 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2646 goto disconnect;
2647
2648 if (!pi->sdu)
2649 goto disconnect;
2650
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002651 if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002652 pi->partial_sdu_len += skb->len;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002653
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002654 if (pi->partial_sdu_len > pi->imtu)
2655 goto drop;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002656
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002657 if (pi->partial_sdu_len != pi->sdu_len)
2658 goto drop;
Gustavo F. Padovan4178ba42010-05-01 16:15:45 -03002659
2660 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002661 }
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002662
2663 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002664 if (!_skb) {
2665 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2666 return -ENOMEM;
2667 }
2668
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002669 err = sock_queue_rcv_skb(sk, _skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002670 if (err < 0) {
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002671 kfree_skb(_skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002672 pi->conn_state |= L2CAP_CONN_SAR_RETRY;
2673 return err;
2674 }
2675
2676 pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
2677 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002678
2679 kfree_skb(pi->sdu);
2680 break;
2681 }
2682
2683 kfree_skb(skb);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002684 return 0;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002685
2686drop:
2687 kfree_skb(pi->sdu);
2688 pi->sdu = NULL;
2689
2690disconnect:
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03002691 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002692 kfree_skb(skb);
2693 return 0;
2694}
2695
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002696static int l2cap_try_push_rx_skb(struct sock *sk)
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002697{
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002698 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002699 struct sk_buff *skb;
2700 u16 control;
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002701 int err;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002702
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002703 while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
2704 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
2705 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
2706 if (err < 0) {
2707 skb_queue_head(BUSY_QUEUE(sk), skb);
2708 return -EBUSY;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002709 }
2710
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002711 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002712 }
2713
2714 if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
2715 goto done;
2716
2717 control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2718 control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
2719 l2cap_send_sframe(pi, control);
2720 l2cap_pi(sk)->retry_count = 1;
2721
2722 del_timer(&pi->retrans_timer);
2723 __mod_monitor_timer();
2724
2725 l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
2726
2727done:
2728 pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
2729 pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
2730
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002731 BT_DBG("sk %p, Exit local busy", sk);
2732
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002733 return 0;
2734}
2735
2736static void l2cap_busy_work(struct work_struct *work)
2737{
2738 DECLARE_WAITQUEUE(wait, current);
2739 struct l2cap_pinfo *pi =
2740 container_of(work, struct l2cap_pinfo, busy_work);
2741 struct sock *sk = (struct sock *)pi;
2742 int n_tries = 0, timeo = HZ/5, err;
2743 struct sk_buff *skb;
2744
2745 lock_sock(sk);
2746
2747 add_wait_queue(sk_sleep(sk), &wait);
2748 while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
2749 set_current_state(TASK_INTERRUPTIBLE);
2750
2751 if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
2752 err = -EBUSY;
2753 l2cap_send_disconn_req(pi->conn, sk, EBUSY);
2754 break;
2755 }
2756
2757 if (!timeo)
2758 timeo = HZ/5;
2759
2760 if (signal_pending(current)) {
2761 err = sock_intr_errno(timeo);
2762 break;
2763 }
2764
2765 release_sock(sk);
2766 timeo = schedule_timeout(timeo);
2767 lock_sock(sk);
2768
2769 err = sock_error(sk);
2770 if (err)
2771 break;
2772
2773 if (l2cap_try_push_rx_skb(sk) == 0)
2774 break;
2775 }
2776
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002777 set_current_state(TASK_RUNNING);
Marcel Holtmann2b0b05d2010-05-10 11:33:10 +02002778 remove_wait_queue(sk_sleep(sk), &wait);
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002779
2780 release_sock(sk);
2781}
2782
2783static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
2784{
2785 struct l2cap_pinfo *pi = l2cap_pi(sk);
2786 int sctrl, err;
2787
2788 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
2789 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
2790 __skb_queue_tail(BUSY_QUEUE(sk), skb);
Gustavo F. Padovan712132e2010-06-21 19:39:50 -03002791 return l2cap_try_push_rx_skb(sk);
2792
2793
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002794 }
2795
2796 err = l2cap_ertm_reassembly_sdu(sk, skb, control);
2797 if (err >= 0) {
2798 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
2799 return err;
2800 }
2801
2802 /* Busy Condition */
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002803 BT_DBG("sk %p, Enter local busy", sk);
2804
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002805 pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
2806 bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
2807 __skb_queue_tail(BUSY_QUEUE(sk), skb);
2808
2809 sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2810 sctrl |= L2CAP_SUPER_RCV_NOT_READY;
2811 l2cap_send_sframe(pi, sctrl);
2812
2813 pi->conn_state |= L2CAP_CONN_RNR_SENT;
2814
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03002815 del_timer(&pi->ack_timer);
2816
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03002817 queue_work(_busy_wq, &pi->busy_work);
2818
2819 return err;
2820}
2821
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002822static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002823{
2824 struct l2cap_pinfo *pi = l2cap_pi(sk);
2825 struct sk_buff *_skb;
2826 int err = -EINVAL;
2827
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002828 /*
2829 * TODO: We have to notify the userland if some data is lost with the
2830 * Streaming Mode.
2831 */
2832
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002833 switch (control & L2CAP_CTRL_SAR) {
2834 case L2CAP_SDU_UNSEGMENTED:
2835 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
2836 kfree_skb(pi->sdu);
2837 break;
2838 }
2839
2840 err = sock_queue_rcv_skb(sk, skb);
2841 if (!err)
2842 return 0;
2843
2844 break;
2845
2846 case L2CAP_SDU_START:
2847 if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
2848 kfree_skb(pi->sdu);
2849 break;
2850 }
2851
2852 pi->sdu_len = get_unaligned_le16(skb->data);
2853 skb_pull(skb, 2);
2854
Gustavo F. Padovan052897c2010-05-01 16:15:40 -03002855 if (pi->sdu_len > pi->imtu) {
2856 err = -EMSGSIZE;
2857 break;
2858 }
2859
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002860 pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
2861 if (!pi->sdu) {
2862 err = -ENOMEM;
2863 break;
2864 }
2865
2866 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2867
2868 pi->conn_state |= L2CAP_CONN_SAR_SDU;
2869 pi->partial_sdu_len = skb->len;
2870 err = 0;
2871 break;
2872
2873 case L2CAP_SDU_CONTINUE:
2874 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2875 break;
2876
2877 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2878
2879 pi->partial_sdu_len += skb->len;
2880 if (pi->partial_sdu_len > pi->sdu_len)
2881 kfree_skb(pi->sdu);
2882 else
2883 err = 0;
2884
2885 break;
2886
2887 case L2CAP_SDU_END:
2888 if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
2889 break;
2890
2891 memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
2892
2893 pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
2894 pi->partial_sdu_len += skb->len;
2895
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03002896 if (pi->partial_sdu_len > pi->imtu)
2897 goto drop;
2898
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002899 if (pi->partial_sdu_len == pi->sdu_len) {
2900 _skb = skb_clone(pi->sdu, GFP_ATOMIC);
2901 err = sock_queue_rcv_skb(sk, _skb);
2902 if (err < 0)
2903 kfree_skb(_skb);
2904 }
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002905 err = 0;
2906
Gustavo F. Padovan36f2fd52010-05-01 16:15:37 -03002907drop:
2908 kfree_skb(pi->sdu);
Gustavo F. Padovanc74e5602009-08-20 22:25:58 -03002909 break;
2910 }
2911
2912 kfree_skb(skb);
2913 return err;
2914}
2915
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002916static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
2917{
2918 struct sk_buff *skb;
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03002919 u16 control;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002920
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002921 while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002922 if (bt_cb(skb)->tx_seq != tx_seq)
2923 break;
2924
2925 skb = skb_dequeue(SREJ_QUEUE(sk));
Gustavo F. Padovanafefdbc2010-05-01 16:15:43 -03002926 control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03002927 l2cap_ertm_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002928 l2cap_pi(sk)->buffer_seq_srej =
2929 (l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03002930 tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002931 }
2932}
2933
2934static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
2935{
2936 struct l2cap_pinfo *pi = l2cap_pi(sk);
2937 struct srej_list *l, *tmp;
2938 u16 control;
2939
Gustavo F. Padovan59203a22010-05-01 16:15:43 -03002940 list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002941 if (l->tx_seq == tx_seq) {
2942 list_del(&l->list);
2943 kfree(l);
2944 return;
2945 }
2946 control = L2CAP_SUPER_SELECT_REJECT;
2947 control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2948 l2cap_send_sframe(pi, control);
2949 list_del(&l->list);
2950 list_add_tail(&l->list, SREJ_LIST(sk));
2951 }
2952}
2953
2954static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
2955{
2956 struct l2cap_pinfo *pi = l2cap_pi(sk);
2957 struct srej_list *new;
2958 u16 control;
2959
2960 while (tx_seq != pi->expected_tx_seq) {
2961 control = L2CAP_SUPER_SELECT_REJECT;
2962 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
2963 l2cap_send_sframe(pi, control);
2964
2965 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03002966 new->tx_seq = pi->expected_tx_seq;
2967 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002968 list_add_tail(&new->list, SREJ_LIST(sk));
2969 }
Gustavo F. Padovan8ff50ec2010-05-10 19:34:11 -03002970 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002971}
2972
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002973static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
2974{
2975 struct l2cap_pinfo *pi = l2cap_pi(sk);
2976 u8 tx_seq = __get_txseq(rx_control);
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03002977 u8 req_seq = __get_reqseq(rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002978 u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
Gustavo F. Padovanf6337c72010-05-10 18:32:04 -03002979 int tx_seq_offset, expected_tx_seq_offset;
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03002980 int num_to_ack = (pi->tx_win/6) + 1;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002981 int err = 0;
2982
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03002983 BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
2984 rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002985
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03002986 if (L2CAP_CTRL_FINAL & rx_control &&
2987 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03002988 del_timer(&pi->monitor_timer);
2989 if (pi->unacked_frames > 0)
2990 __mod_retrans_timer();
2991 pi->conn_state &= ~L2CAP_CONN_WAIT_F;
2992 }
2993
Gustavo F. Padovan9f121a52009-10-03 02:34:38 -03002994 pi->expected_ack_seq = req_seq;
2995 l2cap_drop_acked_frames(sk);
2996
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03002997 if (tx_seq == pi->expected_tx_seq)
2998 goto expected;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03002999
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003000 tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
3001 if (tx_seq_offset < 0)
3002 tx_seq_offset += 64;
3003
3004 /* invalid tx_seq */
3005 if (tx_seq_offset >= pi->tx_win) {
Gustavo F. Padovan9b108fc2010-05-20 16:21:53 -03003006 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003007 goto drop;
3008 }
3009
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003010 if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
3011 goto drop;
3012
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003013 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3014 struct srej_list *first;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003015
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003016 first = list_first_entry(SREJ_LIST(sk),
3017 struct srej_list, list);
3018 if (tx_seq == first->tx_seq) {
3019 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3020 l2cap_check_srej_gap(sk, tx_seq);
3021
3022 list_del(&first->list);
3023 kfree(first);
3024
3025 if (list_empty(SREJ_LIST(sk))) {
3026 pi->buffer_seq = pi->buffer_seq_srej;
3027 pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan855666cc2010-05-01 16:15:40 -03003028 l2cap_send_ack(pi);
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003029 BT_DBG("sk %p, Exit SREJ_SENT", sk);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003030 }
3031 } else {
3032 struct srej_list *l;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003033
3034 /* duplicated tx_seq */
3035 if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
3036 goto drop;
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003037
3038 list_for_each_entry(l, SREJ_LIST(sk), list) {
3039 if (l->tx_seq == tx_seq) {
3040 l2cap_resend_srejframe(sk, tx_seq);
3041 return 0;
3042 }
3043 }
3044 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003045 }
3046 } else {
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003047 expected_tx_seq_offset =
3048 (pi->expected_tx_seq - pi->buffer_seq) % 64;
3049 if (expected_tx_seq_offset < 0)
3050 expected_tx_seq_offset += 64;
3051
3052 /* duplicated tx_seq */
3053 if (tx_seq_offset < expected_tx_seq_offset)
3054 goto drop;
3055
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003056 pi->conn_state |= L2CAP_CONN_SREJ_SENT;
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003057
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003058 BT_DBG("sk %p, Enter SREJ", sk);
3059
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003060 INIT_LIST_HEAD(SREJ_LIST(sk));
3061 pi->buffer_seq_srej = pi->buffer_seq;
3062
3063 __skb_queue_head_init(SREJ_QUEUE(sk));
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003064 __skb_queue_head_init(BUSY_QUEUE(sk));
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003065 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3066
Gustavo F. Padovanef54fd92009-08-20 22:26:04 -03003067 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
3068
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003069 l2cap_send_srejframe(sk, tx_seq);
Gustavo F. Padovan7fe9b292010-05-12 18:32:04 -03003070
3071 del_timer(&pi->ack_timer);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003072 }
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003073 return 0;
3074
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003075expected:
3076 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3077
3078 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
Gustavo F. Padovan3b1a9f32010-05-01 16:15:42 -03003079 bt_cb(skb)->tx_seq = tx_seq;
3080 bt_cb(skb)->sar = sar;
3081 __skb_queue_tail(SREJ_QUEUE(sk), skb);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003082 return 0;
3083 }
3084
Gustavo F. Padovan2ece3682010-06-16 17:21:44 -03003085 err = l2cap_push_rx_skb(sk, skb, rx_control);
3086 if (err < 0)
3087 return 0;
3088
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003089 if (rx_control & L2CAP_CTRL_FINAL) {
3090 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3091 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003092 else
3093 l2cap_retransmit_frames(sk);
Gustavo F. Padovan4ec10d92009-10-03 02:34:39 -03003094 }
3095
Gustavo F. Padovanc1b4f432010-05-01 16:15:39 -03003096 __mod_ack_timer();
3097
Gustavo F. Padovan803020c2010-05-01 16:15:41 -03003098 pi->num_acked = (pi->num_acked + 1) % num_to_ack;
3099 if (pi->num_acked == num_to_ack - 1)
Gustavo F. Padovan9e917af2010-05-01 16:15:37 -03003100 l2cap_send_ack(pi);
3101
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003102 return 0;
João Paulo Rechi Vita9b533502010-05-01 16:15:44 -03003103
3104drop:
3105 kfree_skb(skb);
3106 return 0;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003107}
3108
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003109static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003110{
3111 struct l2cap_pinfo *pi = l2cap_pi(sk);
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003112
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003113 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
3114 rx_control);
3115
Gustavo F. Padovan6e3a5982010-05-01 16:15:38 -03003116 pi->expected_ack_seq = __get_reqseq(rx_control);
3117 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003118
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003119 if (rx_control & L2CAP_CTRL_POLL) {
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003120 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003121 if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
3122 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3123 (pi->unacked_frames > 0))
3124 __mod_retrans_timer();
3125
3126 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3127 l2cap_send_srejtail(sk);
3128 } else {
3129 l2cap_send_i_or_rr_or_rnr(sk);
Gustavo F. Padovan05fbd892010-05-01 16:15:39 -03003130 }
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003131
3132 } else if (rx_control & L2CAP_CTRL_FINAL) {
3133 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003134
3135 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3136 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003137 else
3138 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003139
3140 } else {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003141 if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
3142 (pi->unacked_frames > 0))
3143 __mod_retrans_timer();
3144
3145 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003146 if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003147 l2cap_send_ack(pi);
Andrei Emeltchenko894718a2010-12-01 16:58:24 +02003148 else
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003149 l2cap_ertm_send(sk);
3150 }
3151}
3152
3153static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
3154{
3155 struct l2cap_pinfo *pi = l2cap_pi(sk);
3156 u8 tx_seq = __get_reqseq(rx_control);
3157
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003158 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3159
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003160 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3161
Gustavo F. Padovan8abb52e2010-05-01 16:15:38 -03003162 pi->expected_ack_seq = tx_seq;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003163 l2cap_drop_acked_frames(sk);
3164
3165 if (rx_control & L2CAP_CTRL_FINAL) {
3166 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3167 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003168 else
3169 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003170 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003171 l2cap_retransmit_frames(sk);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003172
Gustavo F. Padovan0301ef02010-05-05 20:56:43 -03003173 if (pi->conn_state & L2CAP_CONN_WAIT_F)
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003174 pi->conn_state |= L2CAP_CONN_REJ_ACT;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003175 }
3176}
3177static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
3178{
3179 struct l2cap_pinfo *pi = l2cap_pi(sk);
3180 u8 tx_seq = __get_reqseq(rx_control);
3181
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003182 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3183
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003184 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3185
3186 if (rx_control & L2CAP_CTRL_POLL) {
3187 pi->expected_ack_seq = tx_seq;
3188 l2cap_drop_acked_frames(sk);
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003189
3190 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003191 l2cap_retransmit_one_frame(sk, tx_seq);
3192
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003193 l2cap_ertm_send(sk);
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003194
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003195 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3196 pi->srej_save_reqseq = tx_seq;
3197 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3198 }
3199 } else if (rx_control & L2CAP_CTRL_FINAL) {
3200 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
3201 pi->srej_save_reqseq == tx_seq)
3202 pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
3203 else
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003204 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003205 } else {
Gustavo F. Padovandfc909b2010-05-01 16:15:45 -03003206 l2cap_retransmit_one_frame(sk, tx_seq);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003207 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3208 pi->srej_save_reqseq = tx_seq;
3209 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3210 }
3211 }
3212}
3213
3214static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
3215{
3216 struct l2cap_pinfo *pi = l2cap_pi(sk);
3217 u8 tx_seq = __get_reqseq(rx_control);
3218
Gustavo F. Padovan0e989582010-04-19 14:45:38 -03003219 BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
3220
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003221 pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
3222 pi->expected_ack_seq = tx_seq;
3223 l2cap_drop_acked_frames(sk);
3224
Gustavo F. Padovan3cb123d2010-05-29 02:24:35 -03003225 if (rx_control & L2CAP_CTRL_POLL)
3226 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
3227
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003228 if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
3229 del_timer(&pi->retrans_timer);
Gustavo F. Padovana2e12a22010-05-05 19:58:27 -03003230 if (rx_control & L2CAP_CTRL_POLL)
3231 l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003232 return;
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003233 }
Gustavo F. Padovan99b0d4b2010-05-01 16:15:38 -03003234
3235 if (rx_control & L2CAP_CTRL_POLL)
3236 l2cap_send_srejtail(sk);
3237 else
3238 l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003239}
3240
3241static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
3242{
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003243 BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
3244
Gustavo F. Padovan9b16dc62010-05-05 20:05:57 -03003245 if (L2CAP_CTRL_FINAL & rx_control &&
3246 l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003247 del_timer(&l2cap_pi(sk)->monitor_timer);
3248 if (l2cap_pi(sk)->unacked_frames > 0)
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003249 __mod_retrans_timer();
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003250 l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
Gustavo F. Padovan1d8f5d12010-05-01 16:15:37 -03003251 }
3252
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003253 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3254 case L2CAP_SUPER_RCV_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003255 l2cap_data_channel_rrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003256 break;
3257
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003258 case L2CAP_SUPER_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003259 l2cap_data_channel_rejframe(sk, rx_control);
Gustavo F. Padovan30afb5b2009-08-20 22:25:59 -03003260 break;
3261
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003262 case L2CAP_SUPER_SELECT_REJECT:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003263 l2cap_data_channel_srejframe(sk, rx_control);
Gustavo F. Padovan8f171542009-08-20 22:26:03 -03003264 break;
3265
3266 case L2CAP_SUPER_RCV_NOT_READY:
Gustavo F. Padovane0727452010-05-01 16:15:38 -03003267 l2cap_data_channel_rnrframe(sk, rx_control);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003268 break;
3269 }
3270
Gustavo F. Padovanfaaebd12010-05-01 16:15:35 -03003271 kfree_skb(skb);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003272 return 0;
3273}
3274
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003275static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3276{
3277 struct l2cap_pinfo *pi = l2cap_pi(sk);
3278 u16 control;
3279 u8 req_seq;
3280 int len, next_tx_seq_offset, req_seq_offset;
3281
3282 control = get_unaligned_le16(skb->data);
3283 skb_pull(skb, 2);
3284 len = skb->len;
3285
3286 /*
3287 * We can just drop the corrupted I-frame here.
3288 * Receiver will miss it and start proper recovery
3289 * procedures and ask retransmission.
3290 */
3291 if (l2cap_check_fcs(pi, skb))
3292 goto drop;
3293
3294 if (__is_sar_start(control) && __is_iframe(control))
3295 len -= 2;
3296
3297 if (pi->fcs == L2CAP_FCS_CRC16)
3298 len -= 2;
3299
3300 if (len > pi->mps) {
3301 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3302 goto drop;
3303 }
3304
3305 req_seq = __get_reqseq(control);
3306 req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
3307 if (req_seq_offset < 0)
3308 req_seq_offset += 64;
3309
3310 next_tx_seq_offset =
3311 (pi->next_tx_seq - pi->expected_ack_seq) % 64;
3312 if (next_tx_seq_offset < 0)
3313 next_tx_seq_offset += 64;
3314
3315 /* check for invalid req-seq */
3316 if (req_seq_offset > next_tx_seq_offset) {
3317 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3318 goto drop;
3319 }
3320
3321 if (__is_iframe(control)) {
3322 if (len < 0) {
3323 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3324 goto drop;
3325 }
3326
3327 l2cap_data_channel_iframe(sk, control, skb);
3328 } else {
3329 if (len != 0) {
3330 BT_ERR("%d", len);
3331 l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
3332 goto drop;
3333 }
3334
3335 l2cap_data_channel_sframe(sk, control, skb);
3336 }
3337
3338 return 0;
3339
3340drop:
3341 kfree_skb(skb);
3342 return 0;
3343}
3344
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
3346{
3347 struct sock *sk;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003348 struct l2cap_pinfo *pi;
Nathan Holstein51893f82010-06-09 15:46:25 -04003349 u16 control;
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003350 u8 tx_seq;
3351 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003352
3353 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
3354 if (!sk) {
3355 BT_DBG("unknown cid 0x%4.4x", cid);
3356 goto drop;
3357 }
3358
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003359 pi = l2cap_pi(sk);
3360
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361 BT_DBG("sk %p, len %d", sk, skb->len);
3362
3363 if (sk->sk_state != BT_CONNECTED)
3364 goto drop;
3365
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003366 switch (pi->mode) {
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003367 case L2CAP_MODE_BASIC:
3368 /* If socket recv buffers overflows we drop data here
3369 * which is *bad* because L2CAP has to be reliable.
3370 * But we don't have any other choice. L2CAP doesn't
3371 * provide flow control mechanism. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003373 if (pi->imtu < skb->len)
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003374 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003376 if (!sock_queue_rcv_skb(sk, skb))
3377 goto done;
3378 break;
3379
3380 case L2CAP_MODE_ERTM:
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003381 if (!sock_owned_by_user(sk)) {
3382 l2cap_ertm_data_rcv(sk, skb);
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003383 } else {
Gustavo F. Padovan218bb9d2010-06-21 18:53:22 -03003384 if (sk_add_backlog(sk, skb))
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003385 goto drop;
Gustavo F. Padovan277ffbe2010-05-01 16:15:37 -03003386 }
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003387
Andrei Emeltchenkofcafde22009-12-22 15:58:08 +02003388 goto done;
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003389
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003390 case L2CAP_MODE_STREAMING:
3391 control = get_unaligned_le16(skb->data);
3392 skb_pull(skb, 2);
3393 len = skb->len;
3394
Gustavo F. Padovan26000082010-05-11 22:02:00 -03003395 if (l2cap_check_fcs(pi, skb))
3396 goto drop;
3397
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003398 if (__is_sar_start(control))
3399 len -= 2;
3400
Gustavo F. Padovanfcc203c2009-08-20 22:26:02 -03003401 if (pi->fcs == L2CAP_FCS_CRC16)
3402 len -= 2;
3403
Nathan Holstein51893f82010-06-09 15:46:25 -04003404 if (len > pi->mps || len < 0 || __is_sframe(control))
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003405 goto drop;
3406
3407 tx_seq = __get_txseq(control);
3408
3409 if (pi->expected_tx_seq == tx_seq)
3410 pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
3411 else
Gustavo F. Padovan7dffe422010-05-01 16:15:36 -03003412 pi->expected_tx_seq = (tx_seq + 1) % 64;
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003413
Gustavo F. Padovan18778a62010-05-01 16:15:44 -03003414 l2cap_streaming_reassembly_sdu(sk, skb, control);
Gustavo F. Padovan6840ed02009-08-20 22:26:01 -03003415
3416 goto done;
3417
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003418 default:
Gustavo F. Padovane8235c62010-05-01 16:15:36 -03003419 BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003420 break;
3421 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422
3423drop:
3424 kfree_skb(skb);
3425
3426done:
Marcel Holtmann01394182006-07-03 10:02:46 +02003427 if (sk)
3428 bh_unlock_sock(sk);
3429
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430 return 0;
3431}
3432
Al Viro8e036fc2007-07-29 00:16:36 -07003433static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434{
3435 struct sock *sk;
3436
3437 sk = l2cap_get_sock_by_psm(0, psm, conn->src);
3438 if (!sk)
3439 goto drop;
3440
Gustavo F. Padovane0f0cb52010-11-01 18:43:53 +00003441 bh_lock_sock(sk);
3442
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443 BT_DBG("sk %p, len %d", sk, skb->len);
3444
3445 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
3446 goto drop;
3447
3448 if (l2cap_pi(sk)->imtu < skb->len)
3449 goto drop;
3450
3451 if (!sock_queue_rcv_skb(sk, skb))
3452 goto done;
3453
3454drop:
3455 kfree_skb(skb);
3456
3457done:
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003458 if (sk)
3459 bh_unlock_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460 return 0;
3461}
3462
3463static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
3464{
3465 struct l2cap_hdr *lh = (void *) skb->data;
Al Viro8e036fc2007-07-29 00:16:36 -07003466 u16 cid, len;
3467 __le16 psm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468
3469 skb_pull(skb, L2CAP_HDR_SIZE);
3470 cid = __le16_to_cpu(lh->cid);
3471 len = __le16_to_cpu(lh->len);
3472
Gustavo F. Padovan1c2acff2009-08-20 22:25:57 -03003473 if (len != skb->len) {
3474 kfree_skb(skb);
3475 return;
3476 }
3477
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478 BT_DBG("len %d, cid 0x%4.4x", len, cid);
3479
3480 switch (cid) {
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003481 case L2CAP_CID_SIGNALING:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482 l2cap_sig_channel(conn, skb);
3483 break;
3484
Gustavo F. Padovan8db4dc42009-04-20 01:31:05 -03003485 case L2CAP_CID_CONN_LESS:
Gustavo F. Padovan1b7bf4e2009-08-24 00:45:20 -03003486 psm = get_unaligned_le16(skb->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487 skb_pull(skb, 2);
3488 l2cap_conless_channel(conn, psm, skb);
3489 break;
3490
3491 default:
3492 l2cap_data_channel(conn, cid, skb);
3493 break;
3494 }
3495}
3496
3497/* ---- L2CAP interface with lower layer (HCI) ---- */
3498
3499static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
3500{
3501 int exact = 0, lm1 = 0, lm2 = 0;
3502 register struct sock *sk;
3503 struct hlist_node *node;
3504
3505 if (type != ACL_LINK)
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003506 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507
3508 BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
3509
3510 /* Find listening sockets and check their link_mode */
3511 read_lock(&l2cap_sk_list.lock);
3512 sk_for_each(sk, node, &l2cap_sk_list.head) {
3513 if (sk->sk_state != BT_LISTEN)
3514 continue;
3515
3516 if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003517 lm1 |= HCI_LM_ACCEPT;
3518 if (l2cap_pi(sk)->role_switch)
3519 lm1 |= HCI_LM_MASTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520 exact++;
Marcel Holtmann2af6b9d2009-01-15 21:58:38 +01003521 } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
3522 lm2 |= HCI_LM_ACCEPT;
3523 if (l2cap_pi(sk)->role_switch)
3524 lm2 |= HCI_LM_MASTER;
3525 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526 }
3527 read_unlock(&l2cap_sk_list.lock);
3528
3529 return exact ? lm1 : lm2;
3530}
3531
3532static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
3533{
Marcel Holtmann01394182006-07-03 10:02:46 +02003534 struct l2cap_conn *conn;
3535
Linus Torvalds1da177e2005-04-16 15:20:36 -07003536 BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
3537
Ville Tervoacd7d372011-02-10 22:38:49 -03003538 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003539 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003540
3541 if (!status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542 conn = l2cap_conn_add(hcon, status);
3543 if (conn)
3544 l2cap_conn_ready(conn);
Marcel Holtmann01394182006-07-03 10:02:46 +02003545 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003546 l2cap_conn_del(hcon, bt_err(status));
3547
3548 return 0;
3549}
3550
Marcel Holtmann2950f212009-02-12 14:02:50 +01003551static int l2cap_disconn_ind(struct hci_conn *hcon)
3552{
3553 struct l2cap_conn *conn = hcon->l2cap_data;
3554
3555 BT_DBG("hcon %p", hcon);
3556
3557 if (hcon->type != ACL_LINK || !conn)
3558 return 0x13;
3559
3560 return conn->disc_reason;
3561}
3562
3563static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564{
3565 BT_DBG("hcon %p reason %d", hcon, reason);
3566
Ville Tervoacd7d372011-02-10 22:38:49 -03003567 if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
João Paulo Rechi Vita963cf682010-06-22 13:56:28 -03003568 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003569
3570 l2cap_conn_del(hcon, bt_err(reason));
Marcel Holtmann01394182006-07-03 10:02:46 +02003571
Linus Torvalds1da177e2005-04-16 15:20:36 -07003572 return 0;
3573}
3574
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003575static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
3576{
Gustavo F. Padovanbd3c9e22010-05-01 16:15:42 -03003577 if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
Marcel Holtmann255c7602009-02-04 21:07:19 +01003578 return;
3579
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003580 if (encrypt == 0x00) {
3581 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
3582 l2cap_sock_clear_timer(sk);
3583 l2cap_sock_set_timer(sk, HZ * 5);
3584 } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
3585 __l2cap_sock_close(sk, ECONNREFUSED);
3586 } else {
3587 if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
3588 l2cap_sock_clear_timer(sk);
3589 }
3590}
3591
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003592static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003593{
3594 struct l2cap_chan_list *l;
Marcel Holtmann40be4922008-07-14 20:13:50 +02003595 struct l2cap_conn *conn = hcon->l2cap_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003596 struct sock *sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597
Marcel Holtmann01394182006-07-03 10:02:46 +02003598 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003599 return 0;
Marcel Holtmann01394182006-07-03 10:02:46 +02003600
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601 l = &conn->chan_list;
3602
3603 BT_DBG("conn %p", conn);
3604
3605 read_lock(&l->lock);
3606
3607 for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
3608 bh_lock_sock(sk);
3609
Marcel Holtmann6a8d3012009-02-06 23:56:36 +01003610 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
3611 bh_unlock_sock(sk);
3612 continue;
3613 }
3614
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003615 if (!status && (sk->sk_state == BT_CONNECTED ||
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003616 sk->sk_state == BT_CONFIG)) {
Marcel Holtmannf62e4322009-01-15 21:58:44 +01003617 l2cap_check_encryption(sk, encrypt);
Marcel Holtmann9719f8a2008-07-14 20:13:45 +02003618 bh_unlock_sock(sk);
3619 continue;
3620 }
3621
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003622 if (sk->sk_state == BT_CONNECT) {
3623 if (!status) {
3624 struct l2cap_conn_req req;
3625 req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
3626 req.psm = l2cap_pi(sk)->psm;
3627
3628 l2cap_pi(sk)->ident = l2cap_get_ident(conn);
Andrei Emeltchenkoe501d052010-07-08 12:14:41 +03003629 l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003630
3631 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3632 L2CAP_CONN_REQ, sizeof(req), &req);
3633 } else {
3634 l2cap_sock_clear_timer(sk);
3635 l2cap_sock_set_timer(sk, HZ / 10);
3636 }
3637 } else if (sk->sk_state == BT_CONNECT2) {
3638 struct l2cap_conn_rsp rsp;
3639 __u16 result;
3640
3641 if (!status) {
3642 sk->sk_state = BT_CONFIG;
3643 result = L2CAP_CR_SUCCESS;
3644 } else {
3645 sk->sk_state = BT_DISCONN;
3646 l2cap_sock_set_timer(sk, HZ / 10);
3647 result = L2CAP_CR_SEC_BLOCK;
3648 }
3649
3650 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
3651 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
3652 rsp.result = cpu_to_le16(result);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +02003653 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003654 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
3655 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656 }
3657
Linus Torvalds1da177e2005-04-16 15:20:36 -07003658 bh_unlock_sock(sk);
3659 }
3660
3661 read_unlock(&l->lock);
Marcel Holtmannb1235d72008-07-14 20:13:54 +02003662
Linus Torvalds1da177e2005-04-16 15:20:36 -07003663 return 0;
3664}
3665
3666static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
3667{
3668 struct l2cap_conn *conn = hcon->l2cap_data;
3669
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +02003670 if (!conn)
3671 conn = l2cap_conn_add(hcon, 0);
3672
3673 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674 goto drop;
3675
3676 BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
3677
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +02003678 if (!(flags & ACL_CONT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679 struct l2cap_hdr *hdr;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003680 struct sock *sk;
3681 u16 cid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682 int len;
3683
3684 if (conn->rx_len) {
3685 BT_ERR("Unexpected start frame (len %d)", skb->len);
3686 kfree_skb(conn->rx_skb);
3687 conn->rx_skb = NULL;
3688 conn->rx_len = 0;
3689 l2cap_conn_unreliable(conn, ECOMM);
3690 }
3691
Andrei Emeltchenkoaae7fe22010-09-15 14:28:43 +03003692 /* Start fragment always begin with Basic L2CAP header */
3693 if (skb->len < L2CAP_HDR_SIZE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694 BT_ERR("Frame is too short (len %d)", skb->len);
3695 l2cap_conn_unreliable(conn, ECOMM);
3696 goto drop;
3697 }
3698
3699 hdr = (struct l2cap_hdr *) skb->data;
3700 len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003701 cid = __le16_to_cpu(hdr->cid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702
3703 if (len == skb->len) {
3704 /* Complete frame received */
3705 l2cap_recv_frame(conn, skb);
3706 return 0;
3707 }
3708
3709 BT_DBG("Start: total len %d, frag len %d", len, skb->len);
3710
3711 if (skb->len > len) {
3712 BT_ERR("Frame is too long (len %d, expected len %d)",
3713 skb->len, len);
3714 l2cap_conn_unreliable(conn, ECOMM);
3715 goto drop;
3716 }
3717
Andrei Emeltchenko89794812010-09-15 14:28:44 +03003718 sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
3719
3720 if (sk && l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
3721 BT_ERR("Frame exceeding recv MTU (len %d, MTU %d)",
3722 len, l2cap_pi(sk)->imtu);
3723 bh_unlock_sock(sk);
3724 l2cap_conn_unreliable(conn, ECOMM);
3725 goto drop;
3726 }
3727
3728 if (sk)
3729 bh_unlock_sock(sk);
3730
Linus Torvalds1da177e2005-04-16 15:20:36 -07003731 /* Allocate skb for the complete frame (with header) */
Gustavo F. Padovanaf05b30b2009-04-20 01:31:08 -03003732 conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
3733 if (!conn->rx_skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003734 goto drop;
3735
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003736 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003737 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003738 conn->rx_len = len - skb->len;
3739 } else {
3740 BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
3741
3742 if (!conn->rx_len) {
3743 BT_ERR("Unexpected continuation frame (len %d)", skb->len);
3744 l2cap_conn_unreliable(conn, ECOMM);
3745 goto drop;
3746 }
3747
3748 if (skb->len > conn->rx_len) {
3749 BT_ERR("Fragment is too long (len %d, expected %d)",
3750 skb->len, conn->rx_len);
3751 kfree_skb(conn->rx_skb);
3752 conn->rx_skb = NULL;
3753 conn->rx_len = 0;
3754 l2cap_conn_unreliable(conn, ECOMM);
3755 goto drop;
3756 }
3757
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03003758 skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
Marcel Holtmanne1027a72009-02-09 09:18:02 +01003759 skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760 conn->rx_len -= skb->len;
3761
3762 if (!conn->rx_len) {
3763 /* Complete frame received */
3764 l2cap_recv_frame(conn, conn->rx_skb);
3765 conn->rx_skb = NULL;
3766 }
3767 }
3768
3769drop:
3770 kfree_skb(skb);
3771 return 0;
3772}
3773
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003774static int l2cap_debugfs_show(struct seq_file *f, void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775{
3776 struct sock *sk;
3777 struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778
3779 read_lock_bh(&l2cap_sk_list.lock);
3780
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003781 sk_for_each(sk, node, &l2cap_sk_list.head) {
3782 struct l2cap_pinfo *pi = l2cap_pi(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003783
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02003784 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 +01003785 batostr(&bt_sk(sk)->src),
3786 batostr(&bt_sk(sk)->dst),
3787 sk->sk_state, __le16_to_cpu(pi->psm),
3788 pi->scid, pi->dcid,
Gustavo F. Padovan903d3432011-02-10 14:16:06 -02003789 pi->imtu, pi->omtu, pi->sec_level,
3790 pi->mode);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003791 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003792
Linus Torvalds1da177e2005-04-16 15:20:36 -07003793 read_unlock_bh(&l2cap_sk_list.lock);
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003794
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003795 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796}
3797
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003798static int l2cap_debugfs_open(struct inode *inode, struct file *file)
3799{
3800 return single_open(file, l2cap_debugfs_show, inode->i_private);
3801}
3802
3803static const struct file_operations l2cap_debugfs_fops = {
3804 .open = l2cap_debugfs_open,
3805 .read = seq_read,
3806 .llseek = seq_lseek,
3807 .release = single_release,
3808};
3809
3810static struct dentry *l2cap_debugfs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003811
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812static struct hci_proto l2cap_hci_proto = {
3813 .name = "L2CAP",
3814 .id = HCI_PROTO_L2CAP,
3815 .connect_ind = l2cap_connect_ind,
3816 .connect_cfm = l2cap_connect_cfm,
3817 .disconn_ind = l2cap_disconn_ind,
Marcel Holtmann2950f212009-02-12 14:02:50 +01003818 .disconn_cfm = l2cap_disconn_cfm,
Marcel Holtmann8c1b2352009-01-15 21:58:04 +01003819 .security_cfm = l2cap_security_cfm,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003820 .recv_acldata = l2cap_recv_acldata
3821};
3822
Gustavo F. Padovan64274512011-02-07 20:08:52 -02003823int __init l2cap_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824{
3825 int err;
Marcel Holtmannbe9d1222005-11-08 09:57:38 -08003826
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02003827 err = l2cap_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828 if (err < 0)
3829 return err;
3830
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003831 _busy_wq = create_singlethread_workqueue("l2cap");
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04003832 if (!_busy_wq) {
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02003833 err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003834 goto error;
3835 }
3836
3837 err = hci_register_proto(&l2cap_hci_proto);
3838 if (err < 0) {
3839 BT_ERR("L2CAP protocol registration failed");
3840 bt_sock_unregister(BTPROTO_L2CAP);
3841 goto error;
3842 }
3843
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003844 if (bt_debugfs) {
3845 l2cap_debugfs = debugfs_create_file("l2cap", 0444,
3846 bt_debugfs, NULL, &l2cap_debugfs_fops);
3847 if (!l2cap_debugfs)
3848 BT_ERR("Failed to create L2CAP debug file");
3849 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003850
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851 BT_INFO("L2CAP socket layer initialized");
3852
3853 return 0;
3854
3855error:
Anderson Lizardob78d7b4f2010-11-29 12:15:50 -04003856 destroy_workqueue(_busy_wq);
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02003857 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858 return err;
3859}
3860
Gustavo F. Padovan64274512011-02-07 20:08:52 -02003861void l2cap_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862{
Marcel Holtmannaef7d972010-03-21 05:27:45 +01003863 debugfs_remove(l2cap_debugfs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864
Gustavo F. Padovan1890d362010-05-01 16:15:44 -03003865 flush_workqueue(_busy_wq);
3866 destroy_workqueue(_busy_wq);
3867
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868 if (hci_unregister_proto(&l2cap_hci_proto) < 0)
3869 BT_ERR("L2CAP protocol unregistration failed");
3870
Gustavo F. Padovanbb58f742011-02-03 20:50:35 -02003871 l2cap_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872}
3873
Gustavo F. Padovand1c4a172010-07-18 16:25:54 -03003874module_param(disable_ertm, bool, 0644);
3875MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");